diff --git a/.abcd/development/intents/drafts/itd-93-abcd-scaffolds-a-hardened-changelog-driven-release-gate-into.md b/.abcd/development/intents/drafts/itd-93-abcd-scaffolds-a-hardened-changelog-driven-release-gate-into.md index 438dcb0..7ce916e 100644 --- a/.abcd/development/intents/drafts/itd-93-abcd-scaffolds-a-hardened-changelog-driven-release-gate-into.md +++ b/.abcd/development/intents/drafts/itd-93-abcd-scaffolds-a-hardened-changelog-driven-release-gate-into.md @@ -118,21 +118,34 @@ at its first public release. ## Open Questions -- **Which surface scaffolds it?** An `ahoy install` step, a new - `abcd launch setup` / `abcd release init` sub-verb, or an `embark`-time - record family? Leans toward an explicit, opt-in verb (release CI is a - deliberate, outward-facing addition, not part of bare install). -- **How much is templated vs. copied?** A verbatim copy of abcd-cli's fixed - workflows risks drift as abcd's own evolve; a template needs per-repo - substitution (check-name list, module path, Go version). Prefer a template - with a lockstep test against abcd-cli's own workflows so the shipped pattern - can't silently diverge from the proven one. -- **Private→public activation.** abcd-cli's gate was dormant while private and - activated on the public flip — which is *how the flaw stayed hidden*. Should - the scaffolded gate be exercisable while private (e.g. a dry-run mode) so a - managed repo discovers problems before going public? -- **Relationship to itd-73** (derived versioning) — the scaffold should leave a - clean seam for the derived-version number to feed the CHANGELOG roll. +_All four resolved in the 2026-07-24 maintainer grill (see DECISIONS.md, +2026-07-24 entries). The PRD is synthesised from that interview; promotion is +queued in `../../plans/2026-07-24-next-run-queue.md` (Track 1)._ + +- **Which surface scaffolds it?** RESOLVED: a `launch` sub-verb (e.g. + `abcd launch scaffold`) — launch already owns how a release is cut and + gated; explicit and opt-in; extends the existing 04-launch chapter. + Rejected: new top-level verb (new surface to reconcile), `ahoy install` + step (release CI silently arriving with install is the non-deliberate path + this intent argues against), embark-time record family (couples to a + round-trip most managed repos won't use). +- **How much is templated vs. copied?** RESOLVED: **self-scaffold parity** — + one template; abcd-cli's own `release.yml`/`auto-release.yml` are + regenerated from it (with abcd-cli's substitutions) and a test asserts the + tree matches the template output. The proven pattern and the shipped + template are one artifact by construction; every abcd release exercises the + exact machinery managed repos get. Rejected: lockstep diff test between two + hand-maintained artifacts; frozen verbatim copy. +- **Private→public activation.** RESOLVED: **built-in rehearsal mode** — the + scaffold ships a `workflow_dispatch` dry-run that arms the full gate + against a simulated changelog roll and reviewed-content commit, asserts the + gate admits it, and publishes nothing. The runbook makes a green rehearsal + the precondition for the first real release. +- **Relationship to itd-73** (derived versioning) — RESOLVED: the CHANGELOG + dated-heading format **is** the seam; `auto-release` keys on the newest + dated heading, so `launch ship`'s derived version is one optional producer + and a hand-rolled heading fires the same machinery. The scaffold stays + producer-agnostic. ## References diff --git a/.abcd/development/intents/planned/itd-28-rp-reviews-into-flow.md b/.abcd/development/intents/planned/itd-28-rp-reviews-into-flow.md index 282170a..9c65d6c 100644 --- a/.abcd/development/intents/planned/itd-28-rp-reviews-into-flow.md +++ b/.abcd/development/intents/planned/itd-28-rp-reviews-into-flow.md @@ -26,7 +26,7 @@ severity: major ## Press Release -> **abcd lands every spec-tied review next to the spec it reviewed, in the native review store, pinned to the commit it reviewed, with a sanitisation pass before commit.** When a plan-review or impl-review finishes — whichever oracle adapter produced it — an abcd-side post-processor captures the review receipt via the native receipt contract and lands a canonical JSON sidecar (`review.json`) and rendered Markdown view (`review.md`) in a per-review directory at `.abcd/reviews//--/`. The sidecar carries the full sanitised review body, structured findings, and a `review_of_commit` SHA pin so future agents can detect when a review's findings have gone stale. Raw transcripts land in a per-review `raw/` subdirectory (gitignored). A two-stage redaction scheme applies: Stage 1 is a write-time sanitiser (AWS, GCP, Azure, Cloudflare, GitHub, Anthropic, OpenAI, Stripe, Slack, JWT, PEM) before any file is written; Stage 2 is a `gitleaks protect --staged --redact=100` detect-and-block gate that rejects commits if secrets survive Stage 1. An on-demand `reviews-index --spec ` regenerates `INDEX.md` + `INDEX.json`; CI runs `--check` mode to catch drift without ever writing to the working tree. +> **abcd lands every spec-tied review next to the spec it reviewed, in the native review store, pinned to the commit it reviewed, with a sanitisation pass before commit.** When a plan-review or impl-review finishes — whichever oracle adapter produced it — an abcd-side post-processor captures the review receipt via the native receipt contract and lands a canonical JSON sidecar (`review.json`) and rendered Markdown view (`review.md`) in a per-review directory at `.abcd/reviews//--/`. The sidecar carries the full sanitised review body, structured findings, and a `review_of_commit` SHA pin so future agents can detect when a review's findings have gone stale. Raw transcripts land in a per-review `raw/` subdirectory (gitignored). A two-stage redaction scheme applies: Stage 1 is a write-time sanitiser (AWS, GCP, Azure, Cloudflare, GitHub, Anthropic, OpenAI, Stripe, Slack, JWT, PEM) before any file is written; Stage 2 is a detect-and-block commit gate run through the scanner seam — native patterns by default, `gitleaks protect --staged --redact=100` as the stronger opt-in adapter when the binary is present, the engine always reported — that rejects commits if secrets survive Stage 1. An on-demand `reviews-index --spec ` regenerates `INDEX.md` + `INDEX.json`; CI runs `--check` mode to catch drift without ever writing to the working tree. > > "Reviews used to die on the laptop they were generated on, in a folder I had to know about," said Frank, SRE. "Spec-tied reviews live where the spec lives. When I clone the repo six months later, every review comes with it — and `staleness: 14_commits` tells me at a glance which ones I should re-run." @@ -61,7 +61,7 @@ The unscoped-transport sweep is adapter-scoped and runs only when an oracle adap - **Verdict enum locked**: `{SHIP, NEEDS_WORK, MAJOR_RETHINK}` — the canonical review verdict enum, shared by every oracle adapter. - **Sequence allocation**: `flock` with 5s timeout; up to 5 retries with 100ms exponential backoff on contention. No fallback filename variants — if all retries fail, exit non-zero with guidance. - **Directory convention**: `--/` where `` = 7-char short SHA (when `pinning: "commit"`) or literal `unpinned` (when `pinning: "none"`). -- **Two-stage redaction**: Stage 1 write-time sanitiser strips home-dir paths, AWS/GCP/Azure/Cloudflare/GitHub/Anthropic/OpenAI/Stripe/Slack/JWT/PEM secrets before any file is written. Stage 2 detect-and-block runs `gitleaks protect --staged --redact=100` and blocks commits if secrets survive Stage 1. +- **Two-stage redaction**: Stage 1 write-time sanitiser strips home-dir paths, AWS/GCP/Azure/Cloudflare/GitHub/Anthropic/OpenAI/Stripe/Slack/JWT/PEM secrets before any file is written. Stage 2 detect-and-block runs through the **scanner seam** (decided 2026-07-24, maintainer grill — see DECISIONS.md): the native pattern engine is the default; `gitleaks protect --staged --redact=100` is the stronger opt-in adapter when the binary is present; the hook reports which engine ran (loud staging — no silent downgrade); CI's gitleaks pass remains the authoritative backstop. Native-vs-gitleaks pattern parity (iss-96) is in scope for the spec. No new hard dependency — adr-22 holds. - **Size caps**: `body_max_bytes` (default 20 KiB, bounds `body_markdown`); `render_max_bytes` (default 24 KiB, bounds `review.md`). Both caps recorded in `review.json`. - **`.gitignore`** allow-lists the native review store `.abcd/reviews/`; ignores each per-review `raw/` subdirectory (`.abcd/reviews/**/-*/raw/`). - **Index discovery**: `reviews-index --spec ` generates `INDEX.md` + `INDEX.json` on demand (no new command surface). CI verifier runs `--check` mode on PRs touching `.abcd/reviews/**`. No git hooks — on-demand plus CI only. @@ -79,7 +79,7 @@ The unscoped-transport sweep is adapter-scoped and runs only when an oracle adap - **One-shot import tool** for reviews sitting in an external adapter's own storage — explicitly out of scope. - **Cross-spec review aggregation, sigstore signing, IDE integration, scoring/trends** — out of scope. - **Modifying ephemeral build artifacts** (`/tmp/review-prompt.md`, `/tmp/re-review.md`) — keep these in `/tmp/`. -- **Hand-rolling redaction regexes** — use gitleaks instead. +- **Hand-rolling a new redaction engine for this feature** — Stage 2 reuses the scanner seam's canonical patterns as its native default; gitleaks provides the deeper ruleset as the opt-in adapter. - **Replacing the review pipeline** — this intent adds storage + governance, not a new oracle adapter. - **Automatic git-hook regeneration of INDEX.md** — practice-scout established this is the canonical anti-pattern (pre-commit#2240 re-stage loop, post-commit feedback loops). On-demand only + CI verifier. - **Unscoped oracle transport storage** — covered by the adapter-scoped sweep into `.abcd/work/reviews/`. @@ -92,7 +92,8 @@ The unscoped-transport sweep is adapter-scoped and runs only when an oracle adap - **Given** the post-processor is killed mid-write (`kill -9`), **when** the persona inspects the working tree, **then** no `.tmp` or partial files are visible to git. - **Given** 5 concurrent post-processor invocations on the same spec, **when** they complete, **then** 5 distinct sequence numbers exist (no collisions). - **Given** the persona sets `ABCD_REVIEW_POSTPROCESS=0` and runs a plan-review, **when** the review completes, **then** the post-processor exits 0 with no side effects and the review remains only in the producing oracle adapter's raw output. -- **Given** a staged `.abcd/reviews/**` file containing a multi-cloud secret (AWS access key, fine-grained GitHub PAT, Anthropic key, JWT, or PEM private key) that was NOT caught by Stage 1, **when** the pre-commit hook runs `gitleaks protect --staged`, **then** the commit is blocked with the finding path/line/rule reported (never the raw secret value). +- **Given** a staged `.abcd/reviews/**` file containing a multi-cloud secret (AWS access key, fine-grained GitHub PAT, Anthropic key, JWT, or PEM private key) that was NOT caught by Stage 1, **when** the pre-commit hook runs the Stage-2 scan (native engine, or gitleaks when present), **then** the commit is blocked with the finding path/line/rule reported (never the raw secret value). +- **Given** the gitleaks binary is absent, **when** the pre-commit hook runs the Stage-2 scan, **then** the native engine runs and the hook output names the engine that ran — a downgrade is never silent. - **Given** a committed `.abcd/reviews/**/*.md` file containing `AKIAIOSFODNN7EXAMPLE`, **when** the pre-commit hook runs, **then** the EXAMPLE-allowlisted value is NOT redacted. - **Given** a review file with a `review_of_commit` SHA that fails `git rev-parse --verify`, **when** the pre-commit hook runs, **then** the commit is rejected with a clear error message. - **Given** a `review.json` with `body_markdown` exceeding `body_max_bytes`, **when** the pre-commit verifier runs, **then** the commit is rejected with guidance (the post-processor truncates automatically; this acceptance captures the case where someone manually edits the sidecar to violate the cap). diff --git a/.abcd/development/plans/2026-07-24-next-run-queue.md b/.abcd/development/plans/2026-07-24-next-run-queue.md new file mode 100644 index 0000000..fac6eb1 --- /dev/null +++ b/.abcd/development/plans/2026-07-24-next-run-queue.md @@ -0,0 +1,94 @@ +# Next implementation-run queue (2026-07-24) + +**Status:** the backlog for the next autonomous implementation run, consumed by +the generic protocol at +[`2026-07-12-abcd-run-protocol.md`](2026-07-12-abcd-run-protocol.md). This file +supersedes the pick-up role of +[`2026-07-18-next-drain-run-queue.md`](2026-07-18-next-drain-run-queue.md) +(itd-93's readiness gates listed there are now cleared — see the 2026-07-24 +DECISIONS.md entries; that file remains the record of why they were gates). + +Run contract, unchanged: `make preflight` is the sole gate; ledger is +capture-only; correctness + security reviews before each PR; one PR per item; +never merge, never commit to main. Prioritisation lens (maintainer, +2026-07-24): abcd is designed while being built — prefer work that speeds +abcd's own build loop or gets new functionality into early dogfooded use. + +## STOP conditions (this run) + +Hitting one means stop and report, never push through (per the playbook): + +1. **itd-93 PRD synthesis ambiguity** — the PRD is synthesised from the + 2026-07-24 grill decisions (DECISIONS.md). If synthesis requires an + interpretation the grill did not settle, STOP; do not invent the bar. +2. **receipt_gate schema** — iss-122 adds manifest-hash and tier fields to the + receipt contract. Any change beyond adding those fields (renaming, removing, + re-gating existing fields) is a STOP. +3. **Missing or ambiguous plan/spec file** — fail closed; never synthesise a + substitute record. +4. **Any fix ahead of an armed detector** — record the finding first + (capture-only), then fix behind it. + +## Track 1 — loop friction + grill consequences (small, mechanical) + +1. **iss-117** — `capture resolve` / `intent seedDraft` gain the `impact` + field so abcd's own verbs satisfy its own validators. Root-cause class: + the write paths, not the validators. +2. **iss-115 / iss-120** — one allocator fix for the class: record-id minting + (`iss-` / `itd-` / `spc-`) must not collide across parallel branches. + Detectors are armed (see iss-120); fix the class, not the site. +3. **iss-101 / iss-102** — lock the lockless load-modify-write paths + (history index registerRepo; capture orphan sweep vs commit). +4. **iss-75** — always-latest dev install mode, so the dogfooded binary is + the tip build. +5. **iss-35 → resolved/** — via `abcd capture resolve`; the graduation gate + it stayed open for is shipped and armed (decision 2026-07-24). +6. **iss-122** — implement the pinned crosscheck gate: committed input + manifest under `.abcd/development/release-gate/` (doc list, directions, + checker count, prompt hash); tiered depth (full for feature/breaking, + Direction-B shallow for patch); receipt echoes manifest hash + tier; + receipt_gate refuses on tier/manifest mismatch or undispositioned + findings — procedural refusal only, findings themselves route to the + maintainer (verifier-selects-gates-decide). +7. **itd-93 amend + promote** — fold the four settled design decisions into + the intent (launch sub-verb; self-scaffold parity; built-in rehearsal + mode; changelog-heading seam), synthesise the PRD from the grill, + `abcd intent plan itd-93` → planned/, kind standalone, severity minor. + **Promotion only — implementation is NOT in this run** (feature-class; + warrants its own focused run per the 2026-07-18 shape note). + +## Track 2 — itd-94 implement-readiness gate + +`abcd intent ready ` per spc-9: the four checks (bucket, acceptance +criteria, spec link, spec body), strict exit-code contract, refusal with +remedy. Self-contained, zero open questions. Lands the machine version of the +run-curation discipline this very queue applies by hand. + +## Track 3 — probe hardening, then the itd-88 coverage experiment + +1. Walk fixes first, so the experiment's verdicts are trustworthy: + **iss-111** (open-question marker false positives), **iss-112** (unbounded + ReadDir), **iss-114** (O(entries×depth) walk), **iss-116** (skip-set + misses non-Go/Node ecosystems). +2. **itd-88** (spc-3) — `/abcd:disembark probe` + `coverage`, read-only, + cite-or-be-dropped. Closing acceptance: a probe run over abcd-cli itself, + and at least one foreign repo, with the coverage report read as the + experiment's finding — the packer is built to whatever section list + survives. + +## Queued for the following run (not this one) + +- **itd-28** — implement against the 2026-07-24 adapter decision: Stage 2 + through the scanner seam, native default, gitleaks opt-in adapter, engine + reported loudly, CI gitleaks as backstop; iss-96 pattern parity in scope. +- **itd-93 implementation** — focused run once promoted. +- **Launch chain (itd-66 → itd-65 → itd-72)** — grilled and PRD-ready; + hardens shipping, exercised once per release; sequenced after the loop + friction and learning items by the 2026-07-24 lens. + +## Also open (recorded so the run sees them) + +- Ledger follow-ups from the 2026-07-18 file remain: iss-104, iss-105 + (itd-93-adjacent), iss-106 — drain candidates once triaged. +- `planned/README.md`'s file listing has drifted from the directory + (iss-38 class); fix opportunistically when touching that directory. diff --git a/.abcd/work/DECISIONS.md b/.abcd/work/DECISIONS.md index 3db87c5..90c3576 100644 --- a/.abcd/work/DECISIONS.md +++ b/.abcd/work/DECISIONS.md @@ -701,3 +701,51 @@ parallel-agent merge contention bites. present-tense brief prose. The 95 confirmed discrepancies are that ratchet skipped at scale; the crosscheck is the measuring instrument; promoting the principle to a mechanical discipline is the open follow-up (iss-121, iss-122). + +- 2026-07-24 — iss-35 resolves: everything it stayed open for is verified + shipped (surface_coverage armed as blocker, 16 surface chapters incl. + docs/history/version, skills→commands relabel, machine-checked staged Status + column, crosscheck wired as release gate). The only residue is iss-122. + Decided in a maintainer grill interview this date. + +- 2026-07-24 — iss-122 design: the crosscheck gate gets a committed input + manifest (doc list, directions, checker count, prompt hash) with TIERED + depth — full depth for feature/breaking releases, Direction-B-only shallow + pass for patch. The receipt must echo the manifest hash AND the tier; + receipt_gate refuses a receipt whose tier mismatches the release's declared + impact. Automated refusal is PROCEDURAL ONLY (manifest/tier mismatch, + undispositioned findings); confirmed findings go to the maintainer, whose + PROMOTE with recorded dispositions is the gate (verifier-selects-gates- + decide). Rejected: hard-blocking on confirmed majors (a stochastic LLM + triage could block a release); never-worse ratchet (drift persists; tiers + make counts incomparable). + +- 2026-07-24 — itd-93 design settled in maintainer grill: (a) surface is a + `launch` sub-verb (extends 04-launch; rejected: new top-level verb, ahoy + install step, embark-time family); (b) SELF-SCAFFOLD PARITY — abcd-cli's own + release workflows are regenerated from the shipped template and a test + asserts parity, so the proven pattern and the template are one artifact + (rejected: lockstep diff test between two artifacts; frozen verbatim copy); + (c) built-in workflow_dispatch REHEARSAL mode — arms the full gate against a + simulated roll, publishes nothing; a green rehearsal is the runbook + precondition for the first real release; (d) the changelog dated-heading + format IS the itd-73 seam — `launch ship` is one optional producer. + Promotes standalone / severity minor, PRD synthesised from the interview + (no grandfathering); the 5 seeded ACs stand, amended for rehearsal mode. + +- 2026-07-24 — itd-28 gitleaks sign-off: Stage 2 runs through the scanner + seam — native patterns are the default engine, gitleaks is the stronger + opt-in adapter when the binary is present, and the hook reports which + engine ran (loud staging). CI's gitleaks pass stays the authoritative + backstop; iss-96 pattern parity folds into the spec. No new hard + dependency — adr-22 holds. Rejected: gitleaks as hard local dependency + (first adr-22 exception, per-machine install burden); CI-only Stage 2 + (secrets reach pushed remote history before CI sees them). + +- 2026-07-24 — Next-run queue reshaped by the grill: the small consequences + fold into Track 1 (resolve iss-35; implement iss-122 pinning; amend + + promote itd-93 — promotion only, implementation later as its own focused + run); the spine stays friction fixes → itd-94 → walk fixes → itd-88. + itd-28 implements in the following run against the adapter decision. + Queue: plans/2026-07-24-next-run-queue.md (supersedes the 2026-07-18 + queue file's pick-up role). diff --git a/.abcd/work/issues/open/iss-122-iss35-crosscheck-scope-and-depth-unpinned.md b/.abcd/work/issues/open/iss-122-iss35-crosscheck-scope-and-depth-unpinned.md index 6c35e82..0d77bae 100644 --- a/.abcd/work/issues/open/iss-122-iss35-crosscheck-scope-and-depth-unpinned.md +++ b/.abcd/work/issues/open/iss-122-iss35-crosscheck-scope-and-depth-unpinned.md @@ -9,4 +9,18 @@ found_during: "v0.4.0 release gate" found_at: ".abcd/development/release-gate/brief-surface-crosscheck.js" --- -The iss35 crosscheck's scope and depth are unpinned, so the gate is not reproducible: v0.3.0's receipt records zero findings four days ago while a full-depth run (17 brief docs, both directions, 22 checkers) returns 102 discrepancies, and the receipt's own promptHash field is the literal 'no-pinned-prompt' admission. The maintainer choosing briefDocs per run means two honest runs of the same gate can disagree by two orders of magnitude; the gate needs a pinned input manifest and depth so a PROMOTE means the same thing every release. \ No newline at end of file +The iss35 crosscheck's scope and depth are unpinned, so the gate is not reproducible: v0.3.0's receipt records zero findings four days ago while a full-depth run (17 brief docs, both directions, 22 checkers) returns 102 discrepancies, and the receipt's own promptHash field is the literal 'no-pinned-prompt' admission. The maintainer choosing briefDocs per run means two honest runs of the same gate can disagree by two orders of magnitude; the gate needs a pinned input manifest and depth so a PROMOTE means the same thing every release. +--- + +**Design decided (2026-07-24, maintainer grill; see DECISIONS.md):** a +committed input manifest under `.abcd/development/release-gate/` pins the doc +list, directions, checker count, and prompt hash, with **tiered depth** — full +depth for feature/breaking releases, a Direction-B-only shallow pass for patch +releases. The receipt must echo the manifest hash **and** the tier, and +receipt_gate refuses a receipt whose tier mismatches the release's declared +impact — so a PROMOTE is unambiguous within its tier. Automated refusal is +**procedural only** (manifest/tier mismatch, undispositioned findings); +confirmed findings route to the maintainer, whose PROMOTE with recorded +dispositions is the gate (verifier-selects-gates-decide). Rejected: hard-block +on confirmed majors; never-worse ratchet. Queued: Track 1 of +`2026-07-24-next-run-queue.md`. \ No newline at end of file