diff --git a/docs/superpowers/plans/2026-07-21-decision-lifecycle-and-kickoff.md b/docs/superpowers/plans/2026-07-21-decision-lifecycle-and-kickoff.md index b04d6c7f3..fbbb451e2 100644 --- a/docs/superpowers/plans/2026-07-21-decision-lifecycle-and-kickoff.md +++ b/docs/superpowers/plans/2026-07-21-decision-lifecycle-and-kickoff.md @@ -315,9 +315,19 @@ git -c core.hooksPath=/dev/null commit -m "feat(521): decision-record parser (de **Interfaces:** - Consumes: `decisions_lib` (`all_active_records`, `parse_text`, `KEY_RE`, `STATUSES`, `ARCHIVE_DIR`, `TOPIC_DIR`, `DECISIONS_MD`). -- Produces: `validate(records, *, archive_keys, catalog_ok, budget_ok, removed, rewritten) -> - list[str]` (returns error strings; empty = pass); CLI `main()` with `--base REF --head REF` (enables - the merge-base no-vanish + body-diff checks), `--budget N`, exit 1 on any error. +- Produces: `validate(records, *, archive_keys, catalog_ok, budget_ok, removed, rewritten, + archive_records=None) -> list[str]` (returns error strings; empty = pass); CLI `main()` with + `--base REF --head REF` (enables the merge-base no-vanish + body-diff checks), `--budget N`, exit 1 + on any error. +- **Archive-placement invariant** (folded post-review; coordinated with server-management#642 so + supersession = a physical move, not an in-place `status:` flip): a `superseded`/`retired` record in + the ACTIVE files is an error ("relocate to `docs/decisions/archive/`"); an `active` record under + `docs/decisions/archive/` is an error. This makes the MemPalace wing boundary (`ErsatzTV-Decisions` + active vs `ErsatzTV-Decisions-Archive`) hold by construction. +- **Bounded body-strip** (folded post-review): `_rationale()` strips ONLY the contiguous top metadata + block (first non-blank `` `key:`` line → first following blank line), mirroring `decisions_lib`'s + parser — so a `**Rule:**`-prefixed line deep in rationale prose is prose, not silently laundered + past the body-diff. - Non-decision headings skipped: `{"Index", "Active catalog"}` (configurable `SKIP_HEADINGS`). - Diff semantics (only when `--base/--head` given): compute `mb = git merge-base BASE HEAD` and diff `mb → HEAD` (never BASE-tip, which false-flags on every main advance). `removed` = active headings @@ -1084,12 +1094,25 @@ git -c core.hooksPath=/dev/null commit -m "feat(521): rework decisions guard — Protocol. Point decision lookups at the catalog (`docs/decisions/README.md`). Update `[decisions-edit]` mentions to the re-scoped narrow meaning (rationale-prose edits only) — do not delete. - [ ] **Step 3b (MemPalace retrieval rules — #520 done-when, Fable #9)** Add a short "Knowledge - retrieval" block to the kickoff (and/or `docs/README.md`): **MemPalace = candidate discovery only**, - constrained to the ErsatzTV/project wing, retrieved at a bounded `k`, and every passage **verified - against its cited Markdown/Gitea source** before use; if MemPalace is unavailable or stale, fall back - to the `docs/README.md` task map + bounded exact search; **never** derive live queue state from - MemPalace, #237, or historical comments. Without this the #520 "MemPalace candidate discovery + - canonical verification + exact-search fallback documented" box is unmet. + retrieval" block to the kickoff (and/or `docs/README.md`), using the **concrete conventions agreed + with server-management#642** (the sole Gitea→MemPalace exporter): + - **MemPalace = candidate discovery only**, retrieved at a bounded `k`; every passage **verified + against its cited Markdown/Gitea source** before use. + - **Default wing = `ErsatzTV-Decisions`** (active `docs/decisions.md` + `docs/decisions/*.md` + + catalog). History wings `ErsatzTV-Decisions-Archive` (`docs/decisions/archive/**`) and + `Gitea-ErsatzTV` (issues/comments incl. #520 closing records) are touched **only** when the + question is explicitly "what did the rule *used to be*." "What is the current rule for X" never + touches the history wings. + - **Exact-search fallback** (MemPalace stale/down): `docs/decisions/README.md` catalog first, then + ``rg '^`key: `' docs/decisions/`` in the checkout. MemPalace is never the authority or + the fallback. + - **Staleness bounds** (so agents know when to distrust a hit): webhook re-mine in seconds; hourly + reconcile; weekly full sweep catches file moves/deletes. Worst case before a supersession takes + effect in retrieval: ~1h, or ~1 week if the webhook is down and only the move happened. #642 alerts + above 5400s. When in doubt, fall back to exact search. + - **never** derive live queue state from MemPalace, #237, or historical comments. + Without this the #520 "MemPalace candidate discovery + canonical verification + exact-search + fallback documented" box is unmet. - [ ] **Step 3c (dogfood supersession — Fable #5, PR2 half)** #520 reverses the recorded decision `## 2026-07-11 — Queue state lives in the pinned Gitea tracker (#237)`. Give it key `queue.state-source`, `status: superseded`, `superseded-by: startup.parallel-orientation@2026-07-21`, @@ -1166,6 +1189,16 @@ git -c core.hooksPath=/dev/null commit -m "docs(521): retrieval-eval question ba - [ ] **Step 5 (BOM/format)** No `.cs` touched; skip the BOM sweep. Confirm no stray CRLF/BOM in new scripts: `for f in scripts/decisions_lib.py scripts/decisions_validate.py scripts/build_decisions_catalog.py; do head -c3 "$f" | xxd -p | grep -q '^efbbbf' && echo "BOM: $f"; done` (expect no output). - [ ] **Step 6** Push once (batched), open PR `fixes #520 #521`, arm CI monitor at PR-open. +- [ ] **Step 7 (notify server-management#642 — the MemPalace exporter)** #642 is the sole + Gitea→MemPalace ingest and holds (mines nothing) until ErsatzTV signals readiness. The definitive + ready signal is **the `decisions-validate` CI job green on `main` with 0 legacy-unmigrated** (which + also guarantees every record has `key:`/`status:` and all superseded/retired records are under + `docs/decisions/archive/` — the wing boundary #642 keys off). PR2 merges atomically, so main never + shows a partial state. On merge, post a `#642` comment: "ready to mine — decisions-validate green on + \". Do NOT rely on `archive/` merely appearing; the green-validator sha is the go signal. + (Design note: supersession EXTRACTS a single record from a multi-record topic file into `archive/`, + leaving that file's other active records in place — do not repeat metadata per section; the wing + boundary is the guarantee, so chunks 2..n of a record need no inline status.) ---