Development record
Machine assistance in maintaining the ledger, without any context that holds both ledger content and a reading
Press Release
The scribe sees the ledger and nothing else. Its access rule is the assembler's inverse: it reads ledger content, transcribes reading outputs and researcher dispositions, and authors nothing — and it never receives the shipped repository as an object of judgement. No session holds both a reading and the ledger; each is a distinct retained session, and session retention can show it.
What's In Scope
- The scribe definition with the inverse access rule, and (when the verb lands) its ingest path.
- The fidelity-flag permission: the scribe may flag an internal inconsistency in what it is transcribing ("this disposition contradicts the ruling recorded earlier in the session") — that is transcription fidelity, not judgement, and it does not breach authors-nothing. What it may never do is propose a resolution.
- The contribution stamp: anything the scribe is explicitly asked to
produce beyond formatting opens with a stamped attribution that travels
with the material if adopted — the hand-run precursor of the
origin/scribe-transcribedkeys, in force until those keys ship. An unstamped contribution is never delivered. - The protocol until then, documented and followed: entries are transcribed when the reading returns, not later — a protocol invented under time pressure is a protocol that gets skipped.
Acceptance Criteria
- Given a scribe invocation, when its context is assembled, then it contains ledger content and no shipped-tree material.
- Given a reading run and a scribe run, when session retention is inspected, then each is a distinct retained session and no session holds both.
Audit Notes
Fidelity review — receipt rcp-71f5a9b044cb (verifier intent-auditor claude-fable-5).
Provenance: intent-auditor@claude-fable-5 · rubric_hash sha256:f3bba86a84b329fcbfbd3df64ec5d77d382dda9b4b1a61baf887e316bc41f38e · prompt_hash sha256:c07526fb6e333e1e2944acc40cd7f4272cab0c2b73e2352e27c956063e9a590f Input attestations: diff:543aaf19...a1d3ba9a@sha256:52899f2afe5d9898d1472ed0a58814405373369784717f27086e6ea38f95d232;
Acceptance rollup: MET 0 · MET_WITH_CONCERNS 2 · NOT_MET 0 · INCONCLUSIVE 0
Per-criterion verdicts:
- ac-1 — MET_WITH_CONCERNS: The definition's inputs block is a positive allow list confined to .abcd/work/issues/ plus supplied text, its exclusions name the shipped tree and the transcript store, and TestScribeInputsAreLedgerOnly / TestScribeDeclaresNoTranscriptStoreAccess / TestScribePromptSatisfiesTheContract pass over the real file (go test, 6 cases PASS). Concern: no assembler runs for the scribe this cycle, so what is proved is that the DECLARATION names no shipped-tree path, not that any host-assembled context contained only ledger content; the criterion's 'when its context is assembled' is realised at declaration level only, which the spec states.
evidence: agents/scribe.md:40 — "## Inputs (the allow list — anything not named here is excluded)"
evidence: agents/scribe.md:46 — "
.abcd/work/issues/readings/" evidence: agents/scribe.md:59 — "The shipped repository as an object of judgement" evidence: agents/scribe.md:68 — "The session-transcript store. You are not one of its enumerated consumers" evidence: internal/core/lint/scribecontract_test.go:42 — "const scribeLedgerRoot = ".abcd/work/issues/"" evidence: internal/core/lint/scribecontract_test.go:240 — "if !strings.HasPrefix(path.Clean(tok)+"/", scribeLedgerRoot)" evidence: internal/core/lint/scribecontract_test.go:350 — "func TestScribeInputsAreLedgerOnly(t *testing.T)" evidence: internal/core/lint/scribecontract_test.go:375 — "func TestScribeDeclaresNoTranscriptStoreAccess(t *testing.T)" evidence: internal/core/lint/scribecontract_test.go:516 — "func TestScribePromptSatisfiesTheContract(t *testing.T)" evidence: .abcd/development/specs/closed/spc-66-machine-assistance-in-maintaining-the.md:150 — "No assembler runs for the scribe this cycle, so what is pinned is the declaration" - ac-2 — MET_WITH_CONCERNS: The protocol in the brief's agents chapter requires the reading run and the scribe run to be separate host sessions each retained under its own session id; the store retains per-session records (history.Record.SessionID, Capture(session_id), List) and TestCaptureIdenticalSourceDistinctSessionsWritesBoth pins that distinct sessions yield distinct records. Concern (the spec's own declaration, judged sound): the criterion is met procedurally, not mechanically — the delivered range contains no reading run and no scribe run whose retention could be inspected (the ledger at a1d3ba9a has no readings/ or dispositions/ entries and the store holds no scribe session), and the 'no session holds both' half is not observable from the store because the host assembles context before anything is retained. Mechanical enforcement is deferred to the ingest verb.
evidence: .abcd/development/brief/05-internals/01-agents.md:90 — "The reading run and the scribe run are separate host sessions, always. Each is retained under its own session id"
evidence: agents/scribe.md:37 — "No session holds both — the reading session and this one are separate sessions, always."
evidence: internal/core/history/history.go:50 — "SessionID string
json:\"session_id\"" evidence: internal/core/history/history.go:97 — "func Capture(repoRoot, rootSHA, sessionID string, raw []byte, kind string)" evidence: internal/core/history/history.go:223 — "func List(rootSHA string) ([]Record, error)" evidence: internal/core/history/history_test.go:341 — "func TestCaptureIdenticalSourceDistinctSessionsWritesBoth(t *testing.T)" evidence: .abcd/development/specs/closed/spc-66-machine-assistance-in-maintaining-the.md:148 — "None — procedural (below)" evidence: .abcd/development/specs/closed/spc-66-machine-assistance-in-maintaining-the.md:155 — "The second criterion carries no mechanical test"
Gap audit:
- honoured:
- The scribe definition with the inverse access rule: ledger content only, never the shipped repository as an object of judgement, not a transcript consumer evidence: agents/scribe.md:35 — "The access rule is the inverse of the assembler's." evidence: agents/scribe.md:57 — "## Never in context" evidence: internal/core/lint/scribecontract_test.go:277 — "func TestScribeAccessCheckRefusesEveryBypass(t *testing.T)"
- The fidelity-flag permission: may flag an internal inconsistency as a named field, never proposes a resolution
evidence: agents/scribe.md:121 — "Emit each one as an entry in a named
fidelity_flagslist beside the transcribed material" evidence: agents/scribe.md:125 — "A flag is carried to the researcher unresolved. You never propose a resolution" evidence: agents/scribe/fixtures/injection-canary.json:94 — ""fidelity_flags": [" - The contribution stamp: anything beyond formatting opens with a stamped attribution; an unstamped contribution is never delivered evidence: agents/scribe.md:152 — "> SCRIBE CONTRIBUTION — composed by the scribe, not by the researcher." evidence: agents/scribe.md:156 — "An unstamped contribution is never delivered. This is a refusal, not a preference"
- The protocol documented: entries transcribed when the reading returns, two host sessions, ordinary record path, flags carried unresolved evidence: .abcd/development/brief/05-internals/01-agents.md:81 — "## The scribe protocol" evidence: .abcd/development/brief/05-internals/01-agents.md:89 — "Entries are transcribed when the reading returns, not later." evidence: .abcd/development/brief/05-internals/01-agents.md:92 — "A fidelity flag is carried to the researcher unresolved."
- The definition satisfies the agent_contract trust shape: prompt_version, reads_untrusted_input, capability_scope, canary fixture, changelog entry evidence: agents/scribe.md:9 — "prompt_version: 0.1.0" evidence: agents/scribe.md:10 — "reads_untrusted_input: true" evidence: agents/scribe/fixtures/injection-canary.json:2 — ""fixture": "injection-canary"" evidence: agents/CHANGELOG.md:17 — "### scribe 0.1.0" evidence: internal/core/lint/scribecontract_test.go:393 — "func TestScribeCanaryAssertsTheRefusals(t *testing.T)"
- diverged:
- "session retention can show it" (press release) — retention shows two distinct sessions exist; it cannot show that no session holds both, and no reading/scribe session pair exists in the delivered range to inspect evidence: .abcd/development/brief/05-internals/01-agents.md:90 — "it cannot enforce that the practice held, because the separation happens in the host before anything is retained" evidence: .abcd/development/specs/closed/spc-66-machine-assistance-in-maintaining-the.md:155 — "The second criterion carries no mechanical test"
- "when its context is assembled" — no assembly executes; the guard proves the definition names no shipped-tree directory or nested file, and a separator-free shipped filename is outside its reach evidence: internal/core/lint/scribecontract_test.go:10 — "they prove the prompt names the right paths, not that a host assembled the right context" evidence: .abcd/development/specs/closed/spc-66-machine-assistance-in-maintaining-the.md:150 — "No assembler runs for the scribe this cycle"
- missing:
- The scribe's ingest path ("when the verb lands") — scoped out by the intent itself; the emitted shapes have no schema until spc-58's stores land, so the record gate refuses their directory as an undeclared bucket rather than judging a record evidence: agents/scribe.md:162 — "There is no ingest verb, so what you emit is committed through the ordinary record path" evidence: .abcd/development/brief/05-internals/01-agents.md:87 — "There is no ingest verb."
Grounds
- pursued: Pursued now because the ledger has to be maintained during this cycle and the obvious way to get help with it is the one thing the design cannot allow: a context holding both a reading and the ledger. Defining the scribe's inverse access rule before the first run is what keeps machine assistance from becoming the channel by which reading and ledger meet, and session retention is what lets that claim be checked rather than asserted.
Frontmatter
| id | itd-188 |
|---|---|
| type | intent |
| lifecycle | shipped |
| kind | standalone |
| severity | minor |
.abcd/development/intents/shipped/itd-188-machine-assistance-in-maintaining-the.md
open on GitHub ↗ · commit history ↗
Referenced by3
- adr-2609021016275803No session holds both a reading and the ledger, and a per-run context stamp is how the record shows itrelated
- itd-2609020625402599The scribe's context is assembled and its output is ingested by a verb, and the record can show that no session held both a reading and the ledgerbuilt on by
- spc-66The scribe: ledger-only context, authors nothingimplemented by
mentions11
- dcn-26083000000000172026-08-30 — itd-179 round-5: a RELOCATION is not a BACKFILL, and the forward-only rule forbids only the second. Moving a pre-tooling `## Grounds (pursued)` section from a spec onto its intent (commit 09f7d91a, thirteen specs) put text authored at the moment of pursuit where it belongs; nothing was reconstructed, which is the whole of what "never backfilled" refuses. Three shipped intents therefore carry a `## Grounds` section — itd-177, itd-182, itd-188 — and the surface claim now says so instead of asserting the corpus carries none (iss-2608301657357989). The enforcement is unchanged and stays maximally strict: `RecordGrounds` refuses a shipped or superseded record whatever the provenance of the text, because nothing in it can tell relocated text from invented text, so the relocated state is deliberately not reachable through `abcd intent ready --grounds`. Rejected: weakening the refusal to admit a `--relocate` escape, which would make the distinction a caller's assertion rather than a reviewable fact about a commit.
- iss-2608300143315694itd-188 review consistency findings: spc-66 maps acceptance criterion 2 to TestReadingAndScribeSessionsAreDistinctRecords in internal/core/history, which the build neither adds nor declares dropped (deliver it or amend the mapping to say the criterion is procedural); 05-prompt-quality.md still counts ten prompts and six outside the roster after the eleventh landed; the guard test duplicates indexTokenRe and a readRepoFile helper, carries a control that compares a literal to itself, and repeats the canary presence checks the contract rule already runs; the canary's manifest path does not match spc-58's manifest home.
- iss-2608300205343890itd-188 second-round review residue: spc-66 still asserts the record_schema validation path retracted elsewhere and names the guard root as .abcd/work/ while its amended table says .abcd/work/issues/; the guard's prose exemption (fewer than two separators and no dot) admits a bare shipped-tree directory such as internal/core or a spaced-separator path; the canary's must_not_contain token is one the verbatim-transcription rule requires the output to carry, so no faithful run can satisfy it; the extractor does not fold U+2571, U+29F8, U+FF3C, HTML-entity or percent-encoded separators, does not refuse format (Cf) code points, and its comment overclaims every spelling; legitimate prose such as version pairs and URLs is flagged as outside paths without a comment saying so; the canary's input items carry no identifier while the expected output refers to item-1 and item-2.
- iss-2608300217463580itd-188 third-round residue, all in the guard's fold step and the canary exemplar: a single non-hex percent sign anywhere in the definition makes url.PathUnescape fail and the whole percent-decoding step is skipped for the file, contrary to its comment; decoding runs once, so double-encoded separators survive; the separator replacer enumerates forward solidus lookalikes but not their reverse twins (U+2572, U+29F9, U+2216, U+29F5) nor eleven further lookalikes, while its comment claims exhaustiveness; a separator-free shipped-tree filename is outside the guard's reach while spc-66 says any repository path is refused; the canary exemplar emits a reading record for item-1 only against its own one-record-per-item behaviour; the definition's Delivery line 'and nothing else' contradicts the reported outstanding state and the canary's refused entry; two British spellings sit in code-side comments. Remedy is class-closing: refuse every non-ASCII code point outside a small typographic allow-list, decode tolerant and to a fixpoint, refuse residual encoded shapes.
- iss-2608300232312077itd-188 fourth-round residue: spc-66's Tests section still says the guard folds every separator spelling to a slash, while the guard now folds only the ASCII reverse solidus and spaced separators and refuses every other non-ASCII spelling — a maintainer trusting the spec could allow a lookalike in prose believing it still folds; the definition's untrusted-input banner says an embedded instruction is a thing a fidelity flag reports while the flag section requires two disagreeing pieces of material, and the canary's behaviour text names a different candidate flag than its exemplar emits; the residual-entity regex refuses any ampersand followed by a letter (Q&A) without the comment saying so; the bypass table asserts only that some finding exists, so the Cf branch's message is pinned by one case.
- iss-2608301657357989the plugin surface claims the grounds verb refuses a shipped record so no terminal bucket carries grounds while three shipped intents do
- iss-2608301856299268a size classification for specs and tasks is parked as a note and owes a design and filing decision in a future session
- iss-2609012259581057The cold-reading workstream's intents carry no mechanism claim and twelve of fourteen declare no scope condition, so the record was populated by demonstration rather than use
- iss-2609020626114155ADR and brief invariant owed: no session holds both a reading and the ledger, and the session-kind stamp changes the reading bundle's shape
- spc-58Reading records and disposition records: two acts, two writes
- spc-2609020626045177The scribe verb: an allow-list assembler, an authoring-refusing ingest, and a per-run context stamp the transcript store can check