From 446b5074dba9fbdee3158578c5c242ec6af7e931 Mon Sep 17 00:00:00 2001 From: James Thompson Date: Thu, 5 Nov 2026 23:24:43 -0500 Subject: [PATCH 01/12] feat(art): ask whether a build's index file is still on disk Spec 039 Phase 1 (FR-1, decision 4): MTG::Art::Index.file?(name) and MTG::ArtBuild#index_file_present?, plus the art_index_name spec helper. Co-Authored-By: Claude Sonnet 5.5 --- app/models/mtg/art/index.rb | 5 +++++ app/models/mtg/art_build.rb | 4 ++++ spec/models/mtg/art/index_spec.rb | 15 +++++++++++++++ spec/models/mtg/art_build_spec.rb | 9 +++++++++ spec/support/art_helpers.rb | 8 ++++++++ 5 files changed, 41 insertions(+) diff --git a/app/models/mtg/art/index.rb b/app/models/mtg/art/index.rb index 76b27399..e6c88543 100644 --- a/app/models/mtg/art/index.rb +++ b/app/models/mtg/art/index.rb @@ -25,6 +25,11 @@ def self.current = files.first def self.built_for?(catalog_version) = files.any? { it.basename.to_s.start_with?("art-index-#{catalog_version}-#{MTG::Art::Settings.digest}-") } + # True when a file of exactly this name is in the index directory (spec 039 decision 4). The name must be one this + # class writes, so nothing outside the directory is looked at; the file isn't opened. A blank name, a name of another + # shape and a directory that can't be examined are all "not there". + def self.file?(name) = NAME.match?(name.to_s) && dir.join(name.to_s).file? + # Only the current or previous index, by its exact name; anything else is nil (AC-4.2). def self.path_for(name) = NAME.match?(name.to_s) ? files.first(KEEP).find { it.basename.to_s == name } : nil diff --git a/app/models/mtg/art_build.rb b/app/models/mtg/art_build.rb index 891fb501..73be610c 100644 --- a/app/models/mtg/art_build.rb +++ b/app/models/mtg/art_build.rb @@ -71,6 +71,10 @@ def stalled_minutes = ((Time.current - heartbeat_at) / 60).floor # the first two ask #stalled? before it. def left_behind?(queue) = stale? || (quiet? && job_ended?(queue)) + # Whether the index file this build wrote is still on the volume (spec 039). The row and the file can disagree after + # a restore (a backup holds the database only) or when the directory was lost. + def index_file_present? = MTG::Art::Index.file?(index_file) + def counts = COUNTS.index_with { |name| public_send(:"#{name}_count") } private diff --git a/spec/models/mtg/art/index_spec.rb b/spec/models/mtg/art/index_spec.rb index e9086a8d..d0a74196 100644 --- a/spec/models/mtg/art/index_spec.rb +++ b/spec/models/mtg/art/index_spec.rb @@ -41,4 +41,19 @@ described_class.write!("v1", records) expect([ described_class.built_for?("v1"), described_class.built_for?("v2") ]).to eq([ true, false ]) end + + it "knows whether a file of its name is there (spec 039 decision 4)", :aggregate_failures do + path = described_class.write!("default-cards-1", []) + expect(described_class.file?(path.basename.to_s)).to be(true) + [ "art-index-default-cards-1-0123456789abcdef-3.bin.gz", nil, "", "art-index-upgrade.bin.gz", "../../config/master.key" ].each do |name| + expect(described_class.file?(name)).to be(false), "expected #{name.inspect} to be missing" + end + + path.delete + expect(described_class.file?(path.basename.to_s)).to be(false) + + described_class.write!("default-cards-1", []) + FileUtils.rm_rf(MTG::Art.root) + expect(described_class.file?(path.basename.to_s)).to be(false) + end end diff --git a/spec/models/mtg/art_build_spec.rb b/spec/models/mtg/art_build_spec.rb index f01ed8b1..534294ab 100644 --- a/spec/models/mtg/art_build_spec.rb +++ b/spec/models/mtg/art_build_spec.rb @@ -242,4 +242,13 @@ def running(**attributes) = create(:mtg_art_build, status: "running", finished_a create(:mtg_art_build, status: "skipped", started_at: 1.hour.ago) expect(described_class.latest).to eq(finished) end + + describe "#index_file_present?" do + it "is true only while the file the build names is in the index directory (spec 039)", :aggregate_failures, :art_matching do + expect(build(:mtg_art_build, index_file: art_index_name)).to be_index_file_present + expect(build(:mtg_art_build, index_file: "art-index-default-cards-1-0123456789abcdef-9.bin.gz")).not_to be_index_file_present + expect(build(:mtg_art_build, index_file: nil)).not_to be_index_file_present + expect(build(:mtg_art_build, index_file: "../x")).not_to be_index_file_present + end + end end diff --git a/spec/support/art_helpers.rb b/spec/support/art_helpers.rb index 255bbf33..0d205095 100644 --- a/spec/support/art_helpers.rb +++ b/spec/support/art_helpers.rb @@ -11,3 +11,11 @@ FileUtils.rm_rf(MTG::Art.root) end end + +# A finished build's index file: writes an index for the version and returns its name, to set as the build's index_file +# (spec 039). A bare finished build row has none, which now reads as "index file missing". +module ArtIndexHelpers + def art_index_name(version = "default-cards-1") = MTG::Art::Index.write!(version, []).basename.to_s +end + +RSpec.configure { |config| config.include ArtIndexHelpers } From f73f537bf5127e64cdde48535d9a077eb8214dd4 Mon Sep 17 00:00:00 2001 From: James Thompson Date: Thu, 5 Nov 2026 23:26:42 -0500 Subject: [PATCH 02/12] fix(art): the art index panel says when a finished build's index file is missing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Spec 039 Phase 2 (Story 1, FR-2): MTG::Art::Operation gains the :index_missing state, judged only for a finished latest build once nothing is in flight, with the summary "Index file missing. Build the art index again." and the facts of decision 2. Existing "Ready." examples now write a real index file (art_index_name). Ruling: AC-1.5's "no file outside index/ is looked at" is proven by MTG::Art::Index.file? refusing any name that isn't NAME (Phase 1's example with ../../config/master.key); the operation example checks only the state and fact — stubbing a Pathname stat call would test the stub. Ruling: the AC-1.7 spy example lives in the "art matching off" context as the plan says; the plan's "not_to include Index file" check went into the AC-4.7 example, the one that reads facts. Co-Authored-By: Claude Sonnet 5.5 --- app/models/mtg/art/operation.rb | 28 +++++++--- spec/models/mtg/art/operation_spec.rb | 80 ++++++++++++++++++++++++++- spec/requests/admin/catalogs_spec.rb | 19 ++++++- 3 files changed, 113 insertions(+), 14 deletions(-) diff --git a/app/models/mtg/art/operation.rb b/app/models/mtg/art/operation.rb index b98bef95..ec53c7c1 100644 --- a/app/models/mtg/art/operation.rb +++ b/app/models/mtg/art/operation.rb @@ -3,9 +3,10 @@ # both by MTG::ArtBuild#stalled? and #left_behind?). The two differ only while the queue holds a build job that no # running build is being worked on by: one that waits, or one a worker has taken that hasn't opened its build yet. The # page then says "Queued." or "Queued to retry.", and the status line still describes the latest build (interrupted, -# ready or failed), or says that no build has run yet. +# ready, index file missing or failed), or says that no build has run yet. class MTG::Art::Operation < Catalog::Operation OFF = "Art matching is off. Set #{MTG::Art::ENV_NAME}=true to turn it on.".freeze + INDEX_MISSING = "Index file missing. Build the art index again.".freeze NEEDS_CATALOG = "Refresh the catalog first: the art index is built from its cards.".freeze # A restart that stops the worker in good order releases the job it holds: the queue runs it again, and it closes its # own build and carries on. After a crash or a kill the job stays held until the queue notices its worker is gone @@ -36,17 +37,19 @@ def build @build = MTG::ArtBuild.latest end - # :off, :queued, :building, :stalled, :interrupted, :never, :ready or :failed. A build still marked running that - # nothing is working on any more is interrupted: its heartbeat stopped 10 minutes ago, or 2 minutes ago and the queue - # has failed its job or no longer holds it (issue #73). One whose heartbeat stopped 10 minutes ago while a worker - # still holds its job is stalled instead (issue #79). + # :off, :queued, :building, :stalled, :interrupted, :never, :ready, :index_missing or :failed. A build still marked + # running that nothing is working on any more is interrupted: its heartbeat stopped 10 minutes ago, or 2 minutes ago + # and the queue has failed its job or no longer holds it (issue #73). One whose heartbeat stopped 10 minutes ago while + # a worker still holds its job is stalled instead (issue #79). A finished build whose index file isn't on the volume + # is :index_missing (spec 039); it is judged only once nothing is in flight or running, so the states above it win. def state @state ||= if !MTG::Art.enabled? then :off elsif build&.running? then running_state elsif queue.any? then :queued elsif build.nil? then :never - else build.finished? ? :ready : :failed + elsif build.finished? then build.index_file_present? ? :ready : :index_missing + else :failed end end @@ -64,6 +67,7 @@ def summary when :interrupted then "Interrupted. Build it again to carry on from where it stopped." when :never then catalog_loaded? ? "No build has run yet. One starts after the next catalog refresh, or you can start it here." : NEEDS_CATALOG when :ready then "Ready." + when :index_missing then INDEX_MISSING when :failed then failed_summary end end @@ -84,9 +88,7 @@ def facts when :building, :stalled, :interrupted [ fact("Started", build.started_at), fact("Images fetched", build.fetched_count), fact("Failed images", build.failed_count), fact("Last heartbeat", build.heartbeat_at, relative: true) ] - when :ready - [ fact("Finished", build.finished_at), fact("Artworks indexed", build.indexed_count), - fact("Without an image", build.without_image_count), fact("Failed images", build.failed_count) ] + when :ready, :index_missing then finished_facts when :failed then failed_facts else [] end @@ -114,6 +116,14 @@ def retrying? # Why the build failed in plain words, with the error it stored as the detail (issue #84). def failure = Catalog::FailureReason.for(build.message, collectible_type) + # What a finished build records, plus the file's name when that file is the point (spec 039 decision 2). + def finished_facts + [ fact("Finished", build.finished_at), + (fact("Index file", build.index_file.presence || "none recorded") if state == :index_missing), + fact("Artworks indexed", build.indexed_count), fact("Without an image", build.without_image_count), + fact("Failed images", build.failed_count) ].compact + end + def failed_summary = "Failed. #{failure.sentence}" def failed_facts diff --git a/spec/models/mtg/art/operation_spec.rb b/spec/models/mtg/art/operation_spec.rb index c6682e7a..3ee603c6 100644 --- a/spec/models/mtg/art/operation_spec.rb +++ b/spec/models/mtg/art/operation_spec.rb @@ -20,6 +20,15 @@ def quiet_build(job_id, **attributes) summary: "Art matching is off. Set COLLECTOR_MTG_ART_MATCHING=true to turn it on.") expect(operation.start).to be(false) end + + it "looks at no file, whatever the latest build names (spec 039 AC-1.7)", :aggregate_failures do + loaded + build(index_file: "art-index-default-cards-1-0123456789abcdef-9.bin.gz") + allow(MTG::Art::Index).to receive(:file?) + + expect(operation.state).to eq(:off) + expect(MTG::Art::Index).not_to have_received(:file?) + end end context "with art matching on", :art_matching do @@ -396,7 +405,7 @@ def stalled_build(**attributes) it "shows the build as it ended when the job finished before the queue was read" do loaded - quiet_build(job.active_job_id).finish!(:finished) + quiet_build(job.active_job_id, index_file: art_index_name).finish!(:finished) finish_job(job) expect(operation.state).to eq(:ready) @@ -405,11 +414,12 @@ def stalled_build(**attributes) it "shows a finished build's counts and finish time (AC-4.7)", :aggregate_failures do loaded - build(indexed_count: 31_904, without_image_count: 12, failed_count: 3) + build(index_file: art_index_name, indexed_count: 31_904, without_image_count: 12, failed_count: 3) expect(operation).to have_attributes(state: :ready, summary: "Ready.", meter: nil, startable?: true) expect(operation.facts.to_h { |fact| [ fact.label, fact.value ] }) .to include("Artworks indexed" => 31_904, "Without an image" => 12, "Failed images" => 3, "Finished" => be_a(Time)) + expect(operation.facts.map(&:label)).not_to include("Index file") end it "shows why a build failed, its error as the detail, and the index still in use (AC-4.8, issue #84)", :aggregate_failures do @@ -439,10 +449,74 @@ def stalled_build(**attributes) it "ignores a build skipped because another was running, as the status line does" do loaded - build(indexed_count: 9, started_at: 2.hours.ago) + build(index_file: art_index_name, indexed_count: 9, started_at: 2.hours.ago) build(status: "skipped", message: "already running", started_at: 1.hour.ago) expect(operation.state).to eq(:ready) end + + context "with a finished build whose index file is gone (spec 039)" do + let(:gone) { "art-index-default-cards-1-0123456789abcdef-9.bin.gz" } + + def facts = operation.facts.to_h { |fact| [ fact.label, fact.value ] } + + it "says the index file is missing, shows the build's facts and can be built again (AC-1.1, AC-1.2, AC-1.3)", :aggregate_failures do + loaded + build(index_file: gone, indexed_count: 9, without_image_count: 1, failed_count: 2) + + expect(operation).to have_attributes(state: :index_missing, summary: "Index file missing. Build the art index again.", + startable?: true, meter: nil, failed_job?: false, record_running?: false) + expect(operation.facts.map(&:label)).to eq([ "Finished", "Index file", "Artworks indexed", "Without an image", "Failed images" ]) + expect(facts).to include("Finished" => be_a(Time), "Index file" => gone, "Artworks indexed" => 9, "Without an image" => 1, + "Failed images" => 2) + end + + it "is ready while the named file is there (AC-1.4)", :aggregate_failures do + loaded + build(index_file: art_index_name) + + expect(operation).to have_attributes(state: :ready, summary: "Ready.") + end + + it "reads a row with no file name as missing, with none recorded (AC-1.5)", :aggregate_failures do + loaded + build(index_file: nil) + + expect(operation.state).to eq(:index_missing) + expect(facts["Index file"]).to eq("none recorded") + end + + it "reads a name of another shape as missing and shows it as stored (AC-1.5)", :aggregate_failures do + loaded + build(index_file: "../../x") + + expect(operation.state).to eq(:index_missing) + expect(facts["Index file"]).to eq("../../x") + end + + it "is queued while a build job waits (AC-1.6)" do + loaded + build(index_file: gone) + queue_job(MTG::Art::BuildJob) + + expect(operation.state).to eq(:queued) + end + + it "is building while a later build runs (AC-1.6)" do + loaded + build(index_file: gone, started_at: 2.hours.ago) + build(status: "running", finished_at: nil, heartbeat_at: 20.seconds.ago) + + expect(operation.state).to eq(:building) + end + + it "is failed, worded as before, when the latest build failed (AC-1.6, decision 6)", :aggregate_failures do + loaded + build(index_file: gone, started_at: 2.hours.ago) + build(status: "failed", message: "Errno::ENOSPC: No space left on device") + + expect(operation).to have_attributes(state: :failed, summary: "Failed. An unexpected error stopped it.") + end + end end end diff --git a/spec/requests/admin/catalogs_spec.rb b/spec/requests/admin/catalogs_spec.rb index 903029a8..46f40138 100644 --- a/spec/requests/admin/catalogs_spec.rb +++ b/spec/requests/admin/catalogs_spec.rb @@ -500,7 +500,8 @@ def running(**attributes) = create(:catalog_refresh_run, :running, **attributes) it "shows a finished build's counts (AC-4.7) and a failed one's message and index (AC-4.8)", :aggregate_failures, :art_matching do create(:catalog_refresh_run) - build = create(:mtg_art_build, indexed_count: 31_904, without_image_count: 12, failed_count: 3, finished_at: Time.utc(2026, 10, 9, 5, 0)) + name = art_index_name + build = create(:mtg_art_build, index_file: name, indexed_count: 31_904, without_image_count: 12, failed_count: 3, finished_at: Time.utc(2026, 10, 9, 5, 0)) get admin_catalog_path expect(text(section("art_index"))).to eq("Art index Build art index Ready. Finished 9 Oct 2026 05:00 UTC " \ "Artworks indexed 31,904 Without an image 12 Failed images 3") @@ -508,7 +509,21 @@ def running(**attributes) = create(:catalog_refresh_run, :running, **attributes) build.update!(status: "failed", message: "Errno::ENOSPC: No space left on device") get admin_catalog_path expect(text(section("art_index"))).to eq("Art index Build art index Failed. An unexpected error stopped it. " \ - "Finished 9 Oct 2026 05:00 UTC Index in use none Technical detail Errno::ENOSPC: No space left on device") + "Finished 9 Oct 2026 05:00 UTC Index in use #{name} Technical detail Errno::ENOSPC: No space left on device") + end + + it "says a finished build's index file is missing, with its facts and an enabled button, and doesn't poll (spec 039 AC-1.8)", :aggregate_failures, :art_matching do + create(:catalog_refresh_run) + create(:mtg_art_build, index_file: "art-index-default-cards-1-0123456789abcdef-31904.bin.gz", indexed_count: 31_904, + without_image_count: 12, failed_count: 3, finished_at: Time.utc(2026, 10, 9, 5, 0)) + + get admin_catalog_path + + expect(text(section("art_index"))).to eq("Art index Build art index Index file missing. Build the art index again. " \ + "Finished 9 Oct 2026 05:00 UTC Index file art-index-default-cards-1-0123456789abcdef-31904.bin.gz " \ + "Artworks indexed 31,904 Without an image 12 Failed images 3") + expect(section("art_index").at_css("button")["disabled"]).to be_nil + expect(page.at_css("[data-controller~='poll']")).to be_nil end end From 5712f67659203681dceb41e178bc67f6451d8d42 Mon Sep 17 00:00:00 2001 From: James Thompson Date: Thu, 5 Nov 2026 23:27:18 -0500 Subject: [PATCH 03/12] fix(art): catalog:status says when a finished build's index file is missing Spec 039 Phase 3 (Story 2, FR-3): MTG::Art.status_line reads a finished latest build without its file as "Art matching: index file missing (); press Build art index on the admin catalog page to write it again." with the build's counts, and "no file name recorded" for a row without a name. The ready line's example now writes a real index file. Co-Authored-By: Claude Sonnet 5.5 --- app/models/mtg/art.rb | 7 ++++++- spec/models/mtg/art_spec.rb | 17 ++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/app/models/mtg/art.rb b/app/models/mtg/art.rb index 3ce92e12..8ab3bd55 100644 --- a/app/models/mtg/art.rb +++ b/app/models/mtg/art.rb @@ -34,7 +34,8 @@ def self.after_refresh(run) # The art line `catalog:status[mtg]` prints (AC-3.11), from the latest build run that wasn't skipped. A build still # marked running reads as the admin catalog page words it (MTG::Art::Operation): building with no heartbeat while a # worker holds the job of a build that stopped beating (MTG::ArtBuild#stalled?), interrupted once nothing is working - # on it (MTG::ArtBuild#left_behind?), both judged by the queue as it was read before the build. + # on it (MTG::ArtBuild#left_behind?), both judged by the queue as it was read before the build. A finished build whose + # index file isn't on the volume reads as missing, and says to press the admin page's button (spec 039 decision 3). def self.status_line return "Art matching: off (set #{ENV_NAME}=true to turn it on)" unless enabled? @@ -52,6 +53,10 @@ def self.status_line elsif run.running? "Art matching: building since #{run.started_at.utc.iso8601}; #{progress}, #{run.failed_count} failed " \ "(last heartbeat #{run.heartbeat_at.utc.iso8601})" + elsif run.finished? && !run.index_file_present? + "Art matching: index file missing (#{run.index_file.presence || "no file name recorded"}); press Build art index on the " \ + "admin catalog page to write it again. #{run.indexed_count} artworks indexed, #{run.without_image_count} without an image, " \ + "#{run.failed_count} failed images" elsif run.finished? "Art matching: ready; #{run.indexed_count} artworks indexed, #{run.without_image_count} without an image, " \ "#{run.failed_count} failed images; index #{run.index_file}" diff --git a/spec/models/mtg/art_spec.rb b/spec/models/mtg/art_spec.rb index c7d62d77..f131d2ab 100644 --- a/spec/models/mtg/art_spec.rb +++ b/spec/models/mtg/art_spec.rb @@ -115,8 +115,23 @@ def refresh_run(status) = build(:catalog_refresh_run, collectible_type: "mtg", s end it "reports a finished build's counts and index", :art_matching do + name = art_index_name + create(:mtg_art_build, indexed_count: 9, without_image_count: 1, failed_count: 2, index_file: name) + expect(described_class.status_line).to include("ready", "9 artworks indexed", "1 without an image", "2 failed images", name) + end + + it "says the index file is missing, and what to press (spec 039 AC-2.1)", :aggregate_failures, :art_matching do create(:mtg_art_build, indexed_count: 9, without_image_count: 1, failed_count: 2, index_file: "art-index-v1-0123456789abcdef-9.bin.gz") - expect(described_class.status_line).to include("ready", "9 artworks indexed", "1 without an image", "2 failed images", "art-index-v1-0123456789abcdef-9.bin.gz") + line = described_class.status_line + expect(line).to start_with("Art matching: index file missing (art-index-v1-0123456789abcdef-9.bin.gz); press Build art index " \ + "on the admin catalog page to write it again.") + expect(line).to include("9 artworks indexed", "1 without an image", "2 failed images") + expect(line).not_to include("ready") + end + + it "says no file name was recorded for a finished build without one (spec 039 AC-2.1)", :art_matching do + create(:mtg_art_build, index_file: nil) + expect(described_class.status_line).to start_with("Art matching: index file missing (no file name recorded); ") end it "reports a failed build with its message and the index still in use", :art_matching do From 474ee493f4c7d2d6e28f1f2f042b46b297dc8ee6 Mon Sep 17 00:00:00 2001 From: James Thompson Date: Thu, 5 Nov 2026 23:28:13 -0500 Subject: [PATCH 04/12] test(art): building again after a missing index file restores ready Spec 039 Phase 4 (Story 3): AC-3.1 (request: the enabled button queues one MTG::Art::BuildJob; a guard, the controller is unchanged) and AC-3.2 (a second build after the art directory is emptied fetches no image, writes the same named file, and the panel and line read ready again). Against Phase 1's operation and status line the AC-3.2 example failed on :index_missing; the AC-1.8 example likewise. Ruling: AC-3.2 also asserts the rebuilt row names the same index_file as the first build, which pins "the named file now exists" to the name the missing state showed. Co-Authored-By: Claude Sonnet 5.5 --- spec/models/mtg/art/build_spec.rb | 16 ++++++++++++++++ spec/requests/admin/catalogs_spec.rb | 11 +++++++++++ 2 files changed, 27 insertions(+) diff --git a/spec/models/mtg/art/build_spec.rb b/spec/models/mtg/art/build_spec.rb index 8d6e255b..02ef792c 100644 --- a/spec/models/mtg/art/build_spec.rb +++ b/spec/models/mtg/art/build_spec.rb @@ -269,4 +269,20 @@ def self.decode(_path) = raise(Errno::ENOSPC) expect(run_build).to be_nil expect(MTG::ArtBuild.count).to eq(0) end + + it "writes a missing index file again without an image request, and reads ready again (spec 039 AC-3.2)", :aggregate_failures do + printing(art_a, released_on: Date.new(2005, 1, 1)) + serve("#{art_a}-2005-1") + name = run_build.index_file + FileUtils.rm_rf(MTG::Art.root) # the index and the cached image, as a restore onto a fresh volume leaves nothing + expect(MTG::Art::Operation.new("mtg").state).to eq(:index_missing) + expect(MTG::Art.status_line).to start_with("Art matching: index file missing") + + WebMock.reset! # no stub is left: a request would raise, and would be counted + expect(run_build(job_id: "job-2")).to have_attributes(status: "finished", fetched_count: 0, index_file: name) + expect(a_request(:any, /.*/)).not_to have_been_made + expect(MTG::Art::Index.dir.join(name)).to be_file + expect(MTG::Art::Operation.new("mtg").state).to eq(:ready) + expect(MTG::Art.status_line).to start_with("Art matching: ready") + end end diff --git a/spec/requests/admin/catalogs_spec.rb b/spec/requests/admin/catalogs_spec.rb index 46f40138..6c18188c 100644 --- a/spec/requests/admin/catalogs_spec.rb +++ b/spec/requests/admin/catalogs_spec.rb @@ -525,6 +525,17 @@ def running(**attributes) = create(:catalog_refresh_run, :running, **attributes) expect(section("art_index").at_css("button")["disabled"]).to be_nil expect(page.at_css("[data-controller~='poll']")).to be_nil end + + it "queues one build when Build art index is pressed with the index file missing (spec 039 AC-3.1)", :aggregate_failures, :art_matching do + create(:catalog_refresh_run) + create(:mtg_art_build, index_file: "art-index-default-cards-1-0123456789abcdef-9.bin.gz") + get admin_catalog_path + expect(section("art_index").at_css("button")["disabled"]).to be_nil + + start("art_index") + expect(flash[:notice]).to eq("Art index build queued.") + expect(SolidQueue::Job.where(class_name: "MTG::Art::BuildJob").count).to eq(1) + end end it "runs the same queries however many runs and jobs there are (NFR)", :aggregate_failures do From fa3a0f4b4621c9e1d332259aa4ad67768370acef Mon Sep 17 00:00:00 2001 From: James Thompson Date: Thu, 5 Nov 2026 23:29:43 -0500 Subject: [PATCH 05/12] docs(art): record that a missing index file no longer reads as ready (#122) Spec 039 Phase 5 (Story 4): catalog operations gains the "Index file missing" row, the status line's wording, the glossary's "Ready (art index)" and the accepted limit on judging by name only; release and deploy's open limit for #122 becomes the fixed behaviour and its Sources name spec 039; README's two restore steps say what the page and catalog:status read until Build art index is pressed; the specs index records the supersessions of 015 AC-4.1, 011 AC-3.11 and 030 decision 12 on both sides; the roadmap gets #122's Housekeeping line. Ruling: the 030 row's Superseded-by text sat in a seventh cell; it is moved into the sixth (Superseded by), as the plan says, and the 039 clause appended. The spec header already read Approved v1.0.1 on main, so that plan item needed no change. Co-Authored-By: Claude Sonnet 5.5 --- README.md | 4 ++-- docs/architecture/catalog-operations.md | 10 +++++++--- docs/architecture/release-and-deploy.md | 7 ++++--- docs/roadmap.md | 1 + docs/specs/README.md | 8 ++++---- 5 files changed, 18 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index a5662070..ef799901 100644 --- a/README.md +++ b/README.md @@ -429,7 +429,7 @@ Keep several, and delete old ones yourself. A restore needs a **new, empty volume** and runs **before the instance's first start**, as a one-off command in a container of the image you will run. It refuses a volume that already holds a Collector database (or the `-wal`, `-shm` or `-journal` file of one, or the queue, cache or cable database) and changes nothing: to restore over a running instance, restore onto a new volume and switch to it. It restores a backup taken by the same release or an older one, which the first start then migrates as any upgrade does; a backup from a newer release is refused. Use the image tag you run (`COLLECTOR_IMAGE`), and a release that has `backup:restore`. -A restore ends every session (everyone signs in again) and drops pending bulk-removal Undos and selections; no collection is lost. It leaves the art index file behind: with art matching on, press **Build art index** on the admin catalog page afterwards, which needs no downloads. +A restore ends every session (everyone signs in again) and drops pending bulk-removal Undos and selections; no collection is lost. It leaves the art index file behind: with art matching on, press **Build art index** on the admin catalog page afterwards, which needs no downloads. Until you do, that page and `catalog:status` read "Index file missing". **Docker Compose.** Create the volume without starting Collector, and find its real name (Compose prefixes the project's name; a different project name is a different, empty volume): @@ -478,7 +478,7 @@ bin/kamal setup --skip-push --version 0.1.0 Give the exact release as the tag: releases deploy by version, so no `latest` tag is on the server. This path is documented and its container command is tested in CI, but it hasn't been run through Kamal itself. -**After a restore**, before you hand the instance back: compare the counts the command printed (accounts, users, lots) with what you expect; start it; sign in; with art matching on press **Build art index**; check your settings (`COLLECTOR_*`) and your secret. +**After a restore**, before you hand the instance back: compare the counts the command printed (accounts, users, lots) with what you expect; start it; sign in; with art matching on press **Build art index** (until then the admin catalog page and `catalog:status` read "Index file missing"); check your settings (`COLLECTOR_*`) and your secret. **A damaged, cut-short or wrong file is refused** with a plain message and the volume is left as it was: a file still being copied, a file from another tool, a collector's export (use **Import collection** for that), a backup of a newer release, a snapshot that fails SQLite's integrity or foreign-key check. diff --git a/docs/architecture/catalog-operations.md b/docs/architecture/catalog-operations.md index 4f446a3d..d3d47ad2 100644 --- a/docs/architecture/catalog-operations.md +++ b/docs/architecture/catalog-operations.md @@ -33,6 +33,7 @@ How the catalog changes, and how admins start, watch and recover that work: the - **Left behind / interrupted:** a run still marked running that nothing works on any more; see States and transitions for the rules. On the pages and in `catalog:status` it reads "interrupted", and a starting job closes it as failed with the message `interrupted` (spec 015 Glossary, AC-3.2, AC-3.3, AC-3.9, AC-4.10; #60, #73). - **Waiting retry:** an unfinished job of the same operation (for a refresh, queued for the same type), other than the starting one, that the queue holds for a later time (spec 024 Problem Statement, decisions 3 and 5; `Catalog::Operation::Queue#waiting_to_retry?`). - **Starting job:** the job whose `Catalog::Refresh#call` or `MTG::Art::Build#call` is running the start guard (spec 024 Problem Statement). +- **Ready (art index):** the latest build not skipped is finished and the index file it names (`MTG::ArtBuild#index_file`) is in `storage/catalog/mtg/art/index/`. The file is judged by its name only: `MTG::Art::Index.file?` accepts only a name of the index's own shape (`MTG::Art::Index::NAME`), makes one `stat` per panel render or status line, and never opens or caches the file. A blank or other-shaped name, an absent directory and a volume that can't be examined all read as missing (spec 039 decisions 1 and 4; #122). - **Stages of a refresh:** download, sync, retire, index, in that order, shown as "Download", "Sync cards", "Retire missing cards", "Rebuild name index" (`Catalog::RefreshRun::STAGES`, `Catalog::RefreshOperation::STAGES`; spec 015 Glossary). - **Job states on the jobs pages:** Failed (failed, not retried or discarded), Running (claimed by a worker), Queued (ready, or blocked by a concurrency limit, marked "waiting"), Scheduled (due later, including retry waits); every job in every queue counts (spec 015 Glossary, AC-6.1, AC-6.2). - **Admin / member:** a signed-in user with or without `admin` (spec 015 Glossary). @@ -110,10 +111,11 @@ What the art index section shows (`MTG::Art::Operation`; spec 015 Story 4): | Building | "Building.", artworks fingerprinted of the total as a bar, images fetched, failed images, start time and last heartbeat; button disabled; the page polls (spec 015 AC-4.2, AC-4.10) | | Heartbeat older than `STALE_AFTER`, its job still claimed | "Building, no heartbeat for N minutes." with the advice "If it stays that way, restart the app. The build then carries on from where it stopped, or reads interrupted and can be built again.", the same bar and facts; button disabled whatever else waits; the page polls; no link to the Failed list (spec 015 AC-4.11; #79) | | Left behind | "Interrupted. Build it again to carry on from where it stopped.", the bar and facts, a link to the Failed list when its job is there; button enabled unless another build job is in flight, then "Queued." (spec 015 AC-4.10; #73) | -| Finished | "Ready.", finish time, artworks indexed, without an image, failed images (spec 015 AC-4.7) | +| Finished, its index file on the volume | "Ready.", finish time, artworks indexed, without an image, failed images (spec 015 AC-4.7; spec 039 AC-1.4) | +| Finished, its index file not on the volume | "Index file missing. Build the art index again.", finish time, the file's name ("none recorded" for a row without one), artworks indexed, without an image, failed images; button enabled unless a job is in flight; no meter, no link to the Failed list; the page doesn't poll. Judged only once nothing is queued or running, so those states win (spec 039 decisions 2 and 6; #122) | | Failed | "Failed. <plain sentence>", finish time, the index still in use (or "none"), "Technical detail", a link to the Failed list when a build job is there (spec 015 AC-4.8; #84) | -A start request while a build is in flight queues nothing and answers "An art index build is already queued or running."; one while it is unavailable answers with the reason (spec 015 AC-4.4, FR-3). `MTG::Art.status_line`, the art line of `catalog:status`, words a build the same way (off, no build yet, building, building with no heartbeat and "Restart the app if it stays that way; the build then carries on, or reads interrupted.", interrupted with the advice to run the refresh task, ready, failed with the stored message), except that it always describes the latest build, never "Queued." (spec 011 AC-3.11; spec 015 AC-4.1, AC-4.11). +A start request while a build is in flight queues nothing and answers "An art index build is already queued or running."; one while it is unavailable answers with the reason (spec 015 AC-4.4, FR-3). `MTG::Art.status_line`, the art line of `catalog:status`, words a build the same way (off, no build yet, building, building with no heartbeat and "Restart the app if it stays that way; the build then carries on, or reads interrupted.", interrupted with the advice to run the refresh task, ready, failed with the stored message), except that it always describes the latest build, never "Queued." (spec 011 AC-3.11; spec 015 AC-4.1, AC-4.11). A finished build whose file is missing reads `Art matching: index file missing (); press Build art index on the admin catalog page to write it again.` with its counts, "(no file name recorded)" for a row without a name, and never "ready"; since the line describes the latest build, it still says to press the button while a build job is queued (spec 039 decision 3; #122). Pressing it is the recovery: the build fingerprints only what lacks a fingerprint, so after a restore it fetches no image and writes the file again (spec 039 decision 5, AC-3.2; spec 030 AC-2.8). ### What the source does for a refresh (`MTG::Scryfall::Source`) @@ -188,6 +190,7 @@ Filter chips Failed (the default), Running, Queued and Scheduled, each with its - A host suspended long enough for the queue to fail a working job can show its run as interrupted until the worker next records progress (normally within 2 seconds, up to about 70 in a hung request); a refresh started in that window closes it and runs beside it. A working build can do the same while one image takes more than 90 seconds (spec 015 Error Scenarios). - When the database is too busy for a build to record its failure, or to open its run, the section reads "Building." or "Queued." with "Retrying at" instead of "Queued to retry" (spec 015 Error Scenarios). - A skipped manual refresh behind a scheduled job's retry may end as "already applied"; and if the waiting retry later fails for good, the skipped work waits for the next weekly refresh or an admin (spec 024 decision 1). +- A finished build is judged by its file's name only: a damaged file, or one built for older settings or an older catalog version, still reads "Ready." (spec 039 Non-Goals, maintainer ruling 2026-11-03). - [#77](https://github.com/plainprogrammer/Collector/issues/77): an admin can't start a refresh or build, or cancel the wait, while a rate-limited job waits to retry. - [#86](https://github.com/plainprogrammer/Collector/issues/86): rate-limit retries count over a job's whole life (`MAX_RETRIES`), so a long build that is rate limited four times fails, though it did work between them. - [#111](https://github.com/plainprogrammer/Collector/issues/111): the `poll` controller's pauses (hidden tab, busy Turbo, open menu) have no spec source; whether they are a rule waits for the maintainer's ruling. @@ -200,8 +203,9 @@ Filter chips Failed (the default), Running, Queued and Scheduled, each with its - [Spec 015](../specs/015-admin-catalog-and-jobs/spec.md): all. - [Spec 024](../specs/024-refresh-rate-limit-wait/spec.md): all. - [Spec 023](../specs/023-signed-out-catalog-browsing/spec.md) decision 7, for the visitor's not-loaded notice only. +- [Spec 039](../specs/039-art-index-missing-file/spec.md): all. - ADRs [0014](../adr/0014-hand-built-admin-jobs-console.md), [0015](../adr/0015-admin-progress-by-polling.md), [0018](../adr/0018-collectible-agnostic-catalog-core.md). -- Issues [#60](https://github.com/plainprogrammer/Collector/issues/60), [#61](https://github.com/plainprogrammer/Collector/issues/61), [#73](https://github.com/plainprogrammer/Collector/issues/73), [#74](https://github.com/plainprogrammer/Collector/issues/74), [#78](https://github.com/plainprogrammer/Collector/issues/78), [#79](https://github.com/plainprogrammer/Collector/issues/79), [#80](https://github.com/plainprogrammer/Collector/issues/80), [#81](https://github.com/plainprogrammer/Collector/issues/81), [#84](https://github.com/plainprogrammer/Collector/issues/84); open: [#41](https://github.com/plainprogrammer/Collector/issues/41), [#77](https://github.com/plainprogrammer/Collector/issues/77), [#86](https://github.com/plainprogrammer/Collector/issues/86), [#111](https://github.com/plainprogrammer/Collector/issues/111). +- Issues [#60](https://github.com/plainprogrammer/Collector/issues/60), [#61](https://github.com/plainprogrammer/Collector/issues/61), [#73](https://github.com/plainprogrammer/Collector/issues/73), [#74](https://github.com/plainprogrammer/Collector/issues/74), [#78](https://github.com/plainprogrammer/Collector/issues/78), [#79](https://github.com/plainprogrammer/Collector/issues/79), [#80](https://github.com/plainprogrammer/Collector/issues/80), [#81](https://github.com/plainprogrammer/Collector/issues/81), [#84](https://github.com/plainprogrammer/Collector/issues/84), [#122](https://github.com/plainprogrammer/Collector/issues/122); open: [#41](https://github.com/plainprogrammer/Collector/issues/41), [#77](https://github.com/plainprogrammer/Collector/issues/77), [#86](https://github.com/plainprogrammer/Collector/issues/86), [#111](https://github.com/plainprogrammer/Collector/issues/111). ## Distillation log diff --git a/docs/architecture/release-and-deploy.md b/docs/architecture/release-and-deploy.md index ede0cde7..ecf86d88 100644 --- a/docs/architecture/release-and-deploy.md +++ b/docs/architecture/release-and-deploy.md @@ -21,7 +21,7 @@ How Collector is built into an image, published, deployed and kept safe: the con - **Development environment** (stack, `bin/setup`, `bin/ci`, the Claude Code hooks, worktrees, dev ports, libvips in development) has no area doc; its facts stay in CLAUDE.md, where an agent needs them first (specs 001 stack, CI and hooks parts, 003, 014; spec 027 OD3 and D2). Those specs freeze with this area (see Sources). That includes which branches the pre-push hook runs `bin/ci checks` for (spec 035 decision 3, Story 3; `.claude/hooks/pre_push_ci.rb`, `lib/collector/push_scope.rb`); that it runs a `bin/ci` group at all is here. - **Data portability** ([data-portability.md](data-portability.md); specs 017, 022, 025, 026, 028, 029, 030): the export format, what a preview and an apply do, the file's content rules, and which of the export and the backup to use for what (spec 030 decision 11). The upload's size cap (`CollectionImport::MAX_BYTES`) and what an apply writes are there; the layers that refuse a body over 40 MB and the stored file's retention are here. -- **Catalog operations** ([catalog-operations.md](catalog-operations.md)): the weekly refresh (`config/recurring.yml`), the art index build that a restore asks the operator to press, and the wording of a finished build whose index file is missing ([#122](https://github.com/plainprogrammer/Collector/issues/122)). +- **Catalog operations** ([catalog-operations.md](catalog-operations.md)): the weekly refresh (`config/recurring.yml`), the art index build that a restore asks the operator to press, and the wording of a finished build whose index file is missing, which is what the admin page and `catalog:status` read after a restore until that build is pressed (spec 039; [#122](https://github.com/plainprogrammer/Collector/issues/122)). - **Tenancy and accounts** (no area doc yet; spec 004): the ownership rule behind `ActiveStorageGate` is here only as ADR 0022 states it. - **Scanner** (no area doc yet): the OCR engine is fetched and checksum-verified during the image build (`bin/fetch-ocr-engine`, spec 007, [ADR 0001](../adr/0001-browser-ocr-engine-and-asset-hosting.md)); how it is served is the scanner's. @@ -239,7 +239,7 @@ CI proves one release step of it: the previous release's published image, seeded - **Open (code and spec disagree):** spec 012 AC-3.3 reads "Given a pre-release tag such as `v1.0.0-rc.1` … Then the registry has `1.0.0-rc.1` and `latest`", which contradicts the same spec's Goals and FR-2 ("Move `latest` on a pre-release" is a must-not), ADR 0009's table, `docs/releasing.md` and the workflow, which publish the pre-release's own tag only: `type=semver,pattern={{version}}` is the only tag a pre-release matches in `ci.yml`, which names no `latest` tag (metadata-action's default adds `latest` only for a stable semver tag; no pre-release has been pushed yet to show it). This document records the workflow's behaviour as current. The spec isn't edited (spec 027 D4). Open for the maintainer; evidence waits for the first pre-release tag ([#21](https://github.com/plainprogrammer/Collector/issues/21)). - [#21](https://github.com/plainprogrammer/Collector/issues/21): three spec 012 criteria have no evidence yet: the major-only tag `1` published by the first `1.0.0` (AC-3.2), the first pre-release publishing only its own tag (AC-3.3), and a live `bin/kamal deploy --skip-push --version X.Y.Z` on a real server (AC-5.2). -- [#122](https://github.com/plainprogrammer/Collector/issues/122): after a restore, `catalog:status` and the admin panel say the art index is "ready" although its file was left behind; the documents tell the operator to press **Build art index** (spec 030 decision 12, AC-2.8). +- A restore leaves the art index file behind (spec 030 decision 3). Until **Build art index** is pressed, the admin panel reads "Index file missing. Build the art index again." and `catalog:status` "Art matching: index file missing …", no longer "ready"; the build fetches no image and writes the file again (spec 039, which fixed [#122](https://github.com/plainprogrammer/Collector/issues/122); spec 030 decision 12, AC-2.8). - **Provenance attestations and SBOMs** wait until the repository is public (ADR 0008; spec 012 Non-Goals). Retention of `sha-*` images, GitHub Releases and changelogs, a version shown in the app, and Dependabot for the base image are not built (spec 012 Non-Goals, Out of Scope; ADR 0009). - A pull request costs two builds on the private repository's Actions minutes, and so does every merge to `main`; the `main` channel can be throttled without changing release tags (ADR 0009 Consequences). If arm64 hosted runners are withdrawn, the matrix entry falls back to QEMU on `ubuntu-latest` as a plan change (ADR 0010). - An account removed by raw SQL leaves its stored upload's attachment row and file behind, which the sweep doesn't treat as an orphan; the application's own deletions run the callbacks (ADR 0022 Consequences; maintainer, 2026-10-20). @@ -262,10 +262,11 @@ CI proves one release step of it: the previous release's published image, seeded - [Spec 030](../specs/030-backup-restore/spec.md): all but decision 11 (the export versus the backup), which is data portability's (its decision 14 and AC-5.7 are superseded in part by spec 031 decision 7). - [Spec 031](../specs/031-upgrade-from-previous-release/spec.md): all. - [Spec 035](../specs/035-ci-shards/spec.md): decisions 2 and 4–8 (the `bin/ci` groups, the shards, the run-time log, the workflow's `checks`, `rspec` and `ci` jobs, the slowest examples) and Story 2; its decision 3 and Story 3 (which branches the pre-push hook runs `bin/ci checks` for) are covered by CLAUDE.md's Claude Code Hooks. It supersedes spec 001 AC-2.5 and Story 2's "CI passes" in part, and spec 031 AC-7.6, AC-8.5 and decision 2 in part. +- [Spec 039](../specs/039-art-index-missing-file/spec.md): what the admin page and `catalog:status` read after a restore leaves the art index file behind (the rules are catalog operations'). - [Spec 036](../specs/036-advisory-response/spec.md): all (the grouped security updates, the daily audit workflow and the response to a red audit; the criteria that need GitHub are evidenced in its `verification.md`). - ADRs [0008](../adr/0008-public-images-from-the-private-repository.md), [0009](../adr/0009-image-tags-and-release-channels.md), [0010](../adr/0010-native-multi-architecture-image-builds.md), [0011](../adr/0011-own-ghcr-cleanup-script.md), [0016](../adr/0016-sqlite-in-every-environment.md), [0022](../adr/0022-stored-import-upload-retention.md), [0024](../adr/0024-backup-with-vacuum-into.md); and, for the image's contents, [0012](../adr/0012-decode-art-images-with-imagemagick.md) and [0013](../adr/0013-active-storage-variants-with-vips.md). - Reference: [`docs/releasing.md`](../releasing.md), [`docs/backup-restore.md`](../backup-restore.md), `README.md` ("Self-hosting", "Backup and restore"). -- Issues [#31](https://github.com/plainprogrammer/Collector/issues/31) (local builds held the OCR engine twice; fixed, guarded by `bin/image-smoke` and `.dockerignore`), [#42](https://github.com/plainprogrammer/Collector/issues/42) (the upgrade proof), [#145](https://github.com/plainprogrammer/Collector/issues/145) (spike: where CI's time went, and the pre-push hook that stopped gating past its timeout; findings in spec 035's [research.md](../specs/035-ci-shards/research.md)), [#109](https://github.com/plainprogrammer/Collector/issues/109), [#132](https://github.com/plainprogrammer/Collector/issues/132) (actions pinned to SHAs) and [#164](https://github.com/plainprogrammer/Collector/issues/164) (the advisory response, spec 036); open: [#21](https://github.com/plainprogrammer/Collector/issues/21), [#122](https://github.com/plainprogrammer/Collector/issues/122). +- Issues [#31](https://github.com/plainprogrammer/Collector/issues/31) (local builds held the OCR engine twice; fixed, guarded by `bin/image-smoke` and `.dockerignore`), [#42](https://github.com/plainprogrammer/Collector/issues/42) (the upgrade proof), [#145](https://github.com/plainprogrammer/Collector/issues/145) (spike: where CI's time went, and the pre-push hook that stopped gating past its timeout; findings in spec 035's [research.md](../specs/035-ci-shards/research.md)), [#109](https://github.com/plainprogrammer/Collector/issues/109), [#132](https://github.com/plainprogrammer/Collector/issues/132) (actions pinned to SHAs), [#164](https://github.com/plainprogrammer/Collector/issues/164) (the advisory response, spec 036) and [#122](https://github.com/plainprogrammer/Collector/issues/122) (the art index read "ready" after a restore; fixed by spec 039); open: [#21](https://github.com/plainprogrammer/Collector/issues/21). ## Distillation log diff --git a/docs/roadmap.md b/docs/roadmap.md index c98b162d..28f42fcd 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -98,6 +98,7 @@ Taken between specs. - [#145](https://github.com/plainprogrammer/Collector/issues/145): spike: why `bin/ci` grew from minutes to 20–30, and why the pre-push hook stopped gating past its timeout. **Done 2026-10-31:** findings in [research.md](specs/035-ci-shards/research.md); the fixes in [#147](https://github.com/plainprogrammer/Collector/pull/147) (the parity example) and [#148](https://github.com/plainprogrammer/Collector/pull/148) (the hooks block on a timeout). - Spec 035, from #145: `bin/ci` groups, used by GitHub's RSpec shards and by the pre-push hook, which skips RSpec for a documentation-only branch. **Shipped 2026-11-01:** [spec 035](specs/035-ci-shards/spec.md), [PR #149](https://github.com/plainprogrammer/Collector/pull/149), with its verification, review fixes and four shards in a follow-up pull request; GitHub's verdict went from a median 348 s to 140 s. - [#164](https://github.com/plainprogrammer/Collector/issues/164): dependency advisories: Dependabot's security updates for the Ruby gems as one group, a daily scheduled run of both audits on `main`, and the response to a red audit written into the release-and-deploy area doc (found on 2026-11-03, when five Dependabot pull requests failed on advisories for gems that no Dependabot pull request covered). **Done 2026-11-03:** [spec 036](specs/036-advisory-response/spec.md), [PR #163](https://github.com/plainprogrammer/Collector/pull/163); the maintainer's post-merge checks are in its `verification.md`. +- [#122](https://github.com/plainprogrammer/Collector/issues/122): the art index panel and `catalog:status` say "ready" when the finished build's index file is missing (after a restore, or a lost directory). Done when its pull request merges: [spec 039](specs/039-art-index-missing-file/spec.md). ## Parked until after 1.0 diff --git a/docs/specs/README.md b/docs/specs/README.md index 1ae17dae..41705334 100644 --- a/docs/specs/README.md +++ b/docs/specs/README.md @@ -31,11 +31,11 @@ A plan is deleted from the tree in a commit of its own after its feature's pull | [008 Card Scanner Phase 2 Spike — Card Detection and Art Matching](008-card-scanner-phase-2-spike/spec.md) | Shipped | Scanner | present | | | | [009 Card Scanner — Confirm and Add, and Detection on the Photo Path](009-card-scanner-confirm-flow/spec.md) | Shipped | Scanner | present | 007 AC-1.7 and FR-1's "reachable by URL only", AC-3.2, AC-3.3, AC-3.10, AC-4.2, FR-1's "no tenant data", FR-3's "only recognised text", FR-4's "no finish" (its Supersedes list) | AC-2.1, AC-2.3, AC-2.4, AC-5.1, AC-5.2, AC-5.5, FR-3 and FR-5, art evidence: 011 (its Supersedes list). AC-8.2, the collection page head: 026 ("Add by number" before "Scan cards", which stays). The header's navigation for a collector: 029 (gains Locations after Scan, decision 8). Its lots merge by the identity of spec 004; the copies a scan adds are unplaced and join the unplaced lot: 032 (Story 7) | | [010 Card Scanner Art Spike — The Index on a Phone, and Art on Live Captures](010-card-scanner-art-spike/spec.md) | Shipped | Scanner | present | | | -| [011 Card Scanner — Art Matching on Live Capture](011-card-scanner-art-matching/spec.md) | Frozen in part: FR-2's build run, by [catalog operations](../architecture/catalog-operations.md) | Scanner; [catalog operations](../architecture/catalog-operations.md) (FR-2's build run) | present | 007 FR-3, match results sent (amended in place, 007 v2.2.0). 007 FR-6, measurement mode records art. 009 AC-2.1, AC-2.3, AC-2.4, AC-5.1, AC-5.2, AC-5.5, FR-3 and FR-5, art evidence (its Supersedes list) | AC-3.2, a build that starts while another build job's retry waits is skipped: 024 (AC-2.1). AC-3.2, AC-3.4, AC-3.6, AC-3.8, AC-3.11, the left-behind build and rate-limit waits: amended in place for #73, #74, #79 and #81 (v1.1.4–v1.3.0), stating spec 015's AC-4.10 and AC-4.11 | +| [011 Card Scanner — Art Matching on Live Capture](011-card-scanner-art-matching/spec.md) | Frozen in part: FR-2's build run, by [catalog operations](../architecture/catalog-operations.md) | Scanner; [catalog operations](../architecture/catalog-operations.md) (FR-2's build run) | present | 007 FR-3, match results sent (amended in place, 007 v2.2.0). 007 FR-6, measurement mode records art. 009 AC-2.1, AC-2.3, AC-2.4, AC-5.1, AC-5.2, AC-5.5, FR-3 and FR-5, art evidence (its Supersedes list) | AC-3.2, a build that starts while another build job's retry waits is skipped: 024 (AC-2.1). AC-3.2, AC-3.4, AC-3.6, AC-3.8, AC-3.11, the left-behind build and rate-limit waits: amended in place for #73, #74, #79 and #81 (v1.1.4–v1.3.0), stating spec 015's AC-4.10 and AC-4.11. AC-3.11, the art line says "ready" only when the file is there: 039 | | [012 Build and Publish Collector Images](012-ghcr-registry-publishing/spec.md) | Frozen, by [release and deploy](../architecture/release-and-deploy.md) | Release and deploy | retired in `a41bd089232414faafa7f6623b5e79d10997b8f6`; read it with `git show a41bd089232414faafa7f6623b5e79d10997b8f6^:docs/specs/012-ghcr-registry-publishing/plan.md` | 001's Compose file that builds the image from a checkout and Kamal's placeholder registry (FR-4, FR-5; AC-1.5, AC-5.1) | | | [013 Clean Up Untagged GHCR Package Versions](013-ghcr-untagged-cleanup/spec.md) | Frozen, by [release and deploy](../architecture/release-and-deploy.md) | Release and deploy | retired in `5a1e2eb43ff1b8c4b66ca24f3573f96013f64d2a`; read it with `git show 5a1e2eb43ff1b8c4b66ca24f3573f96013f64d2a^:docs/specs/013-ghcr-untagged-cleanup/plan.md` | | | | [014 Active Storage Variants with vips](014-active-storage-vips/spec.md) | Frozen, by [release and deploy](../architecture/release-and-deploy.md) | CLAUDE.md (R5); release and deploy (the image's libvips) | retired in `4691f7b64cbca464dae4c153f145a18f404e6f98`; read it with `git show 4691f7b64cbca464dae4c153f145a18f404e6f98^:docs/specs/014-active-storage-vips/plan.md` | | | -| [015 Admin Catalog Operations and Jobs](015-admin-catalog-and-jobs/spec.md) | Frozen, by [catalog operations](../architecture/catalog-operations.md) | [Catalog operations](../architecture/catalog-operations.md) | retired in `6c4dd4fb5c247d6aeb5739e3ae9e096345309d0e`; `git show 6c4dd4fb5c247d6aeb5739e3ae9e096345309d0e^:docs/specs/015-admin-catalog-and-jobs/plan.md` | 002 FR-4, the 6-hour "already running" rule (AC-3.3, AC-3.4). 002 AC-1.11 and 004 AC-6.5, the not-loaded notice (AC-1.1, AC-1.2) | AC-2.16, a run skipped for another job's retry: 024 (amended in place, v1.3.1). AC-3.3 and AC-4.10, the starting refresh or build is skipped while another job's retry waits: 024 (AC-1.7, AC-2.1). Glossary, AC-3.2, AC-3.3, AC-3.4, AC-3.9, AC-4.1, AC-4.10, AC-4.11, AC-4.12, AC-6.5, FR-1, FR-2 and Error Scenarios, left-behind runs and builds, attempts, queued to retry: amended in place for #60, #61, #73, #74, #79 and #80 (v1.2.0–v1.3.0) | +| [015 Admin Catalog Operations and Jobs](015-admin-catalog-and-jobs/spec.md) | Frozen, by [catalog operations](../architecture/catalog-operations.md) | [Catalog operations](../architecture/catalog-operations.md) | retired in `6c4dd4fb5c247d6aeb5739e3ae9e096345309d0e`; `git show 6c4dd4fb5c247d6aeb5739e3ae9e096345309d0e^:docs/specs/015-admin-catalog-and-jobs/plan.md` | 002 FR-4, the 6-hour "already running" rule (AC-3.3, AC-3.4). 002 AC-1.11 and 004 AC-6.5, the not-loaded notice (AC-1.1, AC-1.2) | AC-2.16, a run skipped for another job's retry: 024 (amended in place, v1.3.1). AC-3.3 and AC-4.10, the starting refresh or build is skipped while another job's retry waits: 024 (AC-1.7, AC-2.1). Glossary, AC-3.2, AC-3.3, AC-3.4, AC-3.9, AC-4.1, AC-4.10, AC-4.11, AC-4.12, AC-6.5, FR-1, FR-2 and Error Scenarios, left-behind runs and builds, attempts, queued to retry: amended in place for #60, #61, #73, #74, #79 and #80 (v1.2.0–v1.3.0). AC-4.1, the art index's states gain "index file missing": 039 | | [016 Do Scryfall's Terms Permit a Hosted Instance?](016-scryfall-hosting-terms/research.md) (research) | Shipped | Catalog core | none | | | | [017 Export Format](017-export-format/spec.md) | Frozen, by [data portability](../architecture/data-portability.md) | Data portability | retired in `d586ff6f117b878fcb40f718e07dd8b832dc0dbc`; `git show d586ff6f117b878fcb40f718e07dd8b832dc0dbc^:docs/specs/017-export-format/plan.md` | | Decision 14's last sentence, AC-3.3's expectation and its version-history sentence, the Out of Scope line on locations: 029 (locations make version 2, lots in locations version 3; ADR 0023). Lot identity (five values) and the consequences about a lot in a location: 032 (six values and format version 3) | | [018 Content Notice Footer](018-content-notice-footer/spec.md) | Shipped | Catalog core | present | 002 AC-3.2 and 004 AC-8.2, the card page's attribution: moved to the footer (FR-3) | | @@ -50,7 +50,7 @@ A plan is deleted from the tree in a commit of its own after its feature's pull | [027 Area Docs Hold the Current Architecture, Starting with Catalog Operations](027-architecture-area-docs/spec.md) | Shipped | All (the documentation process) | retired in `c1ef5f0138c6898ab171fe6315281e6fed5c86c2`; `git show c1ef5f0138c6898ab171fe6315281e6fed5c86c2^:docs/specs/027-architecture-area-docs/plan.md` | | | | [028 Apply an Import](028-apply-import/spec.md) | Frozen, by [data portability](../architecture/data-portability.md) and [release and deploy](../architecture/release-and-deploy.md) | Data portability; release and deploy (stored upload retention) | retired in `ee4c4fa40e2223e2d81299885f8a0cabe7771956`; `git show ee4c4fa40e2223e2d81299885f8a0cabe7771956^:docs/specs/028-apply-import/plan.md` | 025 decision 6, "never stored", for a file that can be applied (decision 10). 025 decision 9, one point: a price that does not fit the cents column is a problem row (1.3.4) | Inputs and Non-Goals (version 1 only), Terms, decision 2 (the fingerprint), decision 5 (replace, lots and the profile only), decision 6 (the checkbox), decision 7 and AC-1.8 (working state cleared only when a lot is written), decision 11 and the notice's counts, Story 6's round trip: 029 (decisions 10 and 11, Story 9). Terms, decision 2 (the plan and fingerprint), the lot upsert's key, the confirmation and the notice: 032 (reads versions 1 to 3; places in the plan and the fingerprint; a location is removed only with the lots in it). AC-6.4, the round trip of each valid example: 032 (AC-11.14, a version 1 or 2 example re-exports as version 3) | | [029 Manage Locations](029-manage-locations/spec.md) | Frozen, by [collection and lots](../architecture/collection-and-lots.md) and [data portability](../architecture/data-portability.md) | [Collection and lots](../architecture/collection-and-lots.md) (locations); [data portability](../architecture/data-portability.md) (export format version 2; the preview and the apply read versions 1 and 2 and cover locations); [design system](../design-system/README.md) (navigation) | retired in `88a52cf7f4b84562d40db23bf157de58fceab2c2`; `git show 88a52cf7f4b84562d40db23bf157de58fceab2c2^:docs/specs/029-manage-locations/plan.md` | ADR 0020 consequences (a lot in a location raises the format to version 3; locations make version 2; a new ADR records it). 017 decision 14, AC-3.3 and its version-history sentence; the format document's "Locations will add where each lot is kept" sentence. Roadmap item 10. 022 (writes version 2). 025 (reads versions 1 and 2; AC-3.2; Locations section). 028 (reads versions 1 and 2; the plan, fingerprint, confirmation, transaction and notice cover locations; decision 7 and AC-1.8 clear working state only when the apply writes lots). 022 decision 6 and 026 (More's rows gain Locations). 004, 009, 023 (the header gains Locations) | Decision 3 (removing a location never removes copies; its confirmation page), Non-Goals (counts per location): 032 (a location that holds copies can't be removed; the refusal page; counts on the locations page). Decision 10 (reads versions 1 and 2): 032 (reads 1 to 3). AC-9.15, the round trip of each valid example: 032 (AC-11.14, a version 1 or 2 example re-exports as version 3) | -| [030 Back Up and Restore an Instance](030-backup-restore/spec.md) | Frozen, by [data portability](../architecture/data-portability.md) and [release and deploy](../architecture/release-and-deploy.md) | Release and deploy (backup and restore commands, the procedure); data portability (the export-versus-backup guidance) | retired in `c8706d3f9b7eb33b9f13388be5a15bec33f3ce76`; `git show c8706d3f9b7eb33b9f13388be5a15bec33f3ce76^:docs/specs/030-backup-restore/plan.md` | | | decision 14 and AC-5.7, the newer-image leg: 031 (decision 7) | +| [030 Back Up and Restore an Instance](030-backup-restore/spec.md) | Frozen, by [data portability](../architecture/data-portability.md) and [release and deploy](../architecture/release-and-deploy.md) | Release and deploy (backup and restore commands, the procedure); data portability (the export-versus-backup guidance) | retired in `c8706d3f9b7eb33b9f13388be5a15bec33f3ce76`; `git show c8706d3f9b7eb33b9f13388be5a15bec33f3ce76^:docs/specs/030-backup-restore/plan.md` | | decision 14 and AC-5.7, the newer-image leg: 031 (decision 7). Decision 12, "not fixed here" (fixed): 039 | | [031 Prove an Upgrade from the Previous Release in CI](031-upgrade-from-previous-release/spec.md) | Frozen, by [release and deploy](../architecture/release-and-deploy.md) | [Release and deploy](../architecture/release-and-deploy.md) (the upgrade proof, the release steps); data portability (none: no collector-owned data) | retired in `224105d82730320af5e64e726dfc653f6920e402`; `git show 224105d82730320af5e64e726dfc653f6920e402^:docs/specs/031-upgrade-from-previous-release/plan.md` | 030 decision 14 and AC-5.7, the newer-image leg: automated where the previous release has the backup task. Delivers the proof 030 left owed to #42 | AC-7.6, AC-8.5 and decision 2 in part, the guard and the full-history checkout in the `ci` job: 035 (decision 5) | | [032 Put a Lot in a Location](032-lot-in-a-location/spec.md) | Frozen, by [collection and lots](../architecture/collection-and-lots.md) and [data portability](../architecture/data-portability.md) | [Collection and lots](../architecture/collection-and-lots.md) (a lot's location, moving copies); [data portability](../architecture/data-portability.md) (export format version 3; the preview and the apply cover places); [design system](../design-system/README.md) (the card page) | retired in `91700487e563dd2821dc5cb5ea294f0af104061e`; `git show 91700487e563dd2821dc5cb5ea294f0af104061e^:docs/specs/032-lot-in-a-location/plan.md` | ADR 0019 (the open question for locations) and ADR 0023 (deleting a location; its "reads versions 1 and 2" bullet). 004 FR-6, AC-7.4, AC-9.3, AC-10.2, the add and edit forms and the card page's Your copies table. 006 (bulk Set condition and Undo keep places). 009, 026 (their copies are unplaced). 017 (lot identity, a lot in a location). 022 (writes version 3). 025 (reads versions 1 to 3, six-value matching, "This instance reads version 3.", decision 9's problem-row reasons). 028 (reads versions 1 to 3; places in the plan and fingerprint; AC-6.4's round trip). 029 decision 3, decision 10, AC-9.15 and its Non-Goal on counts | Decision 5 and Story 7 (AC-7.2), for number entry only (a line may carry a place): 034 Non-Goals on #46, decision 5 and AC-4.4 (the grid and table show no place): 033 | | [033 Show the Location on Tiles and Rows](033-location-on-tiles-and-rows/spec.md) | Frozen in part: all but decision 5 as it applies to rows ([#142](https://github.com/plainprogrammer/Collector/issues/142)), by [collection and lots](../architecture/collection-and-lots.md) | [Collection and lots](../architecture/collection-and-lots.md) (the grid and the table); [design system](../design-system/README.md) (ItemTile, CollectionTable) | retired in `fb8de443936f0fd8446c8cb1d0654faf63156cb6`; `git show fb8de443936f0fd8446c8cb1d0654faf63156cb6^:docs/specs/033-location-on-tiles-and-rows/plan.md` | 032 Non-Goals on #46, decision 5 and AC-4.4. 004 AC-11.2 and the Non-Goal on a location line. 006 AC-2.1 and AC-2.8 | AC-1.8 (a tile shows all its places) under a location filter, and FR-3's `exists?` read: 037 (decision 3, NFR Performance) | @@ -59,5 +59,5 @@ A plan is deleted from the tree in a commit of its own after its feature's pull | [036 Advisory Response for Locked Dependencies](036-advisory-response/spec.md) | Frozen, by [release and deploy](../architecture/release-and-deploy.md) | [Release and deploy](../architecture/release-and-deploy.md) (the Dependabot configuration, a scheduled audit workflow) | retired in `3ebd563429e487d6f03f5bf33c2490664a7d353b`; `git show 3ebd563429e487d6f03f5bf33c2490664a7d353b^:docs/specs/036-advisory-response/plan.md` | | | | [037 Filter the Collection by Location](037-filter-collection-by-location/spec.md) | Approved | [Collection and lots](../architecture/collection-and-lots.md) (the collection page, bulk mode's selection); [design system](../design-system/README.md) (FilterSelect) | present | | Spec 033 AC-1.8 and FR-3; spec 004's filter-bar note; spec 006 FR-4's selection context, as stated in 037's Supersedes | | | [038 Store Currency per Account](038-currency-per-account/spec.md) | Approved | [Collection and lots](../architecture/collection-and-lots.md) (price paid's currency); [data portability](../architecture/data-portability.md) (the export's currency, the preview and the apply) | present | 004 FR-6 (the instance currency; the boot check and "converts nothing" stay). 006 (the table's price in the instance currency). 017 FR-4 and decision 13 (the currency is the instance's). 022 decision 4 (its source). 025 decision 3 and its `other_currency` row (a file in another currency is refused). 028 AC-6.4 and decisions 2, 5, 11, 12 (the apply writes the currency too). 030 (a restore shows another symbol). 032 (the format version after 3 is #64's). North star hosted-door note on currency | | -| [039 A Finished Art Build Whose Index File Is Missing Isn't "Ready"](039-art-index-missing-file/spec.md) | Approved | [Catalog operations](../architecture/catalog-operations.md) (the art index panel and the art line of `catalog:status`) | present | 015 AC-4.7 and 011 AC-3.11, as far as a finished build reads "ready" whatever the volume holds. 030 decision 12 ("not fixed here") | | +| [039 A Finished Art Build Whose Index File Is Missing Isn't "Ready"](039-art-index-missing-file/spec.md) | Approved | [Catalog operations](../architecture/catalog-operations.md) (the art index panel and the art line of `catalog:status`) | present | 015 AC-4.1 in part, the art index's states gain "index file missing" and "ready" needs the file. 011 AC-3.11 in part, the art line says "ready" only when the file is there. 030 decision 12 in part, "not fixed here" (fixed) | | | [040 Scan a Sitting into a Location](040-sitting-into-location/spec.md) | Approved | [Collection and lots](../architecture/collection-and-lots.md) (the scanner adds placed copies); scanner (no area doc) | present | 009 Non-Goals "Sitting-wide defaults" and "Locations", for a location only. 032 decision 5 and Story 7 (AC-7.2), for the scanner only: a sitting may carry a place | | From 80aad739ce7e298d679ab53acf2ee41d29541703 Mon Sep 17 00:00:00 2001 From: James Thompson Date: Thu, 5 Nov 2026 23:34:36 -0500 Subject: [PATCH 06/12] docs(specs): screenshots of the art index panel, ready and index file missing Spec 039: /admin/catalog's mtg panel in light and dark, with the art build row seeded by a scratch script into the worktree's dev database (no real art index; the ready shots have an empty index file written through MTG::Art::Index.write!, the missing shots have it deleted). Co-Authored-By: Claude Opus 5.5 --- .../screenshots/01-art-index-ready-light.jpg | Bin 0 -> 41307 bytes .../screenshots/02-art-index-ready-dark.jpg | Bin 0 -> 38951 bytes .../screenshots/03-art-index-missing-light.jpg | Bin 0 -> 44892 bytes .../screenshots/04-art-index-missing-dark.jpg | Bin 0 -> 42394 bytes 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/specs/039-art-index-missing-file/screenshots/01-art-index-ready-light.jpg create mode 100644 docs/specs/039-art-index-missing-file/screenshots/02-art-index-ready-dark.jpg create mode 100644 docs/specs/039-art-index-missing-file/screenshots/03-art-index-missing-light.jpg create mode 100644 docs/specs/039-art-index-missing-file/screenshots/04-art-index-missing-dark.jpg diff --git a/docs/specs/039-art-index-missing-file/screenshots/01-art-index-ready-light.jpg b/docs/specs/039-art-index-missing-file/screenshots/01-art-index-ready-light.jpg new file mode 100644 index 0000000000000000000000000000000000000000..580976e3079e2a46be3e9e05074d315ef6718b9b GIT binary patch literal 41307 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 R{yhHE0{;{XeD|&Ye*n9>XE^`> literal 0 HcmV?d00001 diff --git a/docs/specs/039-art-index-missing-file/screenshots/02-art-index-ready-dark.jpg b/docs/specs/039-art-index-missing-file/screenshots/02-art-index-ready-dark.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0ea87d57d807611589ff217a9a75097c8e468255 GIT binary patch literal 38951 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

