Development record
An admission and a surprise are written by a verb, and the order the design fixes is a refusal
Typed links: builds_on itd-189 (the admission and surprise schemas), itd-180 (dispositions), itd-185 (the ingest verb); refines itd-180 (admission is the accepted disposition plus the admission record, written as one act, flagged for the maintainer).
Press Release
What the widening reading proposes is admitted or declined through a command.
abcd capture admit <rdi-N> --grounds "<why>"records an admission as one act: the item'saccepteddisposition, carrying the grounds, and the admission record that joins it to the run's candidate set.abcd capture surprise --occasioned-by <id> "<what>"writes one surprise entry as its own record. Declining stays what it already is, a disposition in thedeclinedstate. An admission is refused until the comparative reading over that run has been ingested or recorded as not exercised, because the design characterises first and admits second.abcd <id>dispatches onadm-Nandsrp-N, which no record dispatch reaches today, and the outstanding report says at any moment which widening items carry neither an admission nor adeclinedorhelddisposition.
"Every proposal I took into the candidate set carries the reason I took it, written at the moment I took it, and every one I passed over says I passed over it," said a facilitator who runs the loop for a researcher-developer. "The verb refuses to let me admit before the characterisation is in, so the record shows the order happened the way the design says it must."
Why This Matters
itd-189 places the recording burden on admission: rejecting a proposal costs nothing epistemically, and admitting one into the candidate set is where the frame is engaged. Its scope text says the enforcement is hand-run in Iteration 1, no reading running to produce proposals, and enforced at the command in Iteration 2. Iteration 1 delivered the schemas: the admission family, the surprise family, the store layout and the gate that refuses a blank ground on a committed record. It delivered no verb, and its fidelity verdict named filing the enforcement intent as "the concrete next step this verdict asks for".
The gate that reads committed records has two open defects that a verb closes for the records it writes: its blank refusal decides on literal spellings rather than on the YAML null and empty class (iss-2608301808198621), and a trailing comment on a key defeats every spelling it refuses (iss-2608301744268001). Both belong where the scanner lives and are fixed there, in their own change; a verb that cannot write a blank is the other half.
The ordering is ruled: Step 2 precedes Step 4, and admission is performed after the comparative reading. Under the rule that commands are the write path, a fixed order is a refusal in the verb, not a sentence in a protocol.
Decisions flagged for the maintainer
- Admission is one act with two records. itd-180's ruling is that at the widening position acceptance is admission, and itd-189 shipped an admission record carrying grounds. Today an item with an
accepteddisposition is still reported as unadmitted. This intent makescapture admitwrite theaccepteddisposition and the admission record together under the ledger lock, the disposition carrying the grounds; whereacceptedalready stands, it writes the admission record alone. This refines itd-180 and is flagged rather than assumed.
What's In Scope
abcd capture admit <rdi-N> --grounds "<text>", writing theaccepteddisposition through the existing disposition validator andadmissions/<run-id>/adm-N.mdwith the proposal, the run and the grounds, minted on the timestamp seam, under the ledger lock. It refuses an item that is not a widening item, an item already admitted, an item carrying a standing disposition other thanaccepted, and a ground that does not meet the substance floor the grounds primitive already applies.- The ordering as one gate in the shared disposition writer. At the widening position, any disposition (accepted, declined or held) and any admission refuses until a committed comparative run names the item's run, and names what it is waiting for. The gate lives in the writer every verb routes through, so neither
capture dispositionnor the scribe's ingest can land an acceptance before characterisation. abcd capture surprise --occasioned-by <rdi-N|adm-N|dsp-N> "<text>", writingsurprises/srp-N.mdas its own record, never as a field on a disposition, and refusing an occasion that does not resolve.- Dispatch.
abcd adm-Nandabcd srp-Nreport the record and its joins. The dispatcher covers issues, intents, specs and ADRs today; the reading families (rdi,dsp,rdg) stay outside it and are named as out of scope. - The outstanding report names every widening item of a run that carries neither an admission nor a
declinedorhelddisposition, so the admitted-against-declined count is a query rather than an inspection. - The plugin surface page for capture documents the two verbs and the ordering.
What's Out of Scope
- The scanner fix for absence as a class. It is two recorded issues and ships in its own change with its own trailers.
- A change to the disposition vocabulary. Declining is the
declinedstate and stays so. - Enforcing that a session ended. The report answers the question whenever it is run.
- The comparative channel itself, which is its own intent; this verb only reads whether that run's outcome exists.
- Dispatch on
rdi-N,dsp-Nandrdg-N, which spc-67 records as a residual and which this intent does not close.
Mechanism
We expect a verb that refuses a blank ground to make the admission asymmetry legible because the count that evidences ownership is admitted against declined, and a record that can only be written with a stated reason turns that count into something a query answers rather than something a reader reconstructs. It fails if the verb is bypassed by hand-written records, which the gate exists to catch and which the scanner fix makes it catch as a class.
Scope Conditions
- The ordering gate reads the comparative run the channel commits, which the comparative-channel intent defines (an empty item set records the not-exercised outcome), and the channel lands in Phase A before this verb.
- Grounds on admission use the same substance floor as every other grounds primitive. A different floor for admissions is a ruling this intent does not make.
- The verb is written for the widening position only, because admission is the widening reading's warm act by design.
Acceptance Criteria
- Given a widening item with no admission and no disposition, and a comparative run ingested over its run, when
capture admitruns with a ground meeting the floor, then anaccepteddisposition and one admission record exist naming the item and the run, and a secondcapture admiton the same item refuses. - Given a widening item with a standing
accepteddisposition and no admission, whencapture admitruns, then one admission record is written and the disposition is untouched. - Given the same item before any comparative run names its run, when
capture admitorcapture dispositionruns on it, then it refuses and names what it is waiting for. - Given a widening item with a standing
declineddisposition, whencapture admitruns, then it refuses and names the disposition. - Given
capture admitwith a blank, whitespace or degenerate ground, when it runs, then it refuses and nothing is written. - Given
capture surprisewith an occasion that resolves, when it runs, then one surprise record exists as its own file, and no disposition record was touched. - Given a run with four widening items of which one is admitted, one declined and one held, when the outstanding report runs, then it names the fourth item, which carries neither an admission nor a
declinedorhelddisposition, and no other. - Given
abcd adm-Norabcd srp-N, when it runs, then it reports the record and the records it joins to.
Prior Art
- itd-189 and its spec (the schemas), itd-180 (dispositions), adr-56 (absence as a class, ruled for the exclusion floor).
- The cold-reading rulings of 2026-08-28 in the decision log.
Open Questions
None beyond the flagged decision above.
Audit Notes
Fidelity review — receipt rcp-77c7c87559c2 (verifier intent-auditor claude-fable-5-1).
Provenance: intent-auditor@claude-fable-5-1 · rubric_hash sha256:effa65b3e9e88ff29433b443ec2be159522a8b0b71cf1434526514aa61edb13e · prompt_hash sha256:74f6cc68397cb66a0c07dd9ac2c494d47c595790bfdf769e0d66af279d595483 Input attestations: diff:internal/core/capture/{admit,surprise,reading,itemfate}.go, internal/core/lint/readingoutstanding.go, internal/core/record/record.go, commands/capture.md at 4001d807 (git ls-tree -r)@sha256:22d51985481877746861848e96f958139e71e639b95589d4c2f753fe44bcac92;
Acceptance rollup: MET 8 · MET_WITH_CONCERNS 0 · NOT_MET 0 · INCONCLUSIVE 0
Per-criterion verdicts:
- ac-1 — MET: Admit writes the accepted disposition through the shared writer and the admission record under one ledger lock, both naming the item and the run, and a second Admit refuses on the standing admission; TestAdmitWritesBothRecordsAndRefusesTwice passes at BASE evidence: internal/core/capture/admit.go:124 — "written, err := writeDispositionLocked(repoRoot, issuesRoot, head, DispositionRequest{" evidence: internal/core/capture/admit.go:114 — "if len(fate.Admissions) > 0 {" evidence: internal/core/capture/admit_test.go:82 — "func TestAdmitWritesBothRecordsAndRefusesTwice"
- ac-2 — MET: with exactly one standing disposition Admit reads it through requireStandingAcceptance and writes the admission alone, and the test asserts the disposition's bytes are untouched evidence: internal/core/capture/admit.go:131 — "case 1:" evidence: internal/core/capture/admit.go:187 — "func requireStandingAcceptance(issuesRoot, item, id, ground string)" evidence: internal/core/capture/admit_test.go:115 — "func TestAdmitWritesTheAdmissionAloneOverAStandingAcceptance"
- ac-3 — MET: requireCharacterised sits in writeDispositionLocked, the writer both Disposition and Admit route through, and the admission-alone branch calls it too; the refusal names the run and the comparative reading it waits for, and both TestDispositionRefusesBeforeTheComparativeRun and TestAdmitRefusesBeforeTheComparativeRun assert ErrNotCharacterised with nothing written evidence: internal/core/capture/reading.go:454 — "if err := requireCharacterised(repoRoot, head); err != nil {" evidence: internal/core/capture/reading.go:497 — "func requireCharacterised(repoRoot string, head itemHead) error {" evidence: internal/core/capture/admit.go:138 — "if err := requireCharacterised(repoRoot, head); err != nil {" evidence: internal/core/capture/reading_test.go:581 — "func TestDispositionRefusesBeforeTheComparativeRun" evidence: internal/core/capture/admit_test.go:180 — "func TestAdmitRefusesBeforeTheComparativeRun"
- ac-4 — MET: a standing disposition in any state but accepted refuses naming the disposition id and its state; TestAdmitRefusesAStandingNonAcceptance covers rejected, declined and held evidence: internal/core/capture/admit.go:198 — "if state := asString(fm["state"]); state != issueschema.DispositionAccepted {" evidence: internal/core/capture/admit_test.go:219 — "func TestAdmitRefusesAStandingNonAcceptance"
- ac-5 — MET: the ground is settled through requireFreeGrounds (redact, fold, grounds.ValidateText) before the ledger is touched, so a blank, whitespace or degenerate ground refuses with nothing written; TestAdmitRefusesADegenerateGround asserts the ledger digest is unchanged evidence: internal/core/capture/admit.go:76 — "ground, redacted, degraded, err := requireFreeGrounds(repoRoot, "admit", req.Grounds)" evidence: internal/core/capture/admit.go:292 — "if err := grounds.ValidateText(folded); err != nil {" evidence: internal/core/capture/admit_test.go:263 — "func TestAdmitRefusesADegenerateGround"
- ac-6 — MET: Surprise writes surprises/srp-N.md as its own file after resolving the occasion under the lock, and TestSurpriseIsItsOwnRecord asserts the dispositions tree digest is unchanged; the CLI test dispatches abcd srp-N to it evidence: internal/core/capture/surprise.go:99 — "path := filepath.Join(dir, id+".md")" evidence: internal/core/capture/surprise_test.go:38 — "func TestSurpriseIsItsOwnRecord" evidence: internal/surface/cli/capture_admit_test.go:113 — "func TestCaptureSurpriseRequiresAnOccasion"
- ac-7 — MET: ReadReadingOutstanding renders one WideningRun per run with the admitted/declined/held counts and the outstanding list; TestWideningRunSummaryNamesTheOutstandingItem builds exactly the four-item run of the criterion and asserts the fourth item alone is named, and the capture board renders the count evidence: internal/core/lint/readingoutstanding.go:140 — "type WideningRun struct {" evidence: internal/core/lint/reading_outstanding_test.go:1097 — "func TestWideningRunSummaryNamesTheOutstandingItem" evidence: internal/surface/cli/capture_admit_test.go:106 — "1 proposal(s): 1 admitted, 0 declined, 0 held, 0 outstanding"
- ac-8 — MET: the record dispatcher's IDRe admits adm and srp and routes them to describeAdmission (run, proposal, proposal_path, standing disposition) and describeSurprise (occasioned_by, occasion_path); TestDescribeAdmission and TestDescribeSurprise assert the joins and the CLI test dispatches a minted srp-N
evidence: internal/core/record/record.go:36 — "var IDRe = regexp.MustCompile(
^(iss|itd|spc|adr|adm|srp|rfm)-[0-9]+$)" evidence: internal/core/record/record.go:113 — "case "adm":" evidence: internal/core/record/record_test.go:786 — "func TestDescribeAdmission" evidence: internal/core/record/record_test.go:818 — "func TestDescribeSurprise" evidence: internal/surface/cli/capture_admit_test.go:142 — "// Andabcd srp-Ndispatches to it."
Gap audit:
- honoured:
- admission is one act with two records under the ledger lock, and where accepted stands the admission is written alone on the standing ground evidence: internal/core/capture/admit.go:94 — "err = withLedgerLock(repoRoot, issuesRoot, func() error {" evidence: internal/core/capture/admit_test.go:342 — "func TestAdmissionAndDispositionCarryOneGround"
- the ordering gate lives in the shared writer, so neither capture disposition nor the scribe's ingest lands an acceptance before characterisation evidence: internal/core/capture/reading_test.go:677 — "func TestDispositionAndAdmitShareOneWritePath" evidence: internal/core/scribe/ingest_test.go:385 — "if !errors.Is(err, capture.ErrNotCharacterised)"
- a comparative run committed with an empty item set (not exercised) satisfies the gate evidence: internal/core/capture/admit_test.go:208 — "func TestAdmitProceedsOnAnEmptyComparativeRun"
- both-or-neither: a failed admission write removes the disposition the act wrote evidence: internal/core/capture/admit.go:157 — "if rmErr := removeContained(ledgerBase(repoRoot, issuesRoot), dispPath); rmErr != nil {" evidence: internal/core/capture/admit_test.go:300 — "func TestAdmitRemovesTheDispositionWhenTheAdmissionWriteFails"
- the plugin surface page documents both verbs and the ordering evidence: commands/capture.md:435 — "At the widening position, characterise first and admit second." evidence: commands/capture.md:468 — "## Record a surprise"
- surprise refuses an occasion outside rdi/adm/dsp or one that does not resolve, before anything is minted evidence: internal/core/capture/surprise.go:61 — "if !issueschema.ValidSurpriseOccasion(occasion) {" evidence: internal/core/capture/surprise_test.go:78 — "func TestSurpriseRefusesAnUnresolvedOccasion"
- diverged: (none)
- missing: (none)
Scope-condition dispositions:
- cond-2609020626047113 — survived: the gate probes ComparativeRunFor over the committed run records the comparative channel writes, an empty item set counts as not exercised, and the channel intent itd-2609020625407419 is in shipped/ evidence: internal/core/capture/itemfate.go:145 — "func ComparativeRunFor(repoRoot, run string) (string, error) {" evidence: internal/core/capture/reading.go:501 — "comp, err := ComparativeRunFor(repoRoot, head.run)"
- cond-2609020626042968 — survived: admission grounds pass through grounds.ValidateText, the same floor every grounds primitive applies; no admission-specific floor exists evidence: internal/core/capture/admit.go:289 — "func requireFreeGrounds(repoRoot, verb, raw string)" evidence: internal/core/capture/admit.go:292 — "if err := grounds.ValidateText(folded); err != nil {"
- cond-2609020626040151 — survived: requireWidening refuses every other position by name and the ordering gate is keyed on the widening position alone; TestAdmitRefusesANonWideningItem covers it evidence: internal/core/capture/admit.go:174 — "func requireWidening(head itemHead) error {" evidence: internal/core/capture/admit_test.go:247 — "func TestAdmitRefusesANonWideningItem"
Grounds
- pursued: we expect a verb that refuses a blank ground and refuses to admit before the comparative outcome exists to make the admitted-against-declined count a query and the ruled ordering a fact rather than a protocol; a hand-written admission the gate accepts with no ground, or an admission recorded before characterisation with every gate green, would show it wrong
Frontmatter
| id | itd-2609020625400194 |
|---|---|
| type | intent |
| lifecycle | shipped |
| kind | standalone |
| severity | minor |
.abcd/development/intents/shipped/itd-2609020625400194-an-admission-and-a-surprise-are-written.md
open on GitHub ↗ · commit history ↗
References3
- itd-180A cold reading's findings land as reading records, and the researcher's response is a separate disposition record — two acts, two writes, never collapsedbuilds on
- itd-185One ingest verb validates every cold-reading output — including what the reading was licensed to produce, not only what it sawbuilds on
- itd-189What the widening reading proposes is admitted or declined on the record — grounds on admission, dispositions on declines, and surprises as their own entriesbuilds on
Referenced by2
- iss-2610262045235833itd-46 says sub-verbs act on existing records and quoted text creates; itd-2609020625400194 adds a capture sub-verb that creates a new record from quoted textrelated
- spc-2609020626040342The admission and surprise verbs: one act, two records, and the ruled order held as a refusalimplemented by
mentions8
- adr-56An exclusion control asserts only what it can prove
- dcn-26090200000000202026-09-02 — The entailment reading is handed the OBJECT SET's drafts and planned intents, and none by default (maintainer, at the Phase A review). The framework's section 13 fixes the object set as "Iteration 1's shipped state and claim record" — the fifteen workstream intents, which the record extends by the ten Iteration 2 intents — and the readings companion's section 6.2 makes drafts and planned intents ADMISSIBLE at that position: admissible is a permission, the object set is the scope, and the assembly was handing every draft and planned intent in the repository (147 projected intents on the Phase A tree) because a record row is admitted whole when the object set names none of its records. The drafts and planned rows therefore narrow by the entry's record list exactly as the shipped row does, so a draft or planned intent travels only when the committed entry names it; the companion's admissibility becomes a switch on the entailment entry — `admit_drafts_and_planned`, yes or no for drafts and planned intents beyond the object set, default no, refused at load on any other position because those two rows are admitted at entailment alone. The committed entailment entry names the ten Iteration 2 intents (itd-194, itd-2609021003095168, itd-2609020625400169, itd-2609020625400194, itd-2609020625400445, itd-2609020625402518, itd-2609020625402599, itd-2609020625405170, itd-2609020625405251, itd-2609020625407419) beside the fifteen, and declares no switch; several of the ten are shipped by the time Phase A completes and travel through the shipped row, which is the same object set either way. Issues, ADRs and every other warm family stay excluded by construction and gain no switch. Divergence register entry 1 is corrected accordingly: it recorded the ten as reaching the position through the companion's admission, which is the reading this ruling replaces.
- dcn-26092500000000292026-09-25 — itd-2609020625400194 (admission and surprise verbs) is delivered on main by autonomous run A's lane, built against the current main, and not by the parked `phase-9/admit` branch that delivered the same spec on 2026-09-04. Phase 9 stays parked on the product thinker's word of 2026-09-22 ("leave both parked workstreams"). Its build branch sits 213 commits behind main and ships six other intents that exist nowhere else, so the run neither merges nor edits it. The overlap is this one intent: when Phase 9 is unparked, its admission commits (the spec close in 30f42daa, with b0334b03, 5ca30f92 and 074dea98) are dropped or reconciled against this delivery. That reconciliation is owed to the product thinker and listed in the run's rulings-owed list. The ruling is reversible: nothing on the parked branches is touched (orchestrator abcd-39, autonomous run A).
- iss-2608301744268001a trailing comment on a frontmatter key defeats every blank spelling the record_schema gate refuses because the shared same-line scanner strips no comments
- iss-2608301808198621isAbsentValue decides on literal strings rather than the yaml null and empty class so chasing spellings cannot close it
- 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-2609020625407419A comparative reading receives the widening run's items as its candidate set, and characterises them before anyone admits one
- spc-67Step-2 admission records: schemas now, command enforcement next cycle