Agent eligibility check · The decision corpus

Make the record conventions followable and enforce the actor rule

docs/records/2026-09-19-process-record-conventions.md · ae-2026-09-19-process-record-conventions · revision 2 · open / submitted

This is the development record, published as it was written. It is amended by revision, including where the work went wrong. Nothing here has been rewritten for the web.

Record header

created_at: 2026-09-19T19:15:07-06:00
format: perspicuity-work/1
id: ae-2026-09-19-process-record-conventions
record_status: open
revision: 2
skill_version: 0.4.0
updated: 2026-09-19
updated_at: 2026-09-19T19:27:31-06:00
work_status: submitted

Make the record conventions followable and enforce the actor rule

Current position

Parent: RECORD.md, revision 6.

Principal: David. Decider: David for the convention; Rook for the reversible wording and mechanics inside it, under the delegated authority in RECORD.md and David's instruction to Rook of 2026-09-19. Work owner: Rook. Decision: inherited, and selected in part — the convention itself is David's instruction: the actor-naming rule, the checkability requirement and the "no context needed" bar are givens, not proposals. What Rook selected inside that grant is the name, the enforcement mechanism and the wording of the revised documents. Basis: RECORD.md revision 5, which inherits the parent selection at next-project-choice revision 2, a sibling project's record; amended at this revision 2 after the independent check below. Work scope: the three process documents named in the instruction — AGENTS.md, CONTEXT.md, docs/RECORDS.md — plus the actor-naming retrofit, the check that enforces it, and this record. No product code, no rubric, no site, no deployment. Work: AGENTS.md, CONTEXT.md and docs/RECORDS.md are revised; docs/ARCHITECTURE.md and RECORD.md carry the normalised actor label; scripts/check_actors.py and its 23 test cases are added and run by make records; Rook is named in docs/ACTORS.md with the candidates not chosen and the retired label's history. Landed at 2cf38fc and 5ff06c8 (revision 1) and 58ced5c (this revision), after make ci and make records passed at each. Outcome: unknown, and nothing about it is claimed. No worker who lacks context has yet tried to follow these documents, so the bar the instruction sets — followable without asking a question — is unobserved. What is observed: a planted violation of each kind the check claims to catch fails the build, and the shipped tree passes; and the independent check found a real hole in the first version of the check, which is now closed and covered by a test. Next: David — accept, revise or reject this record, the revised documents and the answers to the check below; feature work waits on that acceptance. Verity — nothing further; the return is assessed here and any disagreement belongs in a further revision of this record. Dependency: David's acceptance. Nothing in the increment is blocked meanwhile, and no later work depends on this record's state.

Stagebegan_atregistered_at / exact basis revisionfinished_at
Frame and Decide2026-09-19T19:06:00-06:002026-09-19T19:15:07-06:00 / revision 12026-09-19T19:15:07-06:00
Act2026-09-19T19:15:07-06:002026-09-19T19:15:07-06:00 / revision 12026-09-19T19:57:00-06:00
Review2026-09-19T19:15:07-06:002026-09-19T19:15:07-06:00 / revision 1, criteria in Independent check2026-09-19T19:33:00-06:00
Act, second pass2026-09-19T19:33:00-06:002026-09-19T19:33:00-06:00 / this revision, answering the check2026-09-19T19:33:00-06:00

Registration lag, stated rather than glossed. The frame and the alternatives were saved before the documents were final, but the plan was written with the evidence rather than before it — the script and the wording were already being written when revision 1 was committed. The Review row above is the correction: its criteria were registered in writing at 19:15:07, in the Independent check section commissioned then, and that registration is what the first pass was assessed against. The Act plan still was not registered ahead of its work. That is the failure the revised docs/RECORDS.md names, and this record is the honest example of it rather than a tidy one. The first pass's remaining defect — revision 1 claimed an unobserved number, corrected under Material failures — is the second reason the procedure exists.