P{TJ*ilGQ+V8mP* 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 Z>Z=G5!i4_cwtoB%G4}tb48=c3{vT>+F`)ne literal 0 HcmV?d00001 From 76339203547fdfdb9b358c6d3c0dc697107cde54 Mon Sep 17 00:00:00 2001 From: James Thompson Date: Fri, 6 Nov 2026 00:01:41 -0500 Subject: [PATCH 07/12] test(art): tighten spec 039's guards and the README's wording after review Implementation review (Opus, read-only), minor findings 1-3: - README's two restore places quote the status line as it prints ("Art matching: index file missing"), not the panel's words. - AC-2.2's guard compares the whole ready line, not a substring. - AC-1.6 gains an interrupted example with a missing-file build behind a left-behind one (stalled shares the running branch it now guards). These are guards: they pass on the current code by design. Co-Authored-By: Claude Opus 5.5 --- README.md | 4 ++-- spec/models/mtg/art/operation_spec.rb | 8 ++++++++ spec/models/mtg/art_spec.rb | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ef799901..42dfc961 100644 --- a/README.md +++ b/README.md @@ -429,7 +429,7 @@ Keep several, and delete old ones yourself. A restore needs a **new, empty volume** and runs **before the instance's first start**, as a one-off command in a container of the image you will run. It refuses a volume that already holds a Collector database (or the `-wal`, `-shm` or `-journal` file of one, or the queue, cache or cable database) and changes nothing: to restore over a running instance, restore onto a new volume and switch to it. It restores a backup taken by the same release or an older one, which the first start then migrates as any upgrade does; a backup from a newer release is refused. Use the image tag you run (`COLLECTOR_IMAGE`), and a release that has `backup:restore`. -A restore ends every session (everyone signs in again) and drops pending bulk-removal Undos and selections; no collection is lost. It leaves the art index file behind: with art matching on, press **Build art index** on the admin catalog page afterwards, which needs no downloads. Until you do, that page and `catalog:status` read "Index file missing". +A restore ends every session (everyone signs in again) and drops pending bulk-removal Undos and selections; no collection is lost. It leaves the art index file behind: with art matching on, press **Build art index** on the admin catalog page afterwards, which needs no downloads. Until you do, that page reads "Index file missing" and `catalog:status` "Art matching: index file missing". **Docker Compose.** Create the volume without starting Collector, and find its real name (Compose prefixes the project's name; a different project name is a different, empty volume): @@ -478,7 +478,7 @@ bin/kamal setup --skip-push --version 0.1.0 Give the exact release as the tag: releases deploy by version, so no `latest` tag is on the server. This path is documented and its container command is tested in CI, but it hasn't been run through Kamal itself. -**After a restore**, before you hand the instance back: compare the counts the command printed (accounts, users, lots) with what you expect; start it; sign in; with art matching on press **Build art index** (until then the admin catalog page and `catalog:status` read "Index file missing"); check your settings (`COLLECTOR_*`) and your secret. +**After a restore**, before you hand the instance back: compare the counts the command printed (accounts, users, lots) with what you expect; start it; sign in; with art matching on press **Build art index** (until then the admin catalog page reads "Index file missing" and `catalog:status` "Art matching: index file missing"); check your settings (`COLLECTOR_*`) and your secret. **A damaged, cut-short or wrong file is refused** with a plain message and the volume is left as it was: a file still being copied, a file from another tool, a collector's export (use **Import collection** for that), a backup of a newer release, a snapshot that fails SQLite's integrity or foreign-key check. diff --git a/spec/models/mtg/art/operation_spec.rb b/spec/models/mtg/art/operation_spec.rb index 3ee603c6..90c29861 100644 --- a/spec/models/mtg/art/operation_spec.rb +++ b/spec/models/mtg/art/operation_spec.rb @@ -510,6 +510,14 @@ def facts = operation.facts.to_h { |fact| [ fact.label, fact.value ] } expect(operation.state).to eq(:building) end + it "is interrupted when a later build was left behind (AC-1.6, decision 6)" do + loaded + build(index_file: gone, started_at: 2.hours.ago) + build(status: "running", finished_at: nil, heartbeat_at: (MTG::ArtBuild::STALE_AFTER + 1.minute).ago) + + expect(operation.state).to eq(:interrupted) + end + it "is failed, worded as before, when the latest build failed (AC-1.6, decision 6)", :aggregate_failures do loaded build(index_file: gone, started_at: 2.hours.ago) diff --git a/spec/models/mtg/art_spec.rb b/spec/models/mtg/art_spec.rb index f131d2ab..c79f8ad5 100644 --- a/spec/models/mtg/art_spec.rb +++ b/spec/models/mtg/art_spec.rb @@ -117,7 +117,7 @@ def refresh_run(status) = build(:catalog_refresh_run, collectible_type: "mtg", s it "reports a finished build's counts and index", :art_matching do name = art_index_name create(:mtg_art_build, indexed_count: 9, without_image_count: 1, failed_count: 2, index_file: name) - expect(described_class.status_line).to include("ready", "9 artworks indexed", "1 without an image", "2 failed images", name) + expect(described_class.status_line).to eq("Art matching: ready; 9 artworks indexed, 1 without an image, 2 failed images; index #{name}") end it "says the index file is missing, and what to press (spec 039 AC-2.1)", :aggregate_failures, :art_matching do From af1e7ae853375353cf10a4a2135ca64351c62288 Mon Sep 17 00:00:00 2001 From: James Thompson Date: Fri, 6 Nov 2026 00:01:55 -0500 Subject: [PATCH 08/12] docs(specs): spec 039 verification and implementation review Red-then-green evidence per phase, the AC table, the local bin/ci result, and the Mode B review (Opus, read-only): SPEC-ALIGNED WITH MINOR GAPS, minors 1-3 fixed in 7633920, 4-6 ruled. Co-Authored-By: Claude Opus 5.5 --- .../verification.md | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 docs/specs/039-art-index-missing-file/verification.md diff --git a/docs/specs/039-art-index-missing-file/verification.md b/docs/specs/039-art-index-missing-file/verification.md new file mode 100644 index 00000000..a95dc84d --- /dev/null +++ b/docs/specs/039-art-index-missing-file/verification.md @@ -0,0 +1,58 @@ +# Verification: Feature 039, A Finished Art Build Whose Index File Is Missing Isn't "Ready" + +**Spec:** [spec.md](spec.md) v1.0.1 · **Plan:** [plan.md](plan.md) · **Issue:** [#122](https://github.com/plainprogrammer/Collector/issues/122) · **Pull request:** [#175](https://github.com/plainprogrammer/Collector/pull/175) + +## Red, then green, per phase + +| Phase | Commit | Red (before the code change) | Green | +|---|---|---|---| +| 1. `MTG::Art::Index.file?`, `MTG::ArtBuild#index_file_present?` | `446b507` | `index_spec.rb` "knows whether a file of its name is there" and `art_build_spec.rb` "#index_file_present?" failed, neither method existing yet (the latter: "expected … to respond to `index_file_present?`") (35 examples, 2 failures) | 35 examples, 0 failures | +| 2. The panel's `:index_missing` state | `f73f537` | The four new missing-state examples (AC-1.1–1.3, both AC-1.5, AC-1.8) failed, reading `:ready` / "Ready."; the AC-1.4, AC-1.6 and AC-1.7 guards passed (94 examples, 4 failures) | 94 examples, 0 failures; with the other readers of the art line and panel (`art_spec.rb`, `catalog_rake_spec.rb`, `scryfall/source_spec.rb`, `backup_restored_art_spec.rb`, `admin_catalog_core_spec.rb`): 150 examples, 0 failures | +| 3. The status line | `5712f67` | AC-2.1's two examples failed, the line reading "Art matching: ready; …" (24 examples, 2 failures) | 55 examples, 0 failures (`art_spec.rb`, `catalog_rake_spec.rb`, `scryfall/source_spec.rb`) | +| 4. Building again restores "Ready." | `474ee49` | With Phase 1's `operation.rb` and `art.rb` put back: AC-3.2 failed (`expected: :index_missing`) and AC-1.8 likewise; AC-3.1 passed, a guard (the controller is unchanged, as the spec says) | 3 examples, 0 failures; `build_spec.rb`, `catalogs_spec.rb`, `backup_restored_art_spec.rb`: 66 examples, 0 failures | +| 5. Documents | `fa3a0f4` | Reading-verified (below) | | + +Full local `bin/ci` at `474ee49` (the last code commit; later commits are documents and images): every step passed, RSpec 2435 examples, 0 failures, 1 pending, in 5m59s. The pre-push hook's full `bin/ci` (it blocks on failure) let the push of `80aad73` through. + +## Acceptance criteria + +| AC | Evidence | +|---|---| +| AC-1.1 | `spec/models/mtg/art/operation_spec.rb` "says the index file is missing, shows the build's facts and can be built again" | +| AC-1.2 | Same example: labels in order `Finished, Index file, Artworks indexed, Without an image, Failed images` and their values | +| AC-1.3 | Same example: `startable?` true, `meter` nil, `failed_job?` false, `record_running?` false; the request example of AC-1.8 finds no `poll` controller | +| AC-1.4 | `operation_spec.rb` "is ready while the named file is there"; the updated AC-4.7 example also checks no "Index file" fact | +| AC-1.5 | `operation_spec.rb` "reads a row with no file name as missing, with none recorded" and "reads a name of another shape as missing and shows it as stored"; that nothing outside `index/` is examined is `MTG::Art::Index.file?`'s `NAME` check, proven in `index_spec.rb` with `../../config/master.key` | +| AC-1.6 | `operation_spec.rb` "is queued while a build job waits", "is building while a later build runs", "is failed, worded as before, when the latest build failed" | +| AC-1.7 | `operation_spec.rb` "looks at no file, whatever the latest build names" (art matching off; `MTG::Art::Index.file?` spied, never called) | +| AC-1.8 | `spec/requests/admin/catalogs_spec.rb` "says a finished build's index file is missing, with its facts and an enabled button, and doesn't poll"; a member's 404 is the file's existing generic example | +| AC-2.1 | `spec/models/mtg/art_spec.rb` "says the index file is missing, and what to press" and "says no file name was recorded for a finished build without one" | +| AC-2.2 | `art_spec.rb` "reports a finished build's counts and index" (now with a real file) | +| AC-2.3 | `art_spec.rb`'s existing running, stalled, interrupted, failed, off and no-build examples, unchanged and green | +| AC-3.1 | `catalogs_spec.rb` "queues one build when Build art index is pressed with the index file missing" | +| AC-3.2 | `spec/models/mtg/art/build_spec.rb` "writes a missing index file again without an image request, and reads ready again" (ImageMagick present; every request blocked after `WebMock.reset!`) | +| AC-4.1 | `docs/architecture/catalog-operations.md`: Glossary "Ready (art index)"; the art index table's two Finished rows; the status-line paragraph; Accepted limits (judged by name only); Sources (spec 039, #122). Read on 2026-11-05 | +| AC-4.1a | `docs/architecture/release-and-deploy.md`: Neighbours line, the #122 limit reworded as fixed, Sources (spec 039; #122 moved from open to fixed). Read on 2026-11-05 | +| AC-4.2 | `docs/specs/README.md`: the 039 row's Supersedes names 015 AC-4.1, 011 AC-3.11 and 030 decision 12, each in part; the 015, 011 and 030 rows' Superseded-by cells name 039 (the 030 row's text moved from a stray seventh cell into Superseded by). No shipped spec edited (`git diff origin/main -- 'docs/specs/0[0-2]*' 'docs/specs/03[0-8]*'` is empty). Read on 2026-11-05 | +| AC-4.3 | `README.md`'s Restore paragraph and "After a restore" checklist say the page and `catalog:status` read "Index file missing" until **Build art index** is pressed; `docs/backup-restore.md` and `lib/collector/backup/restore.rb` unchanged. Read on 2026-11-05 | + +## Demonstration + +`/admin/catalog` with art matching on, the art build row seeded by a scratch script into the worktree's dev database (an empty index written through `MTG::Art::Index.write!` for "ready", deleted for "missing"): [screenshots/](screenshots/) 01–04, light and dark. `catalog:status[mtg]` output for both states is in the pull request body. + +## Implementation review + +SPEC-ALIGNED WITH MINOR GAPS (sdd-review Mode B, Opus, read-only, 2026-11-06, on `80aad73`); the minor gaps it named are closed or ruled below, so the feature stands spec-aligned. + +Every AC was covered by a test or a reading (the table above matches the reviewer's). FR-1 to FR-4, the NFRs, decisions 1 to 6, the error-scenario table and the Supersedes section match the code; FR-4 held (nothing under `app/controllers`, `app/views`, `app/helpers` or `app/models/catalog` changed). No blocking or major findings. The minor ones: + +| # | Finding | Handling | +|---|---|---| +| 1 | README quoted the panel's words for `catalog:status` | Fixed in `7633920`: it quotes "Art matching: index file missing" | +| 2 | AC-2.2's guard matched substrings only | Fixed in `7633920`: the whole ready line is compared | +| 3 | AC-1.6 had no interrupted example behind a missing-file build | Fixed in `7633920`: one example (stalled takes the same `running?` branch) | +| 4 | `verification.md` uncommitted; `Gemfile.lock` noise | This commit; the local arm64-darwin `Gemfile.lock` change stays uncommitted | +| 5 | The settings-drift follow-up issue is unfiled | Left to the coordinator, who files issues; its title and body are in the worker's report | +| 6 | The upgrade seeds' `art-index-upgrade.bin.gz` reads as missing | No action: accepted by the spec's Interactions section; the upgrade proof checks neither page | + +A permission error reading as missing rests on `File.file?` returning false on a failed `stat`; no example forces one (not portable in CI). From fef8f9bf539291fda5b5f9554748f785fb8f5e59 Mon Sep 17 00:00:00 2001 From: James Thompson Date: Fri, 6 Nov 2026 00:02:35 -0500 Subject: [PATCH 09/12] docs(architecture): distil spec 039 into catalog operations and release and deploy The area docs' rules were written in Phase 5 (fa3a0f4); this adds their Distillation log rows and marks the index row Frozen by both docs, its plan retirement owed. Co-Authored-By: Claude Opus 5.5 --- docs/architecture/catalog-operations.md | 1 + docs/architecture/release-and-deploy.md | 1 + docs/specs/README.md | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/architecture/catalog-operations.md b/docs/architecture/catalog-operations.md index d3d47ad2..4f04d8fa 100644 --- a/docs/architecture/catalog-operations.md +++ b/docs/architecture/catalog-operations.md @@ -212,3 +212,4 @@ Filter chips Failed (the default), Running, Queued and Scheduled, each with its | Date | Distilled | Pull request | |---|---|---| | 2026-10-15 | Specs 002 (FR-3–FR-6 and their Error Scenarios rows), 011 (FR-2's build run), 015 and 024; issues #60, #61, #73, #74, #78–#81 and #84, and the open #41, #77 and #86; and CLAUDE.md's "Admin catalog and jobs" bullet | [#110](https://github.com/plainprogrammer/Collector/pull/110) | +| 2026-11-06 | Spec 039 (the art index's "Index file missing" state, the status line's missing wording, "ready" judged by the build's own named file, the accepted limit on judging by name only) and issue #122 | [#175](https://github.com/plainprogrammer/Collector/pull/175) | diff --git a/docs/architecture/release-and-deploy.md b/docs/architecture/release-and-deploy.md index ecf86d88..d40a7bf7 100644 --- a/docs/architecture/release-and-deploy.md +++ b/docs/architecture/release-and-deploy.md @@ -276,3 +276,4 @@ CI proves one release step of it: the previous release's published image, seeded | 2026-10-24 | Spec 031 (the upgrade proof, the migration guard, the release steps around them) | spec 031's pull request | | 2026-11-01 | Spec 035 (the `bin/ci` groups, the shards and their run-time log, the workflow's `checks`, `rspec` and `ci` jobs, the slowest examples, the measured shard count); its pre-push hook (decision 3, Story 3) stays in CLAUDE.md, which has the development environment's facts | [#149](https://github.com/plainprogrammer/Collector/pull/149) and spec 035's follow-up pull request | | 2026-11-03 | Spec 036 (the Ruby gems' security updates as one group, the daily advisory audit workflow, the response to a red audit, the two Named constants rows); the criteria that need GitHub stay in its `verification.md` | [#163](https://github.com/plainprogrammer/Collector/pull/163) | +| 2026-11-06 | Spec 039 (what the admin page and `catalog:status` read after a restore leaves the art index file behind; #122 fixed) | [#175](https://github.com/plainprogrammer/Collector/pull/175) | diff --git a/docs/specs/README.md b/docs/specs/README.md index 41705334..25ebc560 100644 --- a/docs/specs/README.md +++ b/docs/specs/README.md @@ -59,5 +59,5 @@ A plan is deleted from the tree in a commit of its own after its feature's pull | [036 Advisory Response for Locked Dependencies](036-advisory-response/spec.md) | Frozen, by [release and deploy](../architecture/release-and-deploy.md) | [Release and deploy](../architecture/release-and-deploy.md) (the Dependabot configuration, a scheduled audit workflow) | retired in `3ebd563429e487d6f03f5bf33c2490664a7d353b`; `git show 3ebd563429e487d6f03f5bf33c2490664a7d353b^:docs/specs/036-advisory-response/plan.md` | | | | [037 Filter the Collection by Location](037-filter-collection-by-location/spec.md) | Approved | [Collection and lots](../architecture/collection-and-lots.md) (the collection page, bulk mode's selection); [design system](../design-system/README.md) (FilterSelect) | present | | Spec 033 AC-1.8 and FR-3; spec 004's filter-bar note; spec 006 FR-4's selection context, as stated in 037's Supersedes | | | [038 Store Currency per Account](038-currency-per-account/spec.md) | Approved | [Collection and lots](../architecture/collection-and-lots.md) (price paid's currency); [data portability](../architecture/data-portability.md) (the export's currency, the preview and the apply) | present | 004 FR-6 (the instance currency; the boot check and "converts nothing" stay). 006 (the table's price in the instance currency). 017 FR-4 and decision 13 (the currency is the instance's). 022 decision 4 (its source). 025 decision 3 and its `other_currency` row (a file in another currency is refused). 028 AC-6.4 and decisions 2, 5, 11, 12 (the apply writes the currency too). 030 (a restore shows another symbol). 032 (the format version after 3 is #64's). North star hosted-door note on currency | | -| [039 A Finished Art Build Whose Index File Is Missing Isn't "Ready"](039-art-index-missing-file/spec.md) | Approved | [Catalog operations](../architecture/catalog-operations.md) (the art index panel and the art line of `catalog:status`) | present | 015 AC-4.1 in part, the art index's states gain "index file missing" and "ready" needs the file. 011 AC-3.11 in part, the art line says "ready" only when the file is there. 030 decision 12 in part, "not fixed here" (fixed) | | +| [039 A Finished Art Build Whose Index File Is Missing Isn't "Ready"](039-art-index-missing-file/spec.md) | Frozen, by [catalog operations](../architecture/catalog-operations.md) and [release and deploy](../architecture/release-and-deploy.md) | [Catalog operations](../architecture/catalog-operations.md) (the art index panel and the art line of `catalog:status`); [release and deploy](../architecture/release-and-deploy.md) (what a restore reads until the build) | retirement owed | 015 AC-4.1 in part, the art index's states gain "index file missing" and "ready" needs the file. 011 AC-3.11 in part, the art line says "ready" only when the file is there. 030 decision 12 in part, "not fixed here" (fixed) | | | [040 Scan a Sitting into a Location](040-sitting-into-location/spec.md) | Approved | [Collection and lots](../architecture/collection-and-lots.md) (the scanner adds placed copies); scanner (no area doc) | present | 009 Non-Goals "Sitting-wide defaults" and "Locations", for a location only. 032 decision 5 and Story 7 (AC-7.2), for the scanner only: a sitting may carry a place | | From 6aa432a83eaf20d9df365687db8b1d81f2f9264f Mon Sep 17 00:00:00 2001 From: James Thompson Date: Fri, 6 Nov 2026 00:02:45 -0500 Subject: [PATCH 10/12] docs(specs): mark spec 039 frozen by the catalog operations and release and deploy area docs (spec 027 D4) Co-Authored-By: Claude Opus 5.5 --- docs/specs/039-art-index-missing-file/spec.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/specs/039-art-index-missing-file/spec.md b/docs/specs/039-art-index-missing-file/spec.md index 5c43a02d..0c79d03e 100644 --- a/docs/specs/039-art-index-missing-file/spec.md +++ b/docs/specs/039-art-index-missing-file/spec.md @@ -6,6 +6,7 @@ **Last Updated:** 2026-11-03 **Branch:** `039-art-index-missing-file` **Issue:** [#122](https://github.com/plainprogrammer/Collector/issues/122) +**Frozen:** the current rules are in [`catalog-operations.md`](../../architecture/catalog-operations.md) and [`release-and-deploy.md`](../../architecture/release-and-deploy.md) (whole spec); see the [specs index](../README.md) --- From e75c454f5b3a9c40d44b72f78a178dfc0ddcd8aa Mon Sep 17 00:00:00 2001 From: James Thompson Date: Fri, 6 Nov 2026 00:03:01 -0500 Subject: [PATCH 11/12] docs(specs): record spec 039's distillation Co-Authored-By: Claude Opus 5.5 --- docs/specs/039-art-index-missing-file/verification.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/specs/039-art-index-missing-file/verification.md b/docs/specs/039-art-index-missing-file/verification.md index a95dc84d..3c06fa1e 100644 --- a/docs/specs/039-art-index-missing-file/verification.md +++ b/docs/specs/039-art-index-missing-file/verification.md @@ -56,3 +56,7 @@ Every AC was covered by a test or a reading (the table above matches the reviewe | 6 | The upgrade seeds' `art-index-upgrade.bin.gz` reads as missing | No action: accepted by the spec's Interactions section; the upgrade proof checks neither page | A permission error reading as missing rests on `File.file?` returning false on a failed `stat`; no example forces one (not portable in CI). + +## Distillation + +2026-11-06 (`distill-feature`): the rules were written into [catalog operations](../../architecture/catalog-operations.md) (Glossary "Ready (art index)", the art index table's two Finished rows, the status-line paragraph, an accepted limit, Sources) and [release and deploy](../../architecture/release-and-deploy.md) (Neighbours line, the #122 limit reworded as fixed, Sources) in `fa3a0f4`; `fef8f9b` added both docs' Distillation log rows and set the index row to Frozen by both, plan retirement owed; `6aa432a` added the spec's frozen line. CLAUDE.md only points to the area doc and needed no change. No ADR is owed. The plan is retired after the merge. From 543cdb094996ca57c2f9ce027238b6835548666b Mon Sep 17 00:00:00 2001 From: James Thompson Date: Fri, 6 Nov 2026 00:24:29 -0500 Subject: [PATCH 12/12] docs(specs): link spec 039's settings-drift follow-up, #176 Co-Authored-By: Claude Opus 5.5 --- docs/specs/039-art-index-missing-file/verification.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/specs/039-art-index-missing-file/verification.md b/docs/specs/039-art-index-missing-file/verification.md index 3c06fa1e..606e3253 100644 --- a/docs/specs/039-art-index-missing-file/verification.md +++ b/docs/specs/039-art-index-missing-file/verification.md @@ -52,7 +52,7 @@ Every AC was covered by a test or a reading (the table above matches the reviewe | 2 | AC-2.2's guard matched substrings only | Fixed in `7633920`: the whole ready line is compared | | 3 | AC-1.6 had no interrupted example behind a missing-file build | Fixed in `7633920`: one example (stalled takes the same `running?` branch) | | 4 | `verification.md` uncommitted; `Gemfile.lock` noise | This commit; the local arm64-darwin `Gemfile.lock` change stays uncommitted | -| 5 | The settings-drift follow-up issue is unfiled | Left to the coordinator, who files issues; its title and body are in the worker's report | +| 5 | The settings-drift follow-up issue is unfiled | Filed by the coordinator as [#176](https://github.com/plainprogrammer/Collector/issues/176) | | 6 | The upgrade seeds' `art-index-upgrade.bin.gz` reads as missing | No action: accepted by the spec's Interactions section; the upgrade proof checks neither page | A permission error reading as missing rests on `File.file?` returning false on a failed `stat`; no example forces one (not portable in CI).