Skip to content

Area docs hold the current architecture, starting with catalog operations (spec 027) - #110

Merged
plainprogrammer merged 42 commits into
mainfrom
027-architecture-area-docs
Oct 15, 2026
Merged

plainprogrammer merged 42 commits into
mainfrom
027-architecture-area-docs

Conversation

@plainprogrammer

@plainprogrammer plainprogrammer commented Oct 15, 2026 •

Copy link
Copy Markdown
Owner

Closes #102.

Spec 027, slice A: the current architecture moves into area docs, starting with catalog operations (spec v1.3.0; verification in verification.md).

What changes

  • Area docs: docs/architecture/README.md (purpose, shape, area list, when a doc changes) and docs/architecture/catalog-operations.md, distilled from specs 002 (FR-3–FR-6), 011 (FR-2's build run), 015 and 024, ADRs 0014, 0015 and 0018, and issues Catalog page reads "Running." after a crashed refresh #60–Admin catalog shows raw exception classes when a refresh or build fails #84, with every statement sourced and every constant checked against the code.
  • CLAUDE.md: the 714-word "Admin catalog and jobs" bullet is now a 54-word pointer; the file drops from 2,312 to 1,661 words.
  • Specs index: docs/specs/README.md, with one row per spec folder, its status, areas and plan state, and supersessions in both directions.
  • Frozen specs: specs 002 and 011 are frozen in part, 015 and 024 whole (D4 frozen lines only).
  • Retired plans: the plans of specs 015 and 024 are deleted in commits of their own, with pointers that read them back byte for byte. Merge this PR with a merge commit, or the pointers break (docs/git-convention.md, Merging).
  • Process: .claude/rules/documentation.md, the steering file architecture.md, the distill-feature project skill, .claude/CLAUDE.md's session-end line, and the rewritten memory on not editing shipped specs.
  • Roadmap and ADR index: housekeeping lines for Area docs hold the current architecture, starting with catalog operations #102–Area doc: release and deploy #109; ADR 0023 (YARD) is expected.

There are no application changes: git diff --stat over app lib config bin db spec script is empty.

Follow-ups

Slice B (YARD) is #103. Slices C1–C6 are #104–#109.

The implementation review found one behaviour with no spec source: the admin pages' poll controller pauses while the tab is hidden, while Turbo is busy, and while a menu is open (app/javascript/controllers/poll_controller.js:6, :19-20). It is open for a ruling in #111. The area doc states the behaviour and links the issue.

🤖 Generated with Claude Code

plainprogrammer and others added 30 commits October 15, 2026 11:29
…tions

Records the maintainer's rulings of 2026-10-15 (R1-R7) on area docs,
frozen specs, the specs index, a slimmer CLAUDE.md, plan retirement with
merge commits, and YARD. Splits the work into slice A (this spec: the
structure, rules, index, distillation step and the catalog operations
pilot), slice B (YARD, ADR 0023 expected) and slices C1-C7 (one area per
pull request). Four open decisions carry recommendations.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
From the read-only Fable spec review (APPROVE WITH CHANGES) and the
maintainer's ruling R8: specs 025 and 026 record their supersessions
instead of editing earlier specs, the first use of freezing, and the
edit-specs memory is rewritten in this slice. Adds the skill's
nothing-to-do state, integrations rows for both session-wrap names, the
squash and rebase recovery, the "retirement owed" plan state, the open
issue search, and two new open decisions (log scope, slice C issues).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Records rulings OD1-OD6 of 2026-10-15: distil in the feature PR, retire
the plans of specs 015 and 024 here, keep data portability and drop the
development environment area (its specs' facts stay in CLAUDE.md under
R5, so slice C becomes C1-C6), cover the jobs pages in catalog
operations, log only whole-feature distillations, one issue per area.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Nine phases, one implementer per phase: a baseline record, the rules and
process docs, the catalog operations area doc (drafted in full), CLAUDE.md
and the frozen lines, the specs index, the distill-feature skill and its
integrations rows, retiring the plans of specs 015 and 024, the roadmap,
ADR index and issues, and integration verification. Prose criteria are
verified by reading and recorded in verification.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Spec update from the plan review, maintainer rulings P1-P3: the
distillation step is named in .claude/CLAUDE.md's session-end
instruction instead of integrations rows that can't fire (AC-4.5
withdrawn, AC-4.7 added); spec 027's own row reads "retirement owed";
the repository allows merge commits only, with a pointer check in the
after-merge state. State 2 needs no open pull request and reads the
"## Implementation review" section (AC-4.8).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Phase 5 names distill-feature in .claude/CLAUDE.md's session-end line
instead of integrations rows; the skill's state 2 needs no pull request
and reads "## Implementation review" (or asks), and its after-merge
state checks pointers with git cat-file -e. Spec 027's index row reads
"retirement owed". The rule file names the review heading; the git
convention says merge commits only. Also: spec 024 citations, the
"(whole spec)" frozen form, a step for code no source states, and the
git show command in the pointer text. Phase 8's hook record is dropped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Plan: Phase 0: Baseline record

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Plan: Phase 1: Rules and process docs