Frame and Decide

David's instruction is the frame: name yourself, own the process documents, and file the first record, so that a worker arriving with no context could follow this project's process without asking a question. The product's claim boundary cuts the same way — a report about someone else's legibility is only credible if this project's own outputs are legible — but the immediate question is narrower:

Which conventions does this repository need written down, and which of them can be enforced by the build rather than requested in prose?

The inherited materials are context, not invention. What was missing is what a first reader would have had to guess: when a record is written relative to the work, what a check actually reads, who assesses a returned record, and what happens to a record after it is filed.

#Fundamental objectiveSourceMeasure, direction and horizon
O1A worker with no context can follow the processDavid's instruction: "good enough that a worker arriving with no context could follow them without asking a question"Questions the worker has to ask before filing a correct record; down; the next worker's first session
O2The actor naming rule holds without reviewDavid's instruction: "if you can make the naming rule checkable, that is worth more than a paragraph asking nicely"Violations that reach a commit; down; continuous, from this increment
O3The published corpus reads correctly to a strangerInherited from the two required outcomes in CONTEXT.mdA reader can attribute every choice to a named actor and reconstruct its reason; the publication review
O4The method is not inflated by the process workInherited: "a record that restates its parent is noise"Records filed per consequential choice; the conventions live in one document, not spread across records
Material conditionTypeBasisAffects
The runtime is standard library onlyGivenAGENTS.md standing constraints; scripts/check_stdlib_only.py parses scripts/ tooThe new check cannot use PyYAML, so it reads prose directly rather than front matter
The Perspicuity checker is shipped with the skill, not the repositoryGivenscripts/check_records.sh; absent on another machine, where it skips loudlyThe naming check must be ours and must run whether or not the skill is present
Revisions 1–3 of RECORD.md and all of ARCHITECTURE.md use the retired labelGivengrep over the working tree at e3e54feThe retrofit, and the naming check's first real test
The check must not fail on legitimate proseUncertainty, resolved in partdocs/RUBRIC.md and README.md use "an agent" 26 times as product vocabulary (25 and 1, case-sensitive, measured at this revision)Five listed role words are banned; "agent" and "AI" are never banned, and the product vocabulary is untouched
Whether a real first-time worker finds these documents sufficientUncertainty, unresolvedNo such worker has read themO1 stays a partly-met finding, not a met one
David accepts the name and the mechanismAssumptionHe delegated naming to the coordinator and required it to be checkableThe name and the check are provisional until he accepts

Alternatives and consequences

The four consequential choices in this increment. Each is reversible, which is why they are component choices inside one record rather than four records.

#QuestionAlternativesDecisive tradeoffChosen
C1How is the naming rule enforced?(a) prose only, reviewed by eye; (b) a project script that fails make records on known-bad words, with a marked exception block; (c) a strict allowlist requiring every capitalised name to appear in the roster(a) is free and fails silently; (c) is stronger and would fail on ordinary English prose that happens to use a banned word; (b) catches the defect class that actually occurred here — 38 occurrences of the five listed words at e3e54fe — and is cheap to widen(b), with the block-marker guards below
C2How is a page allowed to discuss the words it bans?(a) ban everywhere, including the page that states the rule; (b) a per-file allowlist of marked blocks; (c) an inline per-occurrence marker(a) makes the rule unwritable, so the docs would have to describe it without naming it, which is how a rule becomes vague; (c) adds a marker to every line and hides which pages are exceptional(b) — markers recognised only in the pages whose subject is the rule, and a block that quotes nothing is an error
C3How much prose may the check read?(a) the corpus only — RECORD.md and docs/records/; (b) the corpus plus the process documents; (c) the corpus plus every markdown file in the repository(a) is smallest and leaves the documents that teach the rule free to break it; (c) would flag "an agent" in the generated rubric and the product vocabulary(b) — the six files listed in docs/RECORDS.md, with the exclusions written down
C4Where do the new rules live?(a) one new sub-record per rule; (b) one record for the increment, with the rules in the documents they govern; (c) a standing process manual(a) manufactures records for choices that share one review and one reversibility condition — the noise the corpus rule warns about; (c) invents a parallel hierarchy beside RECORDS.md(b), which is also the shape O4 asks for

