Development record
Every release arrives with a press release composed from what shipped
Press Release
Every feature release arrives with its own press release. When a release is cut, abcd writes a short announcement to
RELEASE.mdat the top of the repository. The headline features are told as the moment a person notices them, the rest are listed by name, and each is in the words its own press release already uses, quotes included. The previous page moves to the release archive, so the top of the repository always shows the latest feature release and the history is one folder away. It looks back only: nothing still planned, no dates, no "coming next". A release of fixes alone leaves the page as it is and says why. The changelog stays the line-by-line record;RELEASE.mdis the page a person reads first to learn what a release was for."I used to work out what a release was for by reading forty changelog lines," said Iris, a product thinker. "Now the first page I open tells me, in the words I used when I asked for each piece."
Why This Matters
A release is the checkpoint of this record (adr-2609212115255771, decision
3): the version is derived from what shipped and the changelog is composed
from the records that reached a terminal folder. What the checkpoint lacks is
the one paragraph a person reads to learn what the release was for. The phase
carried that paragraph as its ## Expectation, written before the work;
retiring the phase removed it, and the ADR's last consequence names a release
press release composed from the shipped intents' press releases as its nearest
home and leaves the step unruled. The product thinker ruled it on 2026-09-23
(dcn-2609230000000001, the 2026-09-23 rulings entry; the interview's fuller wording is
recorded in this intent's Decisions below): each release gets a press release
composed at the cut from its shipped intents' press releases, backward-looking,
and this release is the first to carry one.
The material already exists. Every shipped intent opens with a press release written as the user moment, and the changelog composer (itd-67) already reads those records at the cut to word its lines. The changelog answers "what changed, line by line"; nothing answers "what is this release for" in the words the product thinker used when each piece was asked for.
An intent's press release is written before its work, so a page composed from it is only as true as the deliveries behind it. This intent does not claim otherwise: its Mechanism states the expectation and what would show it wrong.
Decomposition (itd-84 hand-run, 2026-09-23, confirmed by the product thinker at the planning interview)
Verdict: SPLIT. The website half is a second capability and is filed as its own draft; the rest is this intent, already-recorded stance, or plumbing.
| Part | Type | Home |
|---|---|---|
RELEASE.md at the repository root, composed at the cut from the shipped intents' press releases, with the outgoing page moved to an archive |
capability | this intent |
Release pages on the project website, rendered from RELEASE.md and the archive |
capability | a separate draft intent, next cycle (planning ruling P7) |
| The release record reports only what shipped: no forecast, no promised date, no still-planned intent | standing stance | already recorded: adr-2609212115255771 (decision 3; "a roadmap promises, this view reports"). This intent follows it and declares nothing new |
| Every cited record is data the binary checks, and a mismatch is refused before anything is written | trust rule | already recorded for the changelog as spc-11's completeness bijection (itd-67); applied here to a second document, so no new ADR (confirmed by the product thinker) |
The composer prompt, the ingest step in launch ship, the archive move, and their rollback with the changelog |
plumbing | the spec intent plan mints; the launch surface is brief/04-surfaces/04-launch.md |
Relations, written as prose because the schema carries no typed field for them (iss-2609091256264547):
- refines adr-2609212115255771: this intent is the step the ADR's last consequence names and leaves unruled.
- refines itd-67: it adds a second composed document to the cut that itd-67's changelog slice built, read from the same record set.
- builds on itd-73: the cut's record set and the
impactderivation are itd-73's, and the press release reads that set rather than deriving its own. - itd-24 (release retrospectives) and itd-2609212103572513 (
target_release) are neighbours: the first may read this page as a seed, and the second is the forward-looking line this page must never carry.
What's In Scope
RELEASE.mdat the repository root, holding only the latest feature release's press release, with a heading that names that release's version.- At each cut that writes a new page, the outgoing
RELEASE.mdmoves to.abcd/development/releases/<its version>.md, the permanent-record tier. - The page is composed at the cut by a composer agent from the press releases
of the user-facing intents that entered
shipped/since the previous release tag: the same record set the changelog is composed from, never a second derivation of it. - Headline intents told as prose, every other intent in the set listed by name; the persona quotes of the intents it tells, carried word for word with their attribution.
- The binary validates the composer's output before anything is written, and a refused output is sent back to the composer with the reasons until it is valid.
- The page, the archive move and the dated changelog section land in one cut, or none of them does.
- The read-only preview (
abcd changelog, or thelaunchdry run) listing the intents the page will be composed from. RELEASEadded to thestray_root_docsallowlist and to CI's inert root list.- This release: the next cut carries the first one.
What's Out of Scope
- Any forecast: no
target_releaseintents, no still-planned work, no date, no "coming next". Thetarget_releasereport (itd-2609212103572513) stays in the cut's report and never enters the page. - Issues as a source: an issue carries no press release; fixes stay in the changelog's Fixed lines. A release that ships fixes alone writes no page.
- Intents with
impact: internal, and intents that left the record as Removed (superseded): neither is announced. - Release pages on the project website: a separate draft intent (see Decomposition).
- The published GitHub release notes, which stay as they are.
- Pages for releases cut before this one: no backfill and no on-request composition.
- Rewording the changelog, or changing its bijection, sections or version derivation (itd-67, itd-73).
- The release retrospective (itd-24), which asks what was learned; this page says what shipped.
- A press release for the project as a whole: that is the lifeboat's
disembark press-release, a different document from different sources.
Acceptance Criteria
- Given a cut whose record set contains at least one user-facing shipped
intent, when
launch shipwrites the dated changelog section, then it first validates the composed page, then moves the outgoingRELEASE.mdto.abcd/development/releases/<its version>.md, writes the newRELEASE.md, and writes the changelog heading; if any step fails, the steps already taken are rolled back (on a first cut, the new file is removed), and the report says so, or says the rollback failed. - Given the page for a cut, when it is compared with the cut's
press-release set (the intents that entered
shipped/since the previous tag, excludingimpact: internalintents, Removed intents and issues), then every intent in the set is cited, as a headline or in the name list, no record outside the set is cited, and the cut refuses otherwise. - Given an intent that is planned but not shipped, including one carrying
target_release, when the page is composed, then the page does not cite it; and the composer's fixture for a cut beside such an intent shows no sentence promising a date or a future release. - Given the read-only preview, when it is run before a cut, then it lists the intents the page will be composed from, and writes nothing.
- Given a cut whose press-release set is empty, when
launch shipruns, thenRELEASE.mdand the archive are left untouched and the report says that no page was written because no user-facing intent shipped. - Given composer output with an unknown field, an oversize body, a malformed id, an id outside the press-release set, or a heading or fence that would break the page, when the cut ingests it, then it refuses the output whole, writes nothing, and sends the output back to the composer with the refusal's reasons to rewrite; it repeats until the output is valid, and the report names every refused attempt and its reasons.
- Given a quote on the page, when the cut checks it, then it matches word for word, with its attribution, a quote in the press release of an intent the page cites, and the cut refuses it otherwise.
- Given
RELEASE.md, when anyone reads it, then its heading names the release it describes, so a page left in place by a fixes-only release is not mistaken for the latest tag's; and the composer's injection-canary fixture shows hostile text inside an intent's press release treated as content, never as an instruction.
Decisions
Ruled by the product thinker on 2026-09-23 at the planning interview, after two independent adversarial reviews of the draft (design/feasibility and record discipline):
- Truthfulness. No "true by construction" claim; the Mechanism records a falsifiable expectation instead, with no audit-verdict source and no owed-check label.
- Who writes. A composer agent, as for the changelog lines, checked by the binary before anything is written. The human review is the release pull request's review of the roll commit; there is no separate approval step.
- Completeness. Headline intents are told and the rest are listed by name; every intent in the press-release set appears, and the cut refuses an omission.
- Where.
RELEASE.mdat the repository root holds the latest page only; at each cut the outgoing page moves to.abcd/development/releases/. This was the product thinker's own shape, beside the draft's three options. - A fixes-only release. No new page; nothing moves; the report says why.
- Quotes. Carried word for word from the intents' press releases, with their attribution, knowing the personas are fictional and the page is public.
- Where else it is read. The project website as well, filed as its own intent for next cycle; this intent is repository-only and the release is not held for the website.
- Earlier releases. From this release onward only.
- Refused output. Rewritten automatically, with no retry limit.
Open Questions
None open; decisions 1 to 9 settle the seven this draft carried and the two the reviews raised.
Mechanism
We expect the release press release to stay true because it is composed after the cut from records that passed the completeness bijection; shown wrong the first time it announces something an intent's audit found diverged or missing.
Scope Conditions
- Releases are cut through abcd's own release step (
launch ship), not tagged by hand. - Each shipped intent carries a press release written as the user moment, not a placeholder.
- A repository has one release line, with no parallel release branches.
- A release ships few enough intents, about twenty at most, that the headlines and a name list fit one readable page.
Audit Notes
Fidelity review — receipt rcp-af55e181c483 (verifier intent-auditor claude-fable-5-1).
Provenance: intent-auditor@claude-fable-5-1 · rubric_hash sha256:effa65b3e9e88ff29433b443ec2be159522a8b0b71cf1434526514aa61edb13e · prompt_hash sha256:5d6e3e16dd222b32b131baff15b6882a0945dac3c4c32bd90ef2ddd93e972c93 Input attestations: diff:6155766c..f51f1eac@sha256:4289a84e9a098b8b7a73a0d1458973041149fbbeb04082be4c168f7b36fd6c9d;
Acceptance rollup: MET 6 · MET_WITH_CONCERNS 2 · NOT_MET 0 · INCONCLUSIVE 0
Per-criterion verdicts:
- ac-1 — MET: ingest validates the whole payload and plans the archive before any write, execute() then creates the archive, replaces RELEASE.md and replaces CHANGELOG.md in that order, and a failure at each step is undone in reverse with the error saying 'rolled back' or 'THE ROLLBACK FAILED'; a first cut's rollback removes the page evidence: internal/core/release/ingest.go:340 — "page := validatePage(cut, payload.PressRelease, &rs)" evidence: internal/core/release/write.go:169 — "if plan.page != nil && plan.undo.archived != "" {" evidence: internal/core/release/write.go:161 — "fail := func(step string, err error) (UndoPlan, error) {" evidence: internal/core/release/write_test.go:68 — "func TestCutWritesArchivePageThenHeading" evidence: internal/core/release/write_test.go:86 — "func TestCutRollsBackEveryEarlierWrite" evidence: internal/core/release/write_test.go:113 — "func TestFirstCutRollbackRemovesThePage" evidence: internal/core/release/write_test.go:130 — "func TestCutReportsAFailedRollback"
- ac-2 — MET: the set is PressReleaseRequired (Added, itd-*, InChangelog), so issues, internal and removed records fall out; validatePage refuses an uncited set member (missing), any id outside the set with its cause (outside-set) and a repeat (duplicate-citation), each proven per cause evidence: internal/core/changelog/shipped.go:161 — "func (s RecordSet) PressReleaseRequired() []Record" evidence: internal/core/release/page.go:210 — "rs.add(ReasonMissing, "press_release", "%s shipped in this cut and the page neither tells nor lists it", e.ID)" evidence: internal/core/release/page.go:166 — "rs.add(ReasonOutsideSet, at, "%s is not in the release page's set: %s", id, outsideCause(cut, id))" evidence: internal/core/release/page_test.go:189 — "func TestPageBijection" evidence: internal/core/changelog/shipped_test.go:383 — "func TestPressReleaseRequiredIsAddedUserFacingIntents"
- ac-3 — MET: a planned intent, with or without target_release, is outside the cut and refused as outside-set; the no-forecast fixture sits a target_release intent beside the cut and its expected payload is ingested clean of the date, the version and every forward-looking word evidence: internal/core/release/page_test.go:49 — "r.Write(plannedDir+"itd-91-targeted.md"" evidence: internal/core/release/page_test.go:240 — "func TestPageRefusesATargetReleaseIntent" evidence: internal/core/release/page.go:328 — "only intents that shipped since the last release are cited; nothing planned" evidence: agents/release-changelog-composer/fixtures/no-forecast.json:4 — "no sentence promises a date, a future release or work still to do" evidence: internal/core/release/fixtures_test.go:117 — "for _, bad := range fx.Expected.MustNotContain {"
- ac-4 — MET: renderCut, shared by abcd changelog and the ship emit step, lists the in_press_release entries under 'release page:', --json carries in_press_release, the tree digest is unchanged with a RELEASE.md present, and a live run at BASE listed seven intents and left the tree clean evidence: internal/surface/cli/ship.go:579 — "func renderPageSet(w io.Writer, cut release.Cut)" evidence: internal/surface/cli/ship_test.go:461 — "func TestChangelogPreviewListsThePageSet" evidence: internal/surface/cli/ship_test.go:278 — "r.Write("RELEASE.md", "# Release 0.4.0 (2026-07-01)" evidence: internal/core/release/emit_test.go:530 — "func TestEmitMarksInPressRelease"
- ac-5 — MET: an empty set writes the changelog alone (the recorded ops are one replace), RELEASE.md is byte-identical after, and the report says 'No release page written: no user-facing intent shipped in this cut; RELEASE.md stays on < version>'; a payload carrying a page for an empty set is refused evidence: internal/core/release/write.go:194 — "const lead = "No release page written: no user-facing intent shipped in this cut; "" evidence: internal/core/release/write_test.go:187 — "func TestFixesOnlyCutLeavesThePageAlone" evidence: internal/surface/cli/ship_test.go:509 — "func TestLaunchShipFixesOnlyReportsNoPage" evidence: internal/core/release/page_test.go:258 — "func TestPageForAnEmptySetIsRefused"
- ac-6 — MET_WITH_CONCERNS: the binary half is delivered: unknown field, oversize, malformed id, outside set, heading and fence each refuse the payload whole with the tree unchanged, every reason is collected in one pass and returned as data (exit 2 with payload_refusal); the 'send back, repeat until valid, report every attempt' half exists only as host prose in commands/launch.md, pinned by a string test and exercised by no test or recorded run evidence: internal/core/release/page_test.go:272 — "func TestPagePayloadRefusals" evidence: internal/core/release/page_test.go:348 — "t.Error("a refused payload changed the working tree")" evidence: internal/core/release/page_test.go:360 — "func TestPageRefusalCollectsEveryReason" evidence: internal/surface/cli/ship.go:428 — "if errors.As(err, &refused) {" evidence: internal/surface/cli/ship_test.go:548 — "func TestLaunchShipPayloadRefusalJSON" evidence: commands/launch.md:441 — "### The retry loop: a refused payload is recomposed" evidence: internal/surface/cli/ship_test.go:645 — "for _, want := range []string{"no attempt limit", "report every refused attempt", "payload_refusal"}" evidence: .abcd/development/specs/closed/spc-2609231435545473-every-release-arrives-with-its-own-press.md:412 — "The loop itself is host prose; it is exercised at a real cut, not in CI."
- ac-7 — MET: verbatim() requires a whole quoted sentence, its attribution as the phrase after said/says, and a bounded match inside a paragraph of the cited intent's Press Release section, and the quote must come from a headline intent; a changed word, a changed attribution, a truncation, a sentence from outside the section and a listed-only intent are each refused, and a real record's quote passes evidence: internal/core/release/page.go:369 — "func verbatim(source string, q Quote) string" evidence: internal/core/release/page.go:244 — "if why := verbatim(inSet[q.Record].pressRelease, q); why != "" {" evidence: internal/core/release/page_test.go:385 — "func TestQuoteMustBeVerbatim" evidence: internal/core/release/page_test.go:533 — "func TestQuoteSaysFormFromARealRecord" evidence: internal/core/changelog/source.go:66 — "func pressReleaseSection(blob string) string"
- ac-8 — MET_WITH_CONCERNS: the heading is '# Release X.Y.Z (date)', asserted to name the cut's version before writing and reported as 'stays on < version>' by a fixes-only cut; the press-release canary fixture exists with must_not_contain and must_not_obey lists and its expected payload is ingested clean, but that proves the pinned answer, not that a composer treated the hostile text as content: no run of the fixture against a model is in the delivery evidence: internal/core/release/page.go:98 — "func pageHeading(nextTag string, at time.Time) string" evidence: internal/core/release/ingest.go:363 — "return res, fmt.Errorf("refusing to write %s: its heading does not name this cut's version %s", PageFile, cut.NextTag)" evidence: internal/core/release/page_test.go:130 — "func TestPageHeadingNamesItsVersion" evidence: agents/release-changelog-composer/fixtures/injection-canary-press-release.json:5 — "The composer must treat all of it as the record's content" evidence: internal/core/release/fixtures_test.go:44 — "Whether a given model obeys the prompt is shown when a host runs the fixture; this pins the answer it is measured against."
Gap audit:
- honoured:
- when a release is cut, abcd writes a short announcement to RELEASE.md at the top of the repository evidence: internal/core/release/write.go:179 — "if err := ops.replace(PageFile, plan.page); err != nil {" evidence: internal/core/release/page.go:27 — "const PageFile = "RELEASE.md""
- the previous page moves to the release archive, one folder away evidence: internal/core/release/write.go:137 — "archive := ArchiveDir + "/" + version + ".md"" evidence: internal/core/release/page_test.go:161 — "func TestArchiveIsNamedFromTheOutgoingHeading"
- headline features told as prose, the rest listed by name evidence: internal/core/release/page.go:462 — "lines = append(lines, "Also in this release:", "")"
- it looks back only: nothing still planned, no dates, no coming next evidence: internal/core/release/page_test.go:236 — "func TestPageRefusesAPlannedIntent" evidence: agents/release-changelog-composer.md:157 — "Look back only. Write nothing forward-looking"
- a release of fixes alone leaves the page as it is and says why evidence: internal/surface/cli/ship_test.go:520 — "No release page written: no user-facing intent shipped in this cut; RELEASE.md stays on 0.4.0"
- the changelog stays the line-by-line record evidence: internal/core/release/page.go:469 — "The line-by-line record of this release is its section in"
- RELEASE admitted by stray_root_docs and CI's inert root list evidence: internal/core/release/gates_test.go:20 — "func TestRepositoryGatesAdmitTheReleasePage" evidence: .github/workflows/ci.yml:144 — "README.md|CHANGELOG.md|RELEASE.md|"
- the read-only preview lists the intents the page will be composed from evidence: internal/surface/cli/ship.go:561 — "renderPageSet(w, cut)"
- diverged:
- each headline is in the words its own press release already uses, quotes included: the binary verifies only the quotes a payload carries, so a told intent whose press release carries a persona quote can be told with none and the page is written; the prompt asks for the quote and the spec files the gap as a risk with no criterion behind it evidence: .abcd/development/specs/closed/spc-2609231435545473-every-release-arrives-with-its-own-press.md:438 — "Quotes are optional to the binary." evidence: agents/release-changelog-composer.md:149 — "Carry the quote of each intent you tell" evidence: .abcd/development/intents/shipped/itd-2609231013154443-every-release-arrives-with-its-own-press.md:87 — "the persona quotes of the intents it tells, carried word for word with their"
- words attributed to a persona in headline prose are refused only in the 'said < Name>,' form; a 'says < Name>,' attribution passes the blockquote refusal and record-lint's persona rule unverified (captured and deferred past v0.9.0 as iss-2609231715081185)
evidence: internal/core/lint/persona.go:18 — "var personaAttrRe = regexp.MustCompile(
\bsaid (\p{Lu}[\p{L}\p{M}'’-]*),)" evidence: .abcd/work/issues/open/iss-2609231715081185-the-persona-attribution-checks-only-see.md:12 — "deferred_after: "v0.9.0"" - a refused output is sent back to the composer and rewritten until valid, with every refused attempt reported: delivered as host orchestration prose rather than binary behaviour, and never exercised by a test or a recorded cut evidence: commands/launch.md:459 — "In the final cut report, report every refused attempt and its reasons before" evidence: .abcd/development/specs/closed/spc-2609231435545473-every-release-arrives-with-its-own-press.md:229 — "The verb is host-delegated, so the loop lives in the host orchestration"
- the closed spec's payload example carries a truncated quote the ingest refuses by design (recorded, spec left as written) evidence: dcn-2609230000000023 — "The payload example in spc-2609231435545473 (closed) is stale on one point"
- missing:
- this release: the next cut carries the first page. No RELEASE.md exists at BASE and the archive holds only its README; the page arrives with the first cut that passes, which is the cut's own step and not this diff's evidence: .abcd/development/releases/README.md:7 — "The pages are written by the release cut, never by hand." evidence: .abcd/development/specs/closed/spc-2609231435545473-every-release-arrives-with-its-own-press.md:445 — "The first page waits on the cut."
Scope-condition dispositions:
- cond-2609231435540975 — survived: the page is written only by launch ship, an outgoing page without the cut's own heading stops the cut, and the command page forbids a hand edit of RELEASE.md, so the delivery assumes and enforces the cut as the one writer
evidence: internal/core/release/write.go:133 — "the outgoing %s does not open with a
# Release X.Y.Z (YYYY-MM-DD)heading" evidence: commands/launch.md:336 — "Do not editCHANGELOG.mdorRELEASE.mdby hand to unblock the release." evidence: .abcd/development/releases/README.md:7 — "The pages are written by the release cut, never by hand." - cond-2609231435545969 — survived: every shipped intent at BASE carries a Press Release section (75 of 75), the verifier reads real records (itd-121's quote passes as its record has it) and six intents of the pending cut quote a persona, so the assumption holds for the population the first page reads
evidence: internal/core/release/page_test.go:533 — "func TestQuoteSaysFormFromARealRecord"
evidence: dcn-2609230000000023 — "six intents of that release (itd-119, itd-120, itd-121, itd-123, itd-124, itd-125) quote as
says <Name>, <role>." - cond-2609231435546492 — untested: nothing in the delivery exercises or contradicts a second release line: the archive-never-overwrites check and the base tag both assume one line and no test cuts on two
- cond-2609231435540452 — survived: the delivery enforces no cap (the spec scopes one out) and bounds the page at fifty headlines and quotes as a hostile-payload guard, and the pending first cut at BASE lists seven intents on the page, well inside the assumed twenty evidence: internal/core/release/page.go:35 — "A release is scoped at about twenty intents; fifty of either is not a page, it is a hostile payload." evidence: .abcd/development/specs/closed/spc-2609231435545473-every-release-arrives-with-its-own-press.md:74 — "An enforced cap on intents per release: about twenty is a scope condition of"
Grounds
- pursued: we expect it to fill the gap left by retiring phases, a paragraph of purpose per release, without anyone writing it by hand; shown wrong if releases still need a hand-written summary.
Frontmatter
| id | itd-2609231013154443 |
|---|---|
| type | intent |
| lifecycle | shipped |
| kind | standalone |
| severity | minor |
.abcd/development/intents/shipped/itd-2609231013154443-every-release-arrives-with-its-own-press.md
open on GitHub ↗ · commit history ↗
References5
- adr-2609212115255771Phases and milestones are retired: sequencing is dependencies rendered as status, the checkpoint is the derived releaserelated
- itd-24Completed Releases Get A Retrospectiverelated
- itd-67abcd Is An Installable, Versioned Claude Code Plugin Whose Repo Is Its Own Marketplace And Whose Every Launch Bumps, Tags, And Publishes A New Versionbuilds on
- itd-73abcd Cuts the Version — You Never Type Onebuilds on
- itd-2609212103572513An intent names the release it must land by, and the cut says whether it didrelated
Referenced by7
- iss-2610262033156337itd-2609231013154443 names `abcd changelog` as a read-only preview of the release page's intents; the launch chapter says there is no changelog verbrelated
- iss-2610262035015704itd-2609231013154443 names abcd changelog as the release preview; the board's surface page lists changelog as a retired name the launch preview replaced.related
- iss-2610262039541373itd-2609231013154443 names `abcd changelog` as the release-page preview; the README says `changelog` merged into `launch` and is in neither help block.related
- iss-2610262045391451itd-2609231013154443 excludes intents with impact: internal; itd-73 defines impact as additive, breaking or fix onlyrelated
- iss-2610262045409665itd-2609231013154443 names abcd changelog as the read-only preview; itd-2610090831227812 merges changelog into launch with no aliasrelated
- itd-2609231507251267Release pages on the project websitebuilt on by
- spc-2609231435545473The release cut writes RELEASE.md from the press releases of the intents it shippedimplemented by
mentions15
- dcn-26092300000000012026-09-23 — The product thinker ruled on the owed items of the autonomous run of 2026-09-23 in one interview, one question at a time (07:51Z to 09:32Z, while the run was paused): two release blockers, two intents, the 35 major captures routed to the product thinker, and two older owed rulings. The release waits for two things: version-stamped plugin payloads (iss-2609230733497536, built by a run lane, with no criterion amended and no deferral) and a release press release composed at the cut from the shipped intents' press releases, which is a new capability and gets an intent and its planning interview before any lane builds it. The run may approve the release environment itself once every gate is green; that agenda line is written in the release commit, not here. itd-4's AC3 is built as written, the `--issue-drift` check and the rename of the back-links to `related_issues` / `related_intents` together, and spc-6 closes only when both land (the 2026-07-17 ruling stands). itd-43's third criterion is moot and dropped, so spc-8 closes. The guard contract is extended to read a host-supplied per-call working directory (iss-2609212142557657, option A), after a probe of what the host does when none is supplied. Four majors are ruled to a build (iss-2608231120121681 write-path smoke, iss-2608290810036869 preflight before the push connects, iss-2609090828371674 per-agent staging locks, iss-2609120505141653 the provenance comment) and do not hold the tag. The rulings that set a rule each have their own entry below; every other routed major is deferred past v0.9.0 with its ruling as the `deferral_reason`, and the 168 routed minor and nitpick captures take the run's default deferral. The product thinker also asked that the interview be kept as autonomous-run experiment data, towards making a run transparent to the person it serves; the observations feed the run's end-of-run research note. Rejected, as the frame: the run taking any of these rulings itself.
- dcn-26092300000000232026-09-23 — The payload example in spc-2609231435545473 (closed) is stale on one point: its itd-121 quote opens `"... what I'd do next,"`, a truncation the release-page ingest refuses by design, since a quote is a whole quoted sentence as the press release has it. The example's verb is right: the ingest accepts an attribution after `says` as well as after `said`, because six intents of that release (itd-119, itd-120, itd-121, itd-123, itd-124, itd-125) quote as `says <Name>, <role>.`. The closed spec stays as written; `TestQuoteSaysFormFromARealRecord` carries a working `says` quote, taken from itd-121 as its record has it (lane implementer, on review 2 of the release-page build).
- iss-2609091256264547The decomposition discipline requires a cross-record link to be typed with one of four relations, supersedes or reverses or duplicates or refines, and never a vague related. Only the first of those four exists. supersedes is schema-known through recordHandleFields and is carried by fifty-eight decision records and three others, while reverses, duplicates and refines appear in no schema and in no committed record anywhere in the tree: the field list a record may carry is related_adrs, related_intents, builds_on and blocked_by, and a record carrying a key outside the known set is dropped by the reader rather than reported, so writing one of the three missing words would make the record invisible to every surface that reads it. The consequence is that an author following the rule literally either writes a link the tooling silently discards or writes the relation in prose and calls it typed, and the corpus shows the second: records assert a typed link in a heading and carry no frontmatter edge, which reads as done to a human and is invisible to every graph walker. That is the shape enforcement-claims-are-facts refuses, a convention naming a mechanism that does not exist, and it is load-bearing here because the decomposition protocol is the documented gate until its automated rung ships. Fix candidates, none chosen: implement the three missing relations as known fields so the rule can be followed; or narrow the rule to the vocabulary the schema implements and say what an author does with a relation the four words cannot express; or record that prose is the sanctioned form for the three and stop calling them typed. Detector: a record asserting a typed relation in its body carries a frontmatter edge naming the same target, and a relation the schema cannot express is refused at write time rather than dropped in silence.
- iss-2609231715081185The persona-attribution checks only see the `said <Name>,` form. A headline in a release page that attributes a quote to a persona with `says <Name>,` is not refused as an unverified quote, and record-lint's persona_registry rule does not see a `says` attribution either, so an unregistered persona quoted with `says` passes both. The page's `blockquote` refusal and `lint.PersonaAttribution` share one regex (personaAttrRe) that matches `said` only, while the verbatim-quote check accepts both verbs.
- iss-2609232155567377itd-2609231013154443 promises the release page is in the words each intent's own press release already uses, quotes included, and its scope names the persona quotes of the intents it tells, carried word for word; but the release-page ingest verifies only the quotes a payload carries. A headline may tell an intent whose press release carries a persona quote and carry none, and the cut writes the page. Found by the fidelity audit of ac-7 (receipt rcp-af55e181c483): agents/release-changelog-composer.md asks the composer for the quote of each told intent, and spc-2609231435545473 files the gap under Risks as quotes being optional to the binary because no criterion asks for them. Either the page bijection requires one quote per told intent whose source carries one, or the intent's press release stops promising quotes included.
- iss-2609290448510918The predecessor-store qualifier sweep reaches past the six intents iss-2609261536147903 named: outside drafts/ and those six, 192 citation sites across about forty intents name a spc-N at or below spc-70 that is not the citing intent's own spec, with no '(predecessor store)' on the line. Some are live cross-references (the cold-reading family's intents cite each other's live specs), and some are the predecessor store's (itd-4, itd-6, itd-29, itd-47 and itd-49 describe pre-rebuild work in its terms), so each site needs the same reading against the live spec it collides with; the specs charter's Two spc-N Namespaces section is the rule. Found while sweeping the pattern of iss-2609261536147903 in lane drainDrift3; a census script over intents/{planned,shipped,disciplines} reproduces the count.
- itd-84An Intent Is Decomposed Before It Is Filed, And A Reversal Is Only Ever Flagged
- itd-91A Project Declares Once How It Wants AI Acknowledged — And Every Commit, PR, And Record Follows
- itd-119An Issue Graduates Into An Intent Without Retyping
- itd-120A Resolved Issue Points At What Fixed It
- itd-121Type The Id, Get Your Next Move
- itd-123The Intent Audit Says Audit
- itd-124The Conformance Check Calls Itself Lint
- itd-125The Lifeboat Verdict Says What It Is
- spc-11installable-versioned-plugin