Ruling: the catalog operations row names 002 FR-3–FR-6 "and their Error Scenarios rows" — spec D2 and FR-4 include those rows and the draft dropped them — cost if wrong: one extra phrase in a table cell.
Ruling: "in its own pull request" reads "in the feature's own pull request" — the draft could be read as a separate pull request, while FR-5 (ruling OD1) puts the distillation in the feature's pull request before it is marked ready — cost if wrong: none; the meaning is the spec's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Plan: Phase 1: Rules and process docs

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Plan: Phase 1: Rules and process docs

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Plan: Phase 1: Rules and process docs

Ruling: the History paragraph keeps the maintainer's 2026-10-14 quote and the spec 015 v1.3.1 detail from the old memory — AC-4.6 says the memory keeps its 2026-10-14 history as history, and the draft's one-line summary dropped the quoted ruling — cost if wrong: two extra sentences in a memory file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Plan: Phase 1: Rules and process docs

Ruling: the section cites spec 027 "R6 and D7", not D7 alone — AC-5.1 asks that the section say retired plans depend on merge commits (R6) — cost if wrong: two words.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Plan: Phase 1: Rules and process docs

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs/architecture/catalog-operations.md states the current rules of the
catalog refresh, the art index build, their rate-limit retries, the admin
catalog page and the jobs pages, distilled from specs 002 (FR-3-FR-6 and
their Error Scenarios rows), 011 (FR-2's build run), 015 and 024, issues
#60-#84, and CLAUDE.md's "Admin catalog and jobs" bullet, checked against
the code at the head.

Plan: Phase 2: The catalog operations area doc

Ruling: the art build's left-behind rule is "heartbeat older than
STALE_AFTER, whether or not a worker holds its job, or older than
JOB_ENDED_GRACE while its job is failed or gone" — the draft said "unless a
worker still holds its job", which is #stalled? (display only);
MTG::ArtBuild#left_behind? and .start! close a stale build regardless —
cost if wrong: a reader would think a hung build blocks a starting job.
Ruling: a refresh run with a job id outside the queue (perform_now) is judged
by the job rule; one with no job id only by STALL_AFTER — the draft
conflated the two; Catalog::RefreshRun.job_gone excludes nil job ids —
cost if wrong: one wrong sentence about console runs.
Ruling: the core-boundary invariant names the 15 files
spec/admin_catalog_core_spec.rb checks, not all of app/models/catalog/ and
app/jobs/catalog/ — four comments there name a collectible as an example;
spec 024's NFR says those folders name none; the code decides — cost if
wrong: the invariant overstates what is checked.
Ruling: "Queued to retry. The last build failed. <sentence>" and "Failed.
<sentence>", not "failed: <message>" — #84 changed spec 015 AC-4.12's and
AC-4.8's wording; MTG::Art::Operation#summary — cost if wrong: quoted
wording that the page doesn't show.
Ruling: spec 002 FR-3-FR-6's download, filtering, language and write rules
are stated here, not left to catalog core — D2 assigns 002 FR-3-FR-6 to
this area; the draft's Neighbours handed "what a refresh writes" to
catalog core — cost if wrong: a few rules stated in the wrong area doc.
Ruling: #41 is listed under "Accepted limits and open issues" and in
Sources — AC-1.7 selects every open issue whose body names the art index —
cost if wrong: one line.
Ruling: added the hooks #reapply? and .status_lines, the not-loaded
notice (spec 015 FR-6; spec 023 decision 7), admin-only access (FR-7),
per-type panels and 404s (AC-5.1-AC-5.6), the jobs pages' notices, and the
constants BATCH_SIZE, IMAGE_HOSTS, MIN_INTERVAL, RATE_LIMITED_FOR and
KEEP_DOWNLOADS — the AC-1.4 walk found them in the sources and the code
but missing from the draft — cost if wrong: a longer doc.
Ruling: the poll controller's pause while hidden, busy or a menu is open
is stated as having no spec source — only the code says it — cost if
wrong: the controller asks the maintainer about a small behaviour.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
verification.md's Phase 2 section records AC-1.1 (the eight D5 headings),
AC-1.3 (every constant row against its definition, file:line, no
mismatch), AC-1.2 (the base bullet's 35 statements, each located in the
area doc or kept in CLAUDE.md), AC-1.4 (spec 015's Glossary, FR-1-FR-8 and
Error Scenarios, spec 024's decisions and FRs, spec 002 FR-3-FR-6 and its
Error Scenarios, spec 011 FR-2 and Story 3, item by item), AC-1.5 (links
and issues resolve), AC-1.6 (every grep hit read) and AC-1.7 (the open
issues at the head: #41, #77, #86), with the corrections made to the draft
and the one behaviour with no spec source.

Plan: Phase 2: The catalog operations area doc

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The 714-word "Admin catalog and jobs" bullet becomes a 54-word pointer to docs/architecture/catalog-operations.md that keeps the :solid_queue tag and its helpers (AC-2.1). The opening list of documents names docs/architecture/ and the specs index (AC-2.2). CLAUDE.md goes from 2,312 to 1,661 words.

Plan: Phase 3: CLAUDE.md and the frozen lines

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…(spec 027 D4)

Adds the D4 frozen line as the last line of the header block, naming the parts the area doc covers: FR-3–FR-6 and their Error Scenarios rows. Nothing else in the spec changes (D4).

Plan: Phase 3: CLAUDE.md and the frozen lines

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…(spec 027 D4)

Adds the D4 frozen line as the last line of the header block, naming the part the area doc covers: FR-2, the art build's run. Nothing else in the spec changes (D4).

Plan: Phase 3: CLAUDE.md and the frozen lines

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…(spec 027 D4)

Adds the D4 frozen line as the last line of the header block; the area doc covers the whole spec. Nothing else in the spec changes (D4).

Plan: Phase 3: CLAUDE.md and the frozen lines

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…(spec 027 D4)

Adds the D4 frozen line as the last line of the header block; the area doc covers the whole spec. Nothing else in the spec changes (D4).

Plan: Phase 3: CLAUDE.md and the frozen lines

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Records AC-2.1–AC-2.3, NFR Performance and the four frozen lines' diff with the merge base.

Plan: Phase 3: CLAUDE.md and the frozen lines

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One row per spec folder at the head (001-024 and 027), with status,
areas (D2), plan state and supersession in both directions (FR-3).

Plan: Phase 4: The specs index

Ruling: titles are each spec's own title line, not the draft's short
forms (016 uses its research note's title) — AC-3.2 asks for the
spec's linked title and a reader matches it against the file — cost if
wrong: longer cells, fixed by shortening them.

Ruling: the supersession sweep (plan step 2, widened to "feature 0NN"
and "Supersedes" lists) adds 004 FR-2 -> 023; 002 AC-1.5, AC-1.7,
AC-1.8, AC-1.11 messages, AC-10.1, FR-8 -> 004 (AC-6.5, AC-8.2);
002 AC-3.2 and 004 AC-8.2 -> 018; 002 AC-1.11 and 004 AC-6.5 -> 015
(AC-1.1, AC-1.2); 004 AC-6.3 and 019 AC-1.8 -> 021; 004 -> 006
(AC-1.7); 007 -> 009 and 011; 009 -> 011; 015 AC-3.3, AC-4.10 and
011 AC-3.2 -> 024 (AC-1.7, AC-2.1), each in both rows — the sweep is
to record every place a spec changes an earlier promise — cost if
wrong: a row names a supersession a reader need not follow.

Ruling: the draft's 011 AC-3.2 -> 015 AC-4.10, AC-4.11 pair is
removed; 011's row records it as amended in place for #73, #74, #79
and #81 (v1.1.4-v1.3.0), stating 015's criteria — 015 shipped
following 011 and both specs were edited in place for the same issues
(011 and 015 changelogs), so 015 superseded nothing of 011 —
cost if wrong: one supersession pair to restore.

Ruling: 015's "AC-2.16 and the start guard: 024 (amended in place)"
is split: AC-2.16 amended in place (v1.3.1); AC-3.3 and AC-4.10
superseded by 024 without an edit — 015's changelog names only
AC-2.16 — cost if wrong: one cell reworded.

Ruling: in-place amendments for issues sit under "Superseded by" as
"amended in place for #N (vX)", for 002, 011 and 015, with a sentence
in the introduction — the plan's draft did this for 002 and a reader
needs to know the text is not as shipped — cost if wrong: these notes
have no pairing row and could move to another column.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
AC-3.1 to AC-3.6 checked by reading the index at 3775b2d: folder and
row lists, the supersession sweep and its pairs, the introduction,
027's row, and every link.

Plan: Phase 4: The specs index

Rulings recorded in verification.md (Phase 4, "Rulings"): titles from
each spec's title line; the sweep's added supersessions in both rows;
the 011 -> 015 pair replaced by "amended in place"; 015's 024 cell
split; issue amendments under "Superseded by"; 002's Areas link.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The project skill that holds spec 027's distillation step (D6, D7,
AC-4.4): after the merge it retires owed plans and checks every
retirement pointer with git cat-file -e; before the merge it distils a
finished feature into its area docs; otherwise it says nothing to do.

Ruling: the merged pull request is found from the spec's **Branch:**
header line, not the folder name — spec 002's branch is
feat/002-scryfall-catalog-search, so the draft's --head <NNN-slug>
would miss it — cost if wrong: a merged plan is never retired, or
asking gh by the wrong branch says nothing.
Ruling: the index's retired Plan cell uses Phase 6's shorter form
("retired in `<sha>`; `git show <sha>^:<path>`"), not the spec line
without **Plan:** — so every retired row reads alike — cost if wrong:
two pointer forms in one column.
Ruling: "shows it distilled" is spelled out (Plan retirement owed or
retired, or Status Frozen/Frozen in part for a plan-less spec), and a
row qualifies for retirement only when its PR merged and its plan.md
still exists on the branch — so spec 027 on its own branch gets
"nothing to do" in both states, and a plan isn't retired twice —
cost if wrong: state 1 or 2 acts on 027 before its merge.
Ruling: in state 2 the frozen line goes in a commit of its own naming
spec 027 D4, as Phase 3 did, not inside the distillation commit —
D4 wants each such line in its own commit — cost if wrong: one extra
commit per distillation.

Plan: Phase 5: The distillation step

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The session-end instruction now names the distill-feature skill after
sdd-superpowers:session-wrap (spec 027 D6, AC-4.7, ruling P1).
.claude/integrations.md is left as it was.

Plan: Phase 5: The distillation step

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
AC-4.4 and AC-4.7 checked by reading; spec 027's own row walked
through the skill's states (nothing to do on its branch before merge);
git diff of .claude/integrations.md against the merge base is empty.

Ruling: own-plan link search catches anchors and ./ — AC-5.3 — cost if
wrong: a broken link survives. Ruling: the Distillation log names the
PR by number once opened — the wrap runs before gh pr create — cost if
wrong: a later cell edit. Ruling: ask the maintainer when gh can't
answer and before a housekeeping branch — cost if wrong: an extra
question. (The skill's other rulings are in its own commit.)

Plan: Phase 5: The distillation step

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Spec 015 has shipped and catalog-operations.md covers it, so its plan leaves the tree (spec 027 D7, OD2). Read it with git show <this commit>^:docs/specs/015-admin-catalog-and-jobs/plan.md.

Plan: Phase 6: Plan retirement

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Spec 024 has shipped and catalog-operations.md covers it, so its plan leaves the tree (spec 027 D7, OD2). Read it with git show <this commit>^:docs/specs/024-refresh-rate-limit-wait/plan.md.

Plan: Phase 6: Plan retirement

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…7 D4)

Adds each spec's retirement pointer under its Frozen line, replaces spec 024's verification.md link to its own retired plan with plain text, and sets the two Plan cells in the specs index to the retired form the distill-feature skill writes. Full 40-character shas are used so the pointers stay unambiguous as history grows.

Plan: Phase 6: Plan retirement

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
plainprogrammer and others added 12 commits October 15, 2026 13:21
Records the skipped merge, the checks before editing, the pointers, and AC-5.2 (cmp exit 0 for both plans), AC-5.3 and AC-5.4.

Ruling: full 40-character shas in the pointers and index cells — a pointer should resolve forever and a short sha can become ambiguous — cost if wrong: longer cells, shortened in a later D4 commit.

Plan: Phase 6: Plan retirement

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds the housekeeping lane's lines for spec 027 (#102), slice B (#103, YARD) and slices C1-C6 (#104-#109), after #86. The main line and the decision log are unchanged (FR-9, AC-6.1).

Plan: Phase 7: Roadmap, ADR index and issues

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The ADR index's Expected paragraph names adopting YARD (spec 027 slice B, #103) as ADR 0023, taking the next free number if another ADR merges first (FR-8, AC-6.2).

Plan: Phase 7: Roadmap, ADR index and issues

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Spec 027's header Issue line now links #102 (FR-9). Spec 027 isn't shipped, so this is its own record, not a D4 edit.

Plan: Phase 7: Roadmap, ADR index and issues

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Records the eight issues (#102-#109) as gh reports them, the checks of the three drafts, AC-6.1 and AC-6.2.

Ruling: the specs index (docs/specs/README.md) is left alone - the plan puts no issue numbers in it (Phases 4 and 7) and it has no issue column - cost if wrong: one later edit adding them.

Plan: Phase 7: Roadmap, ADR index and issues

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Plan: Phase 8: Integration verification

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Plan: Phase 8: Integration verification

Ruling: the before-merge step leaves Plan as "none" when no plan was written — FR-3's plan words keep "none", and state 1 already assumed it — cost if wrong: one clause. From the implementation review's observation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Plan: Phase 8: Integration verification

Every AC walked with its evidence, bin/ci's result, the link check, and the read-only implementation review's verdict (SPEC-ALIGNED) under ## Implementation review.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The behaviour has no spec source; the maintainer ruled it gets an issue. #111 names the admin pages, so it joins the open issues the area doc lists (AC-1.7).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The implementation review's no-spec-source finding now links #111 (maintainer ruling, 2026-10-15), and Phase 8's ruling not to open an issue is marked overruled. distill-feature ran on this branch: both retirement pointers resolve (git cat-file -e), 027's row already reads retirement owed and PR #110 hasn't merged, so nothing to do (D6 state 3).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
From spec 027's session wrap: the maintainer overruled the no-issue ruling for the poll controller's pauses (#111).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
From spec 027's session wrap.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@plainprogrammer plainprogrammer self-assigned this Oct 15, 2026
@plainprogrammer
plainprogrammer marked this pull request as ready for review October 15, 2026 18:35
@plainprogrammer
plainprogrammer merged commit f831bf2 into main Oct 15, 2026
4 checks passed
@plainprogrammer
plainprogrammer deleted the 027-architecture-area-docs branch October 15, 2026 18:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Area docs hold the current architecture, starting with catalog operations

1 participant