The name. Three candidates were considered before anything was written into a record. Wren was rejected because the convention documents were already using it as a placeholder for the coordinator, and adopting it would leave every earlier example ambiguous between the actor and the illustration. Pip was rejected because it reads as a package manager to this audience, and Ash because it is a common noun as well as a given name. **Rook** was chosen: short, one syllable, a persona rather than a job, no collision with the working tree, and not a living person's name. Recorded with the same reasoning in docs/ACTORS.md.

The decisive preference. O2 says a rule that nothing checks is a preference, and the instruction asks for enforcement over persuasion. That preference is what makes C1(b) and C3(b) the choices rather than the tidier-sounding alternatives: the check is willing to read prose it does not fully understand, in exchange for catching the defect class that actually occurred here — fifteen occurrences of a role word in the project record.

What would warrant reconsideration. The marker mechanism is the weak point. If a future page hides a real violation inside a marked block, or if the marker count grows past the four places it is allowed today, the exception has stopped being an exception and the check should move to C1(c)'s allowlist. The trigger is a violation that the check passes because it sits in a marked block.

Selection

selected_at 2026-09-19T19:15:07-06:00, by Rook, against this revision. C1(b), C2(b), C3(b), C4(b), and the name Rook. The authority is the delegated scope in RECORD.md — everything inside the project record except spending, outbound messages, external agreements and publication — and David's instruction, which required a naming rule and asked for it to be checkable without prescribing the mechanism.

David has not seen any of it. The name, the mechanism and every wording change are submitted to him for acceptance, and a rejection is a revision of this record rather than a new one.

Act

#ResultInputs / dependenciesOwner / timingDone whenActual evidence
U1The coordinator is named and the retrofit madedocs/ACTORS.md, RECORD.md, docs/ARCHITECTURE.mdRook, 2026-09-19Rook is in the roster, the retired label is normalised, and the normalisation is a change entryMet: roster and name history in docs/ACTORS.md; normalised at RECORD.md revision 5 and docs/ARCHITECTURE.md
U2The naming rule is checkableStandard library only; no dependencyRook, 2026-09-19A planted violation fails the build; the shipped tree passesMet: scripts/check_actors.py, 23 cases in tests/test_actor_check.py, run by make records. The first pass shipped 17 cases and a hole the independent check found; see Material failures
U3The three process documents are followableThe instruction's list of known gapsRook, 2026-09-19Each change has a stated reason and a reader can find the rule it statesMet as delivered; O1 itself is unobserved
U4The corpus's first sub-record exists and passes the checksdocs/RECORDS.mdRook, 2026-09-19make records is clean with this file presentMet: see Review

Registration order, again

The plan above was written with the evidence, not before it. There is no way to repair that after the fact, so it is recorded as the increment's one material process failure rather than presented as a clean run. It also produced the most useful finding of the increment: the old documents did not say *how* to register before the work, and a rule with no procedure is one that gets skipped under time pressure — including by the person writing it.

Material failures found and corrected

  1. The check could not see the marker it documented. docs/RECORDS.md and docs/ACTORS.md have to *name* the marker to explain it, and the first pattern matched any occurrence of the marker text, so the explanation was read as a marker and swallowed the rest of the file. Corrected by anchoring both markers to the start of a line, and pinned by test_prose_that_names_the_marker_is_not_a_marker.
  2. A nested-block error was reported at the wrong line. The unclosed-block message computed a line number from a character offset and printed line 272 for what was line 11. Corrected to track the opening line directly.
  3. The exception was reachable from any file. The first draft recognised a marked block anywhere, which made it a general escape hatch. Narrowed to the four places whose subject is the rule or its history. An intermediate version also confined RECORD.md's marker to its ## Changes section; that rule was dropped at this revision because the check's own accurate sentence about what it catches sits in ## Current position, and the actor-credit guard below protects the thing the section rule was reaching for.
  4. A documented rule would have failed the new check. docs/RECORDS.md's naming example coordinator-policy-stance is safe, but the retrofit text quoting the retired label was not, and neither was the read-order sentence in AGENTS.md. Each was rewritten to make the rule's subject the *history* of the label rather than a live actor reference — a small illustration of why enforcement finds wording problems that review does not.
  5. A live marked block licensed a stale one beside it. The staleness guard searched the concatenation of every block in a file, so appending a second, empty block to a page that already had a legitimate one passed. Found by the independent check, not by the author's tests. Corrected to test each block on its own, with test_one_good_block_does_not_license_a_stale_one.
  6. A marked block could cover an actor credit. The block in docs/ACTORS.md ran from the rule text through the roster, so an actor could be credited to a role word inside it — demonstrated by planting one in the roster and watching the check pass. Corrected by forbidding a block to cover a Work owner:-style field or a roster row, and by restructuring that page so the roster sits outside the marked text. Found by the independent check.
  7. The record claimed an unobserved figure. Revision 1 said the check's first run found 36 violations, all of them the retrofit. That run was never committed, and the only measurable baseline, e3e54fe, gives 38 findings across six files, of which 31 are the retrofit's label. Corrected in the Review table above, and left visible rather than quietly replaced: it is the same failure — a number written from memory — that revision 1's own registration-lag note is about.

Review

The criteria in the first six rows were registered at 19:15:07, in the commission below, before the check's return. The remaining rows were added at this revision; each is marked as such rather than backdated.

CriterionEvidence sourceOwner, window or triggerFindingResponse
None of the five listed words reaches a commit, except where a page is stating the rulescripts/check_actors.py, run by make recordsRook, continuousMet on the shipped tree. Measured at the pre-increment revision e3e54fe, with the current check: 38 findings across six files — 31 the retired label, 3 <!-- actor-naming: discusses-rule -->Coordinator<!-- actor-naming: end -->, 2 <!-- actor-naming: discusses-rule -->Assistant<!-- actor-naming: end -->, 1 <!-- actor-naming: discusses-rule -->Manager<!-- actor-naming: end -->, 1 <!-- actor-naming: discusses-rule -->Admin<!-- actor-naming: end -->. Revision 1 of this record said 36 and attributed all of them to the retrofit; neither was right, and it is corrected here rather than quietly droppedThe check is the mechanism. Its file list and its five-word list are documented limits, not silent ones. The label count and the other seven are distinct findings: the retrofit explains 31 of the 38, and the rest were the rule pages describing the words they ban
The check fails on a violation rather than passing quietlytests/test_actor_check.py, one case per failure mode; planted violations in a temporary copyRook, 2026-09-19Met after correction: 23 cases. The first pass's 17 did not cover a stale block *beside* a live one, nor a block covering an actor credit — the two exploits the independent check demonstrated. Both are now caught, and the reproductions are re-run under ReviewThe independent check was worth its cost for exactly this: it found a hole the author's own tests could not
The exception cannot become the ruleThe marker guards, and the two exploits re-run against the corrected check in a temporary copyRook, on each new page that wants oneMet after correction; not guaranteed by construction. Revision 1 marked this "met by construction" and the independent check falsified that in two ways — a stale block beside a live one, and a role word planted in the roster inside a marked block. Both now fail, with the reproduction commands recorded in the check's returnThe reversal condition stands: if a violation arrives hidden in a marked block, move to the allowlist in C1(c)
Every consequential choice in this increment is reviewableThis recordDavid, on acceptanceSubmitted. The frame, four alternatives with their decisive tradeoffs, the rejected names and the reversal condition are aboveDavid's acceptance, revision or rejection
The three process documents can be followed with no contextThe documents; a first-time workerRook, 2026-09-19; unresolved thereafterPartly met. The named gaps are closed; that a stranger can follow them is not established, because no stranger has read themCarry to the next worker: their first question is the test
The retired label survives only as historygrep over the working tree; the marked-block count; the check's own outputRook, 2026-09-19Met: five marked regions, all inside the pages that state the rule or record the change, and none covering an actor credit. Revision 1 counted four and claimed none covered present-tense actor prose, which the roster plant disprovedNone
Nothing was published, spent or sentGit and the hostRook, 2026-09-19Met: no deployment, no registry entry, no message, no payment, no dependencyDavid's release word remains the gate
The product is untouchedgit diff --stat e3e54feRook, 2026-09-19Met: the changes are documents, one shell script, one Python check and its test; no file under eligibility/, public/, ops/ or tests/test_checks.pyFeature work is the next increment and is not started
The record states who assesses itdocs/RECORDS.md and this recordRook, at this revisionMet after correction. Revision 1 wrote "the assessor" without naming Verity, and the roster in the same commit had the name; the convention's own worked example omitted a rule the convention statesA rule stated in docs/RECORDS.md and broken by the example beside it is the defect the example exists to prevent; the naming rule now also covers this page's own actors
The record carries its landing revisionThis record, Work:Rook, at this revisionMet after correction. Revision 1 said TBD in a submitted recordDavid's instruction asked for the record's path and commit
The front-matter check runs where the records are filedscripts/check_records.sh, scripts/ci.sh, .github/workflows/ci.ymlRook, 2026-09-19Partly met, and the gap is structural. The check runs on this machine; on a GitHub runner it skips, so half of make records has never run in CI. The script says so loudly, and docs/RECORDS.md now records it as a limit rather than a passRecorded in TODO.md as David's decision: vendor the checker, fail on a skip, or accept it as local-only. The increment did not settle it because each option changes what a green build means
The documents agree with each other and with the checksThe six checked documents, read against the script and against each otherRook, at this revisionMet after correction. The independent check found: "a job title" where the check is five listed words (four places); "three files" where there are four; a stale docs/records/README.md; a Next pointing at a return that could not come; a wrong count; a claim that a skip leaves a summary line it does not; and a sentence in CONTEXT.md giving the wrong reason for its own list. All are correctedThe pattern in all of them is the same: prose written from the author's intent rather than re-read against the artefact. It is the strongest argument in this increment for checks over care

Delivery acceptance is separate from benefit. This increment delivers a name, a check and revised documents. It establishes no external user, no revenue and no improvement to any report. Nor does it establish that the corpus is now good: it establishes that five role words are caught mechanically and that six ambiguities a first reader would have had to guess at are now written rules. Everything else about the corpus's readability is still a judgement, and David's to make.

Independent check

Commissioned at 19:15:07, after the choices were registered and before the outcome was known, as the verification unit in the plan. One unit, not two. The grant: Verity (named in docs/ACTORS.md) reads the returned record against the convention it claims to follow, works the new check adversarially in a temporary copy, and reports findings with a recommendation to David. It was granted no authority to change anything, and it changed nothing.

Criteria registered before the outcome, verbatim from the commission: the record files cleanly under the revised convention; one planted violation and one planted escape-hatch marker are each caught; nothing in the documents contradicts the checks; and no actor in the corpus or the process documents is unnamed.

The independent check's return

Verity's recommendation was accept with corrections, with four material findings. Its report is not reproduced here in full — it is long, and the parts that changed the work are the four below. Reproductions were run by Verity in /tmp copies and re-run by Rook after the corrections; the working tree was never used as a test bed.

#FindingSeverityResponse
V1The record does not state who assesses it, and docs/records/README.md still said the directory was empty on purposeMaterialVerity is named in this record's Next and above; the README is now the corpus index. The convention's own example was breaking a rule the convention states
V2The staleness guard tested the concatenation of every block in a file, so a legitimate block licensed a stale one beside itMaterialFixed: each block is tested on its own. test_one_good_block_does_not_license_a_stale_one pins it. Verified by appending a second, empty block to docs/RECORDS.md in a copy: it now fails
V3A marked block could cover the roster and a role word planted in it passed — the escape hatch was demonstrable, not hypotheticalMaterialFixed: a block may not cover an actor credit or a roster row, and docs/ACTORS.md is restructured so the roster sits outside the marked text. Verified by planting <!-- actor-naming: discusses-rule -->Coordinator<!-- actor-naming: end --> in the roster: it now fails
V4The documents describe a five-word denylist as catching "a job title", and RECORD.md said "three files" where the check has fourMaterialReworded in all four places; the check's page now says plainly what it catches and what it does not

Verity's minor findings were all corrected too: the TBD landing revision, the stale Next, the wrong counts, the claim that a skipped check leaves a summary line it does not, the CONTEXT.md sentence that gave the wrong reason for its own list, and a dead constant in the script.

What Verity could not establish, in its own words and worth keeping: whether a genuine stranger can follow these documents — it was briefed, so its reading is not the no-context test this record leaves open; whether any real violation currently hides in a marked block, since it could demonstrate the possibility but not prove a negative about future text; and anything about the host, the registry or outbound effects. Its "nothing was published" check inspected the repository, not the world.

Assessment of the return. The work was independently checked rather than self-assessed, and the check found two defects that the author's own tests had passed — which is the finding that justifies the cost. The criteria were registered before the return, so this is an assessment against a saved basis and not an account written to fit the result. Verity's recommendation is advice: acceptance is David's, and this record does not take it.

Changes

Revision 1, 2026-09-19T19:15:07-06:00. Created as the corpus's first sub-record, filed with its frame, alternatives, selection, plan and review. Source: David's instruction to the first worker on 2026-09-19. Reason: the conventions had to be settled and enforceable before feature work, and the corpus's first entry is the worked example later records follow. Affects: AGENTS.md, CONTEXT.md, docs/RECORDS.md, docs/ACTORS.md, docs/ARCHITECTURE.md, RECORD.md revision 5, scripts/check_actors.py, tests/test_actor_check.py, scripts/check_records.sh. No selection, objective or test in RECORD.md revisions 1–4 is altered. Nothing is published, spent or sent.

Revision 2, 2026-09-19T19:33:00-06:00. Amends revision 1 after the independent check returned. Source: Verity's report to David of the same day, commissioned by Rook and registered under Independent check. Reason: four material findings, two of them defects in the new check, so neither the increment nor its worked example could stand as filed. Changes: the check tests each marked block on its own and refuses a block that covers an actor credit or a roster row; docs/ACTORS.md is restructured so the roster is outside the marked rule text and now says plainly that the check is a five-word denylist; tests/test_actor_check.py grows to 23 cases; the "job title" and "three files" descriptions are corrected wherever they appeared; docs/records/README.md becomes the corpus index; this record names Verity as the assessor, carries its landing revisions, corrects the 36-violation claim to the measured 38, narrows its own overclaims and adds the check's return and the assessment of it. RECORD.md is amended at its revision 6 for the same reasons. Revision 1 is preserved in Git at 2cf38fc. No selection, objective, test or reversal condition in revision 1 is altered. Nothing is published, spent or sent.

How this record connects

It builds on or points to: RECORD, RECORD § authority, ACTORS, RECORDS § registration order, CONTEXT, AGENTS, RECORDS § what is inside the checked set, ACTORS § how the name was chosen, ARCHITECTURE, RECORDS.

It is referenced by: Make small suppliers eligible to AI agents, Actors.