Development record
Relationships
decisionsprinciplesintentsspecsissuesdisciplines
closedresolvedshippedopenplanneddraftssupersededwontfix
Stand by…
Browse as a list
- a-model-run-is-re-runnable-not-reproducibleA model run is re-runnable, not reproducible
- a-remedy-is-filed-wholeA remedy is filed whole, built where it can be, measured where it cannot
- abcd-fixes-what-it-addsabcd fixes what it adds
- adopt-contributor-commitsAdopt contributor commits
- adversarial-review-scales-with-blast-radiusAdversarial review scales with blast radius
- at-every-refusal-emit-what-the-tool-knowsAt every refusal, emit what the tool knows
- basics-built-in-adapters-bring-powerBasics built in, an external dependency brings full power
- consult-freely-cite-deliberatelyConsult Freely, Cite Deliberately
- coordination-lives-on-the-shared-remoteCoordination lives on the shared remote, never only in conversation
- decompose-before-filingDecompose Before Filing
- durable-state-lives-where-the-platform-says-it-survivesDurable state lives where the platform says it survives
- enforcement-claims-are-factsEnforcement claims are facts
- evaluate-at-the-user-surfaceEvaluate at the user surface
- evaluator-outside-the-loopEvaluator outside the loop
- every-claim-has-one-homeEvery claim has one home
- examples-use-reserved-identifiersExamples use reserved identifiers
- facilitator-default-thinker-optionalFacilitator by default, thinker optionally
- fix-the-detectorFix the detector
- guards-prove-themselvesGuards prove themselves
- guidance-carries-its-evidence-and-its-purposeGuidance carries its evidence and its purpose
- instructions-to-a-person-are-verified-and-linkedInstructions to a person are verified and linked
- less-but-betterLess, but better
- loud-stagingLoud staging
- memory-graduates-to-recordMemory graduates to the record
- one-canonical-primitiveOne canonical primitive
- one-writer-per-fileOne writer per file
- pre-existing-is-not-a-defencePre-existing is not a defence
- prefer-sotaPrefer SOTA
- prefer-the-experiment-to-the-inferencePrefer the experiment to the inference
- ratchet-not-big-bangRatchet, not big bang
- reality-is-filableReality is filable
- recurrence-is-signalRecurrence is signal
- retire-the-nameRetire the name
- script-first-mvpScript-first MVP
- secret-shaped-fixtures-at-runtimeSecret-shaped fixtures are built at runtime
- sota-per-intentSOTA Per Intent
- spec-moves-with-the-surfaceSpec moves with the surface
- the-record-lands-with-the-actThe record lands with the act
- the-users-directory-is-theirsThe user's directory is theirs
- unrecognized-input-never-writesUnrecognised input never writes
- verifier-selects-gates-decideVerifier selects, gates decide
- waiting-holds-one-item-never-a-sessionWaiting holds one item, never a session
- widen-options-never-recommendWiden options, never recommend
- workaround-records-the-defectWorkaround records the defect
- itd-1Every Intent Has Acceptance Criteria; Every Audit Verifies Themblocks itd-5 · blocks itd-81 · blocks itd-84 · built on by itd-190 · built on by itd-21 · built on by itd-27 · built on by itd-28 · built on by itd-30 · built on by itd-34 · built on by itd-37 · built on by itd-80 · related adr-2 · related iss-2610262031299872 · related iss-2610262033567089 · related iss-2610262037138873 · related iss-2610262037142878 · related iss-2610262038389473 · related iss-2610262038393994 · related iss-2610262038399413 · related iss-2610262038415265 · related iss-2610262040343151 · related iss-2610262040355731 · related iss-2610262042332488 · related iss-2610262042345947 · related iss-2610262042363456 · related iss-2610262043043502 · related iss-2610262043043610 · related iss-2610262043221489 · related iss-2610262043257570 · related iss-2610262043392051 · related iss-2610262043406581 · related iss-2610262043417816
- itd-2In-Session Subagent Dispatch — the Default Host-Delegated Oraclerelated adr-35 · related adr-39 · related itd-2609201916151817 · superseded by itd-2609201916056194
- itd-3abcd Loads Its Own Rules On Demandbuilt on by itd-2609292109214516 · built on by itd-2610091918433290 · built on by itd-83 · built on by itd-89 · implements spc-1 not in the tree · related adr-2610030814023326 · related adr-2610091918443997 · related iss-2610241427397332 · related iss-2610262032050596 · related iss-2610262032060007 · related iss-2610262033133842 · related iss-2610262033143329 · related iss-2610262036437864 · related iss-2610262038011053 · related iss-2610262039423717 · related iss-2610262039439681 · related iss-2610262041454448 · related iss-2610262041455139 · related iss-2610262043334834 · related iss-2610262044344649 · related iss-2610262044555198 · related iss-2610262044561718 · related iss-2610262045254107 · related iss-2610262045266820 · related iss-2610262045278708 · related iss-2610262045286894
- itd-4Nothing You Notice Gets Lostblocks itd-25 · built on by itd-116 · built on by itd-119 · built on by itd-120 · built on by itd-20 · built on by itd-2609221656361680 · built on by itd-46 · built on by itd-82 · implemented by spc-6 · related adr-12 · related adr-32 · related iss-2610262032042626 · related iss-2610262034550860 · related iss-2610262034566586 · related iss-2610262034567348 · related iss-2610262039487315 · related iss-2610262039494979 · related iss-2610262041559803 · related iss-2610262041563970 · related iss-2610262044218994 · related iss-2610262045343669 · related iss-2610262045478245
- itd-5Every Agent Prompt Carries Its Version, Earns Its Lock, And Survives Injectionblocked by itd-1 · blocks itd-14 · blocks itd-81 · built on by itd-17 · built on by itd-48 · related adr-2 · related iss-2610262031326077 · related iss-2610262031337587 · related iss-2610262031338081 · related iss-2610262032566420 · related iss-2610262033586792 · related iss-2610262038415713 · related iss-2610262038425929 · related iss-2610262038431352 · related iss-2610262038443634 · related iss-2610262038457611 · related iss-2610262040485856 · related iss-2610262040499690
- itd-6RepoPrompt over MCP is one opt-in reviewer route, beside the host's own agentsbuilds on itd-2609170822093401 · builds on itd-2609201916056194 · builds on itd-2609201916151817 · builds on itd-2609201925079472 · implemented by spc-2609211950427074 · related adr-2609221009491186 · related adr-2609300107513982 · related iss-2610241426406882 · related iss-2610262032144104 · related iss-2610262033202441 · related iss-2610262033219255 · related iss-2610262035171024 · related iss-2610262036514870 · related iss-2610262036529540 · related iss-2610262038033829 · related iss-2610262038043808 · related iss-2610262038052818 · related iss-2610262040082360 · related iss-2610262040093616 · related iss-2610262040125215 · related iss-2610262042130595 · related iss-2610262042143519 · related iss-2610262043470447 · related iss-2610262043485833 · related iss-2610262043494574 · related iss-2610262044485589 · related iss-2610262044499326 · related iss-2610262044503777 · related iss-2610262044512344 · related iss-2610262045146746 · related iss-2610262045177576 · related iss-2610262045365573 · related iss-2610262045372683 · related itd-2609081951381895 · related itd-2609201916056194 · related itd-2609221017023290
- itd-7Lifeboats Carry RepoPrompt Workspace Definitions Forwardrelated adr-34 · related iss-2610262031532231 · related iss-2610262031537827 · related iss-2610262033075573 · related iss-2610262034360121 · related iss-2610262034363298 · related iss-2610262039347531 · related iss-2610262041227792 · related iss-2610262045089996
- itd-8Lifeboats Carry Source Code, Not Just Lessonsrelated iss-2610262033030496 · related iss-2610262039173971 · related iss-2610262044045987 · related iss-2610262044466021
- itd-9Old Lifeboats Still Unpackbuilt on by itd-16 · built on by itd-35 · related iss-2610262044045987
- itd-10Full Removal When You Mean Itbuilds on itd-13 · related iss-2610262031329436 · related iss-2610262032548523 · related iss-2610262038521887 · related iss-2610262040479670
- itd-11Disembark Survives Noisy Transcriptsrelated adr-35 · related iss-2610262032561511 · related iss-2610262032572271 · related iss-2610262036068415 · related iss-2610262038460690 · related iss-2610262043053279
- itd-12Working Notes Don't Outrank Settled Decisionsrelated iss-2610262032577014 · related iss-2610262042372556
- itd-13Reviews and Memory Stay Fresh, Alwaysbuilt on by itd-10 · built on by itd-25 · related iss-2610262034143915 · related iss-2610262038534481
- itd-14Prompts Are Versioned Like Codeblocked by itd-5 · builds on itd-15 · built on by itd-15 · related iss-2610262038472526 · related iss-2610262038484184 · related iss-2610262040499773
- itd-15abcd Audits Its Own Prompts on Every Self-Disembarkbuilds on itd-14 · built on by itd-14 · related iss-2610262032578385
- itd-16`/abcd:audit` Is the Umbrella; Conversation/Edit Chain Is Its Default Applicationblocks itd-35 · builds on itd-9 · related adr-40 · related iss-2610262031298011 · related iss-2610262031305231 · related iss-2610262034027543 · related iss-2610262036067608 · related iss-2610262038541403 · related iss-2610262038559695 · related iss-2610262040357240 · related iss-2610262042244924
- itd-17Pick the Right Oracle for the Job, Automaticallybuilds on itd-5 · related adr-25 · related itd-2609170822093401 · related itd-2609221009495079 · related adr-8 not in the tree · superseded by itd-2609221009495079
- itd-18Sensible Permissions From Day Onebuilt on by itd-21
- itd-19Defaults That Match Where the Project Livesrelated iss-2610262037211310 · related iss-2610262042426018 · related iss-2610262043485833
- itd-20`/abcd` Tells You Where You Arebuilds on itd-4 · built on by itd-200 · related iss-168 · superseded by itd-121
- itd-21Start a New Project With abcd Conventionsbuilds on itd-1 · builds on itd-18 · related adr-35 · related iss-2610262031362851 · related iss-2610262034034042 · related iss-2610262036053576
- itd-22abcd Reaches Any Harness Through an Adaptorbuilt on by itd-2609212137128014 · built on by itd-33 · related adr-2610030814023326 · related adr-39 · related itd-2609201916056194 · related itd-2610120738075547
- itd-23Lifeboats Speak To External Tools
- itd-24Completed Releases Get A Retrospectiveimplemented by spc-2609211751376504 · related adr-2609212115255771 · related iss-2610241431221889 · related iss-2610262031592610 · related iss-2610262033081135 · related iss-2610262033086503 · related iss-2610262033096678 · related iss-2610262034479574 · related iss-2610262041301883 · related iss-2610262041318943 · related iss-2610262043005827 · related iss-2610262043017551 · related iss-2610262044017905 · related iss-2610262044029050 · related iss-2610262044093076 · related iss-2610262044102287 · related iss-2610262044591588 · related iss-2610262045054264 · related iss-2610262045168363 · related iss-2610262045198472 · related iss-2610262045214826 · related itd-2609211913453478 · related itd-2609231013154443
- itd-25Patterns Surface Themselvesblocked by itd-4 · builds on itd-13 · builds on itd-36 · built on by itd-26 · related iss-2609211905340006 · related iss-2610262031301413 · related iss-2610262031315138 · related iss-2610262031318900 · related iss-2610262034005768 · related iss-2610262034012499 · related iss-2610262034017438 · related iss-2610262037227384 · related iss-2610262038565943 · related iss-2610262038572033 · related iss-2610262038577903 · related iss-2610262040369028 · related iss-2610262040379523 · related iss-2610262040388759 · related iss-2610262042363456 · related iss-2610262043297244 · related iss-2610262043303389 · related iss-2610262043466977 · related iss-2610262043470447
- itd-26Raid the Open Ocean, Bring the Cargo Home with Papersblocked by itd-36 · builds on itd-25 · related iss-2609211905346507 · related iss-2610262031343432 · related iss-2610262031344534 · related iss-2610262031347358 · related iss-2610262032585048 · related iss-2610262034120625 · related iss-2610262034127412 · related iss-2610262037238195 · related iss-2610262038581765 · related iss-2610262040391985 · related iss-2610262040403877 · related iss-2610262042452621 · related iss-2610262043026422 · related iss-2610262043310309
- itd-27Domain Experts Get Their Intents Grilled Before Anyone Codes Themblocks itd-29 · blocks itd-42 · builds on itd-1 · related adr-7 · superseded by itd-94
- itd-28Spec-Tied Reviews Live Next To The Spec They Reviewedbuilds on itd-1 · built on by itd-29 · implemented by spc-2609211854150455 · related iss-2610262034543078 · related iss-2610262035005988 · related iss-2610262040004118 · related iss-2610262041579226 · related iss-2610262043240944
- itd-29Domain Experts Run A Spec Autonomously And Recover From Anything Without Touching Gitblocked by itd-27 · builds on itd-28 · related itd-2609201916151817 · related itd-2609201925079472 · superseded by itd-2609201916151817
- itd-30Design Fictions As An Alternative Capture Format For Intentsblocked by itd-94 · builds on itd-1 · builds on itd-34 · related iss-2610262031445910 · related iss-2610262031451829 · related iss-2610262033062965 · related iss-2610262034207649 · related iss-2610262034212278 · related iss-2610262037339788 · related iss-2610262039090204 · related iss-2610262039093344 · related iss-2610262041080508 · related iss-2610262041095549 · related iss-2610262041101430 · related iss-2610262044093076 · related iss-2610262044170732 · related iss-2610262044430202
- itd-31The Brief and Every Intent Stay Consistent — Or Abcd Tells You Why They Don'tsuperseded by itd-48 · supersedes itd-32
- itd-32Every Audit In Abcd Knows What It Audits, By What, And Against Whatsuperseded by itd-31
- itd-33Multiple Agents Coordinate On Intent And Spec Work Without Duplicating Effort Or Producing Competing Artefactsblocked by itd-121 · builds on itd-22 · builds on itd-2609201916151817 · related itd-2609221656361680 · related itd-2609221656373558 · superseded by itd-2609091034175565
- itd-34Intents Promote In Three Flavours — Standalone, Bundle-Member, Disciplineblocks itd-44 · builds on itd-1 · built on by itd-2609211913453478 · built on by itd-2609291923559186 · built on by itd-30 · built on by itd-48 · built on by itd-80 · implemented by spc-2609211859391533 · related adr-2 · related adr-2609212115255771 · related adr-3 · related iss-2610262032015266 · related iss-2610262032018111 · related iss-2610262032022112 · related iss-2610262032024089 · related iss-2610262032024609 · related iss-2610262032031758 · related iss-2610262032038666 · related iss-2610262032044265 · related iss-2610262034513980 · related iss-2610262034520240 · related iss-2610262034528274 · related iss-2610262037533417 · related iss-2610262039443223 · related iss-2610262039451705 · related iss-2610262039463304 · related iss-2610262039476904 · related iss-2610262039572342 · related iss-2610262041499021 · related iss-2610262041516427 · related iss-2610262041521807 · related iss-2610262041529246 · related iss-2610262041532193 · related iss-2610262041545005 · related iss-2610262043221489 · related iss-2610262043232891 · related iss-2610262045327872 · related iss-2610262045336833 · related iss-2610262045357230
- itd-35Lifeboats Carry Their Own Integrity Proofblocked by itd-16 · builds on itd-9 · related iss-2610262031437177 · related iss-2610262033042911 · related iss-2610262039066046 · related iss-2610262041102872 · related iss-2610262043528869
- itd-36Knowledge That Compounds, Not Knowledge That Re-Derivesblocks itd-26 · built on by itd-25 · built on by itd-37 · implemented by spc-2609211905174684 · related adr-13 · related adr-2610141646523373 · related adr-28 · related adr-32 · related iss-2610262032046139 · related iss-2610262033155666 · related iss-2610262034535349 · related iss-2610262034587290 · related iss-2610262038000309 · related iss-2610262039522985 · related iss-2610262039527135 · related iss-2610262041468809 · related iss-2610262041476159 · related iss-2610262041481549 · related iss-2610262041504223 · related iss-2610262044356372 · related itd-2610091918433290
- itd-37Every Spec Externalises How It Should And Shouldn't Be Modifiedbuilds on itd-1 · builds on itd-36 · related adr-2 · related iss-2610262032580449 · related iss-2610262034090653 · related iss-2610262037246775 · related iss-2610262038495354 · related iss-2610262038501901 · related iss-2610262038511722 · related iss-2610262040508345 · related iss-2610262043232891 · related iss-2610262043436609
- itd-39abcd Surfaces the Right Memory at the Right Momentbuilt on by itd-44 · implemented by spc-2610111627213138 · related adr-2610091918443997 · related iss-2610262031560983 · related iss-2610262031565906 · related iss-2610262033124129 · related iss-2610262033126804 · related iss-2610262034370169 · related iss-2610262034384038 · related iss-2610262039325628 · related iss-2610262039330569 · related iss-2610262039345320 · related iss-2610262041226231 · related iss-2610262041234230 · related iss-2610262041245870 · related iss-2610262043026422 · related iss-2610262043030522 · related iss-2610262044561718 · related iss-2610262044572933 · related iss-2610262045091104 · related iss-2610262045100283 · related iss-2610262045119850 · related iss-2610262045183188 · related itd-2610091918433290
- itd-40abcd Knows What Kind of Folder You're Inimplemented by spc-5 · related iss-2610262032051655 · related iss-2610262033139821 · related iss-2610262036424620 · related iss-2610262039504627 · related iss-2610262039519748 · related iss-2610262042030813 · related iss-2610262043303389 · related iss-2610262045296807
- itd-41abcd Tells You, Honestly, What a Phasing Choice Costsbuilt on by itd-42 · related adr-10 · related iss-2610262031429165 · related iss-2610262033041268 · related iss-2610262034220886 · related iss-2610262039128746 · related iss-2610262041140753 · related iss-2610262042314589 · related iss-2610262044017905 · related iss-2610262044146391
- itd-42Grill Reads an Intent Against the Brief and Its Siblings, Not Just the Glossaryblocked by itd-27 · builds on itd-41 · built on by itd-2609212137116617 · implemented by spc-2609211918551301 · related iss-2610262032113433 · related iss-2610262032125902 · related iss-2610262035071845 · related iss-2610262035075414 · related iss-2610262040034904 · related iss-2610262042079651 · related iss-2610262042081902 · related iss-2610262043456762 · related iss-2610262044520698 · related iss-2610262045183188 · related iss-2610262045524988 · related itd-2609211913453478
- itd-43abcd Speaks One Word for a Specced Block of Work, and That Word Is "Spec"built on by itd-50 · implemented by spc-8 · related adr-11 · related adr-26 · related adr-34 · related iss-2610262035181369 · related iss-2610262040189116 · related iss-2610262043469929 · related iss-2610262045336833 · related iss-2610262045343669
- itd-44A Capture-Time `decision` Verdict That Routes Infrastructure Choices Into The Existing ADR Storeblocked by itd-34 · builds on itd-39 · built on by itd-50 · related iss-2610262031430108 · related iss-2610262031445176 · related iss-2610262034181775 · related iss-2610262034191519 · related iss-2610262036171679 · related iss-2610262036186092 · related iss-2610262037334466 · related iss-2610262039106613 · related iss-2610262041183220 · related iss-2610262041199183 · related iss-2610262042486043 · related iss-2610262044038958 · related iss-2610262044186274 · related iss-2610262044191365 · related iss-2610262044540397
- itd-46`/abcd:intent "<text>"` And `/abcd:capture "<text>"` Become Symmetric Create Pathsbuilds on itd-4 · implemented by spc-7 · related adr-12 · related iss-2610262032194841 · related iss-2610262035089991 · related iss-2610262035091535 · related iss-2610262040034442 · related iss-2610262042088869 · related iss-2610262042091628 · related iss-2610262043466977 · related iss-2610262044430202 · related iss-2610262044474439 · related iss-2610262045199145 · related iss-2610262045235833 · related iss-2610262045246595 · related iss-2610262045552105
- itd-47Oracle-Backed Gates Pass Honestly Without A Human In The Loopsuperseded by adr-22
- itd-48`intent-fidelity-reviewer` Gains Its Cross-Doc And Kind-Classification Rolesbuilds on itd-34 · builds on itd-5 · built on by itd-2609291923559186 · implemented by spc-2609211921272106 · related adr-40 · related iss-2610262032120773 · related iss-2610262032124254 · related iss-2610262032131693 · related iss-2610262032133109 · related iss-2610262033205781 · related iss-2610262035033556 · related iss-2610262035045702 · related iss-2610262035056745 · related iss-2610262040083517 · related iss-2610262040161220 · related iss-2610262042109861 · related iss-2610262042115843 · related iss-2610262042125545 · related iss-2610262043392051 · related iss-2610262043436609 · related iss-2610262044513201 · related iss-2610262045168363 · related iss-2610262045327872 · related itd-2609212137116617 · supersedes itd-31
- itd-49Flow-State Drift Becomes Visible Before It Compoundssuperseded by adr-26
- itd-50The Audit Loop Drives An Intent To Acceptance — Or Calls For A Replanblocked by itd-53 · builds on itd-43 · builds on itd-44 · built on by itd-2609211116005482 · built on by itd-82 · implemented by spc-2609211924346308 · related iss-2610262031563379 · related iss-2610262034333292 · related iss-2610262034335136 · related iss-2610262034345807 · related iss-2610262034354642 · related iss-2610262037438474 · related iss-2610262037443119 · related iss-2610262039297157 · related iss-2610262039302287 · related iss-2610262039314007 · related iss-2610262041325659 · related iss-2610262041338234 · related iss-2610262043043502 · related iss-2610262043043610 · related iss-2610262043093810 · related iss-2610262045054264 · related iss-2610262045122268 · related iss-2610262045126115 · related itd-2609201916151817
- itd-51abcd Knows What "Safe Enough to Adopt" Means Before a New Harness Arrivesrelated adr-27 · related itd-2609201916056194
- itd-53A Shipped Intent No Longer Drifts Out Of Audit Just Because Nobody Ran The Reviewblocks itd-50 · implemented by spc-2609211930059886 · related adr-40 · related iss-2610262035102052 · related iss-2610262035104777 · related iss-2610262035112905 · related iss-2610262040116437 · related iss-2610262042237923 · related iss-2610262045122268 · related iss-2610262045126115 · related iss-2610262045533651 · related adr-16 not in the tree
- itd-55abcd Can Tell Whether Its Own Reasoning Rests On Bedrock Or On An Unexamined Assumptionrelated iss-2610262034293679 · related iss-2610262039132211 · related iss-2610262041175899 · related iss-2610262044520698
- itd-57Every abcd Voyage Ships With A Manual-Hold Sentinel That Blocks A Spec From Autonomous Pickup Until A Human Lifts Itrelated adr-26 · related adr-27 · related iss-2610262031462724 · related iss-2610262031514386 · related iss-2610262034233163 · related iss-2610262037255566 · related iss-2610262039144591 · related iss-2610262039150797 · related iss-2610262041112989 · related iss-2610262041122493 · related iss-2610262044060780 · related iss-2610262044240923 · related iss-2610262044454212
- itd-58A Real Reviewer's SHIP Verdict Reaches The Session Gate Through A Channel The Worker Cannot Forgerelated adr-27 · related adr-8 not in the tree · superseded by itd-2609201916151817
- itd-59Every Autonomous Run Pass Leaves the Same Durable, Queryable Transcript an Interactive Session Doesbuilds on itd-2609201916151817 · related adr-27 · related adr-29 · related iss-2610262031439210 · related iss-2610262033019185 · related iss-2610262036113224 · related iss-2610262036129928 · related iss-2610262037262122 · related iss-2610262039086156 · related iss-2610262041210479 · related iss-2610262044057318 · related iss-2610262044255432 · related itd-2609212137128014
- itd-60When A Surface Ships, The Brief Describes It — Or The Intent Does Not Reach Shippedbuilds on itd-73 · builds on itd-80 · built on by itd-61 · built on by itd-62 · built on by itd-64 · implemented by spc-2609020903498198 · related adr-2610290238168123 · related iss-2610262032193797 · related iss-2610262036483439 · related iss-2610262036495984 · related iss-2610262038097833 · related iss-2610262040177541 · related iss-2610262040192600 · related iss-2610262042159336 · related iss-2610262044453777 · related iss-2610262045454143 · related iss-2610262045459641 · related iss-2610262045465811
- itd-61A Human Edit To The Brief Cannot Commit Until Its Implied Intents And Principles Are Drawn Out And Reconciledbuilds on itd-60 · built on by itd-2611011151512956 · built on by itd-62 · related iss-2610100649481907 · related iss-2610262034302701 · related iss-2610262039169067 · related iss-2610262041158645 · related iss-2610262041163346 · related iss-2610262042541203 · related iss-2610262044453777 · related iss-2610262044537770
- itd-62abcd Routes The Invisible Risks An Amateur Cannot See To A Real, Fail-Closed Gate That Wraps A Trusted Scannerbuilds on itd-60 · builds on itd-61 · built on by itd-63 · related adr-2611011813195749 · related iss-2610262033027180 · related iss-84 · related itd-2609291923559186
- itd-63The Amateur Coder Is Told What Is Being Installed And Why, Not Just Asked To Run A Commandbuilds on itd-62 · built on by itd-2609221017023290 · implemented by spc-2609211955339422 · related adr-22 · related adr-2609221017021499
- itd-64abcd Learns From Its Own Runs Which Configurations Work Best, And Tunes Its Configuration Layer Accordinglybuilds on itd-60 · builds on itd-75 · related iss-2610262031516342
- itd-65abcd Refuses To Publish A Payload Until The Full Ship-Time Pre-Flight Gate Suite Passes, Not Just The Secret Scanblocked by itd-66 · builds on itd-67 · built on by itd-72 · implemented by spc-2609201955279019 · related adr-28 · related adr-33 · related iss-2610262036509587 · related iss-2610262045222030 · related iss-2610262045380381
- itd-66abcd Renders The Exact Public Payload, Proves The Excludes Never Leak, And Smoke-Tests The Installed Surface Before Any Snapshotblocks itd-65 · built on by itd-67 · built on by itd-72 · implemented by spc-2609201955277614 · related adr-28 · related adr-33 · related iss-2610262045091104 · related iss-2610262045278708
- 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 Versionblocks itd-72 · builds on itd-66 · built on by itd-105 · built on by itd-108 · built on by itd-2609231013154443 · built on by itd-65 · built on by itd-69 · implemented by spc-11 · related adr-19 · related adr-2609231048308186 · related adr-28 · related iss-2610262032146377 · related iss-2610262032158578 · related iss-2610262033173969 · related iss-2610262033179679 · related iss-2610262033185478 · related iss-2610262033189165 · related iss-2610262035142666 · related iss-2610262035153070 · related iss-2610262035169561 · related iss-2610262038066422 · related iss-2610262042162078 · related iss-2610262042174713 · related iss-2610262045198472 · related iss-2610262045379282 · related iss-2610262045380381
- itd-69Plugin Metadata Stays Consistent Across Every Duplicated Surfacebuilds on itd-67 · implemented by spc-2609211957080006 · related adr-20 · related iss-2610262032157319 · related iss-2610262033194284 · related iss-2610262040159117 · related iss-2610262044537770
- itd-70Drawn-out intentrelated adr-33 · related iss-282
- itd-72Publishing A Release Is One Atomic, Refusable `ship`blocked by itd-67 · builds on itd-65 · builds on itd-66 · related adr-28 · related adr-33 · superseded by adr-37
- itd-73abcd Cuts the Version — You Never Type Onebuilt on by itd-2609231013154443 · built on by itd-60 · implemented by spc-10 · related adr-31 · related adr-33 · related adr-37 · related iss-2610262033180356 · related iss-2610262035168556 · related iss-2610262042183674 · related iss-2610262045379282 · related iss-2610262045391451 · related itd-2609212103572513
- itd-74abcd Keeps the Names You Ban Out of Everything You Publishblocks itd-76 · built on by itd-2609151516525843 · implemented by spc-20 · related adr-41
- itd-75abcd Proves Your CLI Actually Runs — From Fixtures You Drop Inbuilt on by itd-64 · related itd-2609212137128014
- itd-76abcd Lets You Consult Sources You Cannot Cite — and Remembers Every Debtblocked by itd-74 · builds on itd-77 · built on by itd-126 · built on by itd-127 · built on by itd-2609292108089653 · implemented by spc-31 · related adr-41 · related iss-2610262032158901 · related iss-2610262033224778 · related iss-2610262035135419 · related iss-2610262036474703 · related iss-2610262038084949 · related iss-2610262040149808 · related iss-2610262042193372 · related iss-2610262042201742 · related iss-2610262043501753 · related iss-2610262044449331 · related iss-2610262045119850
- itd-77abcd's User-Level Home Lives Where You Want Itbuilt on by itd-76 · related iss-2610262041051263 · related iss-2610262043555411 · related iss-2610262043562914 · related iss-2610262044265126 · related iss-2610262044449331
- itd-78abcd Knows What to Build First — Even When It's Something Smallrelated adr-2609212115255771 · related iss-2610262031420591 · related iss-2610262034225527 · related iss-2610262041158993 · related iss-2610262044029050 · related iss-2610262044159830 · related iss-2610262044160347 · related itd-2609211116005482 · related itd-2609211913453478 · related itd-2610170634394993
- itd-79Personas Come From the Registry; the Role Picks the Namerelated iss-2610262043159613 · related iss-2610262043268358
- itd-80An Intent Ships Itself: `planned → shipped` Follows Its Spec Closing, With A Fidelity Audit Attachedbuilds on itd-1 · builds on itd-34 · built on by itd-60 · implemented by spc-2 · related adr-25 · related adr-26 · related adr-2609151513118583 · related adr-27 · related iss-2610262032163067 · related iss-2610262032168367 · related iss-2610262035065340 · related iss-2610262038106941 · related iss-2610262040043356 · related iss-2610262040053417 · related iss-2610262040077279 · related iss-2610262042134366 · related iss-2610262043406581 · related iss-2610262043417816 · related iss-2610262043429522 · related iss-2610262044454212 · related iss-2610262044540397 · related iss-2610262045156888 · related iss-2610262045357230 · related iss-2610262045442294 · related iss-2610262045533651
- itd-81No Judge Ships Unmeasured, And A Clean Diff Is A Resultblocked by itd-1 · blocked by itd-5 · built on by itd-83 · related iss-2610262032558851 · related iss-2610262033588599 · related iss-2610262038490693 · related iss-2610262042345947 · related iss-2610262042351798 · related iss-2610262042495955 · related iss-2610262043240944 · related iss-2610262043429522
- itd-82`abcd drain` fixes the issues that need no decision, and hands the rest back by kindbuilds on itd-119 · builds on itd-2609201916151817 · builds on itd-2609201925079472 · builds on itd-4 · builds on itd-50 · built on by itd-2610301750162657 · built on by itd-2610301850454860 · implemented by spc-2609212015054359 · related adr-25 · related adr-2609291342092738 · related adr-27 · related iss-2610262031575425 · related iss-2610262031575529 · related iss-2610262031582038 · related iss-2610262037387137 · related iss-2610262037392162 · related iss-2610262037409579 · related iss-2610262041372020 · related iss-2610262041388352 · related iss-2610262042571852 · related iss-2610262043542024 · related iss-2610262044580425 · related iss-2610262045139907 · related iss-2610262045199145 · related itd-2609211116005482 · related itd-2609221009495079 · related itd-2610170634394993 · related itd-84
- itd-83The Review Bar Fires By Itself, In Every Repo abcd Managesbuilds on itd-3 · builds on itd-81 · related adr-40 · related iss-2610262031459784 · related iss-2610262033012386 · related iss-2610262034176558 · related iss-2610262039184070 · related iss-2610262039188312 · related iss-2610262044419558
- itd-84An Intent Is Decomposed Before It Is Filed, And A Reversal Is Only Ever Flaggedblocked by itd-1 · built on by itd-2609212137116617 · related iss-2610262033577968 · related iss-2610262036101369 · related iss-2610262042351798 · related iss-2610262042503210 · related itd-82
- itd-85A Read-Only Repo-Conformance Auditrelated adr-40 · related iss-2610262031419126 · related iss-2610262033013099 · related iss-2610262034151413 · related iss-2610262034164290 · related iss-2610262036142715 · related iss-2610262039195057 · related iss-2610262039214406 · related iss-2610262041077645 · related iss-2610262042244924 · related iss-2610262043515080 · related iss-2610262043528869 · related iss-2610262044201056 · related iss-2610262044218994 · related iss-2610262044229426
- itd-86abcd Can Read Its Own Design Documents As A Stranger Wouldbuilt on by itd-180 · built on by itd-183 · built on by itd-184 · related adr-36 · related adr-55 · related iss-2610262031492489 · related iss-2610262034268156 · related iss-2610262036146367 · related iss-2610262037357893 · related iss-2610262039216588 · related iss-2610262041209286 · related iss-2610262042256389 · related iss-2610262044082114 · related iss-2610262044237764
- itd-87A Finding That Comes Back After You Closed It Tells You Something, And abcd Stops Throwing It Awayrelated iss-2610262034242423 · related iss-2610262034255735 · related iss-2610262036157324 · related iss-2610262042279476 · related iss-2610262044079779 · related iss-2610262044221992 · related itd-2609212137116617
- itd-88Know What a Repo Can and Cannot Tell You — Before You Trust the Lifeboatimplemented by spc-3 · related adr-35 · related adr-36 · related iss-2610262032172837 · related iss-2610262032178049 · related iss-2610262033191807 · related iss-2610262042208017 · related iss-2610262043446144 · related iss-2610262044466021 · related iss-2610262045089996 · related iss-2610262045214826
- itd-89Capture the Session You Just Had, Because You Cannot Capture It Laterbuilds on itd-3 · implemented by spc-4 · related adr-29 · related iss-2610262032188853 · related iss-2610262033217382 · related iss-2610262036461110 · related iss-2610262038074426 · related iss-2610262040062985 · related iss-2610262040135811 · related iss-2610262042214474 · related iss-2610262045100283
- itd-90The Product Thinker Is Handed Exactly The Questions Only They Can Answer — And Nothing Elsebuilt on by itd-142 · related adr-35 · related adr-36 · related iss-2610262031493380 · related iss-2610262033033258 · related iss-2610262042269640
- itd-91A Project Declares Once How It Wants AI Acknowledged — And Every Commit, PR, And Record Followsrelated iss-2610262031466884 · related iss-2610262033022683 · related iss-2610262034182114 · related iss-2610262037372402 · related iss-2610262039224536 · related iss-2610262041065877 · related iss-2610262044429007 · related itd-131
- itd-92abcd tells every repo the truth about its fencebuilt on by itd-2609221842494980 · related adr-43 · related adr-44
- itd-93abcd Scaffolds a Release Gate That Works on the First Trybuilt on by itd-106 · implemented by spc-14 · implemented by spc-2609230613193436 · related adr-37 · related iss-2610262036512603 · related iss-327
- itd-94An intent that is not planned cannot be implemented: abcd gains a machine-checkable implement-readiness gate that refuses with a remedy and offers the planning interviewblocks itd-30 · implemented by spc-9 · related adr-40 · related iss-2610262035127167 · related iss-2610262038051992 · related iss-2610262042222565 · related iss-2610262045139907 · related iss-2610262045201587 · supersedes itd-27
- itd-95Disembark Grounds A Lifeboat's Open Questions On A Repo's TODO And FIXME Markersimplemented by spc-12 · related iss-2610262032182670 · related iss-2610262040109467
- itd-96Disembark Reads A Repo's Naming And Internals Conventions Into Its Lifeboatimplemented by spc-13 · related iss-2610262032189264
- itd-97The Facilitator Is a Mode, Not a Personbuilds on itd-2609201916151817 · built on by itd-2610150602547271 · built on by itd-98 · related adr-2610150603484802 · related adr-2610240850193281 · related adr-40 · related iss-2610262031486321 · related iss-2610262031496655 · related iss-2610262041130402 · related iss-2610262044004875 · related iss-2610262044094024 · related itd-2609212137129937
- itd-98Solo vs. Duo Is Measured, Not Debatedbuilds on itd-97 · related iss-2610262042495955 · related iss-2610262043598494
- itd-99A Team of Product Thinkers Decides as Onerelated adr-40 · related iss-2610262031483571 · related iss-2610262044102287 · related iss-2610262044119054
- itd-100Alice Reads One Page and Knows Exactly Where abcd Stands in the Agentic-AI Landscapeimplemented by spc-15 · related itd-2609061543533170 · related itd-2609212103568351
- itd-101**Every citation abcd publishes is provably alive and honestly labelled — and the gate that enforces it never flakes.** A cited reference page is only as trustworthy as its links, and links rot silently: pages retitle, URLs redirect, whole platforms announce their own shutdown. abcd splits citation validation across a deterministic gate and an explicit refresh. An offline lint family checks structure and source policy on every commit — footnote markers and definitions in bijection, URLs and DOIs well-formed, aggregator domains refused — with zero network in the gate. `abcd docs cite refresh` does the live fetching on demand and writes a committed baseline: per URL, the final resolved address, when it was last checked, and whether verification was automatic or manual — never how. Sources that block automated fetchers join a manual queue the maintainer clears link by link: printed as a checklist first, later as a generated, disposable checklist page that hands back a receipt file the verb ingests. The lint then enforces the baseline offline — no broken entries, no stale entries, no cited URL without a receipt, no citation whose recorded final address has drifted. The engine is native and dependency-free first; a specialist link checker can slot in later behind the same seam. "My release gate stays deterministic and my citations stay alive," said Kira, an open-source maintainer. "When a source needs human eyes, abcd hands me the exact list to click through and records that I did — not how I did it."implemented by spc-17 · related iss-2610262036322416
- itd-102**Your repo says the same thing about itself everywhere — because abcd asked you once and holds every surface to it.** A project's positioning fragments silently: the README strapline, the package or plugin manifest description, and the agent conventions file are each edited at different moments, and soon three surfaces tell three stories about what the project is. When abcd prepares a repo it interviews the user for the project's identity — title, tagline, and a short elevator pitch — and records the answers in one canonical home in the development record. Every surface rendering derives from that home, and a deterministic positioning check compares the surfaces against it on every audit: a mismatch is highlighted with the exact drifted line, and the fix is either re-render from the record or a deliberate, recorded identity change — never a silent extra variant, and never a silent rewrite by abcd. "I changed my tagline once, in one place, and abcd chased it everywhere else," said Alice, a solo founder. "When a stray edit crept into the README, the next audit pointed at the exact line instead of letting the drift settle in."built on by itd-2611011151475128 · implemented by spc-19 · related adr-2611011153058085 · related iss-2610262036330589 · related iss-2610262045017395 · related itd-112 · related itd-133
- itd-103**abcd teaches repo agents the shell commands they must never run — and blocks them when they try.** An agent that runs `cd scratch && rm -rf *` is one failed `cd` away from deleting the working tree, and the facilitator watching the session usually has no way to know that. abcd ships a hazard registry: each entry a dangerous command pattern, its severity, the safe successor, and a plain-language why. One registry, two planes. The rules loader injects the matched safety rules before shell-heavy work, so the agent is taught the safe form up front; a deterministic guard — a core verb any harness hook can call — refuses a matching command at execution time and replies with the safe successor, so the block itself is the lesson. Hosts without hook support still get the teaching plane; hosts with hooks get both, wired in at install. The registry grows from reality: a facilitator who sees something scary needs to know exactly one move — capture it — and recurring captures promote patterns into the bundled defaults, each entry shipping with a fixture that proves its guard fires. "I couldn't have told you why that command was dangerous," said Nia, a facilitator. "I didn't have to. The guard refused it, told the agent what to run instead, and told me why in words I understood. The one time something new scared me, I captured it and moved on."implemented by spc-16 · related adr-2610091150447054 · related adr-42
- itd-104**abcd gates a new idea before it becomes a record entry: research it against primary sources, grill it against the existing record, and let an independent adversary try to kill it.** A product thinker's exciting idea is cheapest to kill in its first hour — and most expensive to kill after it has minted intents, specs, and branches. `/abcd:ideate` runs the admission interview: SOTA research in which every load-bearing claim is checked against its primary source; a record grill — does the brief, an intent, an ADR, or a principle already cover, contradict, or supersede this?; and an independent adversarial review, evaluator outside the loop. The output is a verdict plus a recorded decision with rejected alternatives; only a surviving idea graduates to a draft intent. The protocol is already proven by hand: three ideas entered it on 2026-07-14 — two were killed (one by a measured null result its premise could not survive, one by three independently fatal methodological defects) and one was reframed by adversarial review before a line was built. The manual run also named the two load-bearing steps automation must keep: check the record first (one idea was already written and superseded), and open the primary (three secondary-source claims were falsified, one of them fabricated by tool extraction). "The ideas I'm proudest of are the ones abcd killed in an afternoon," said Iris, a product thinker. "Each one left a recorded reason behind, so I never talk myself back into them six months later."implemented by spc-18 · related iss-2610262034468406 · related iss-2610262036303950 · related iss-2610262036312405
- itd-105A fresh plugin install just works: the hook binary survives install and every updatebuilds on itd-67 · built on by itd-108 · built on by itd-130 · built on by itd-132 · built on by itd-2610161616086564 · built on by itd-2610161617096084 · implemented by spc-21 · related adr-2609151706587280 · related adr-38 · related adr-46 · related iss-2610262039378497 · related iss-2610262044572933
- itd-106abcd Sets Up the CI a Repo Requires, and Reports What It Didbuilds on itd-93 · related iss-2610262031403463 · related iss-2610262032556158 · related iss-2610262042367104 · related iss-2610262042399506 · related iss-2610262042403190 · related iss-2610262043135705 · related iss-2610262043265040
- itd-107Autonomous Routines Assemble From One Versioned Templaterelated iss-172 · related iss-178 · related iss-2608282124231752 · related iss-2610262037186224 · related iss-2610262039022652 · related iss-2610262042367104 · related iss-2610262043063912 · related itd-2610120738075547
- itd-108The plugin installs from the curated release artifact, not the repo, and every cut release reaches users automaticallybuilds on itd-105 · builds on itd-67 · built on by itd-111 · built on by itd-130 · related adr-2609231048308186 · related adr-38 · related iss-205 · related iss-206
- itd-109Acceptance Criteria Verify Themselves, And The Manual Rest Renders For A Humanrelated adr-40 · related iss-2610262043093810 · related iss-2610262043202769
- itd-110The grill interview renders with clear structure and colour instead of a wall of prose: each question visually separated, the decision point, options, and the recommended answer distinctly styled, progress through the design tree visible, so the person being grilled always knows what is being asked and where they arebuilds on itd-112 · superseded by itd-2610030810350727
- itd-111A Stale abcd Never Answers Silentlybuilds on itd-108 · built on by itd-2610031026190632 · built on by itd-2610161616086564 · built on by itd-2610161617096084 · implemented by spc-22 · implemented by spc-2609230613208843 · related adr-38 · related iss-2610262034492769 · related iss-2610262039403534 · related iss-2610262045033573
- itd-112A bare abcd on an interactive terminal opens with a generated banner: the flag hoist in half-block colour on its painted panel, version beside it, tagline beneath — identity baked in at build time, full colour ladder, never a byte on a machine-consumed streambuilds on itd-133 · built on by itd-110 · built on by itd-134 · built on by itd-144 · built on by itd-2610030810370060 · implemented by spc-2609230613206687 · implemented by spc-41 · related adr-49 · related itd-102 · related itd-133 · related itd-134
- itd-113The MCP Front Door Opens — abcd's Core Verbs From Any MCP-Capable Harnessrelated adr-2611011813195749 · related iss-2610262039030685
- itd-114Two Agents Can Mint At The Same Instant And Never Collideimplemented by spc-33 · related adr-45 · related iss-2610262034489695 · related iss-2610262043063912 · related iss-2610262043071551 · related iss-2610262044038958
- itd-115A Ready PR Merges Without Ever Wedging BEHINDrelated iss-2610262042372556 · related iss-2610262042381184 · related iss-2610262043071551 · related iss-2610262043143346 · related itd-2610170634394993 · superseded by itd-2610261025516272
- itd-116Validated GitHub Issues Become Ledger Entries Without Retypingbuilds on itd-4 · related itd-2609221656361680
- itd-117A Machine's Shared Conventions Are Declared Once In The User Scope — And Every Managed Repo Inherits Themimplemented by spc-23 · related iss-2610262031557534 · related iss-2610262033117994 · related iss-2610262034403157 · related iss-2610262036343040 · related iss-2610262037458871 · related iss-2610262039356482 · related iss-2610262041346676 · related iss-2610262043555411 · related iss-2610262044555198 · related iss-2610262045072539
- itd-118Merged work leaves no residue: abcd-managed repos delete a PR branch on merge, and abcd tidies the stale local branch, tracking ref, and worktreebuilt on by itd-148 · related adr-2609091014087993 · related adr-2609091248200336 · related adr-2610161940004937 · related iss-2610130501296659 · related iss-2610262042403190 · related iss-2610262043385436 · related itd-2609091014076309 · related itd-2609091034175565 · superseded by itd-2610222214476887
- itd-119An Issue Graduates Into An Intent Without Retypingbuilds on itd-4 · built on by itd-82 · implemented by spc-24
- itd-120A Resolved Issue Points At What Fixed Itbuilds on itd-4 · implemented by spc-25 · related iss-2610262043143346
- itd-121Type The Id, Get Your Next Moveblocks itd-33 · implemented by spc-26 · related iss-2610262045246595 · supersedes itd-20
- itd-122The Registry Cannot Wave Its Handsimplemented by spc-2609230613204830 · implemented by spc-27 · related iss-2610262033095338 · related iss-2610262034417109 · related iss-2610262036376225 · related iss-2610262045047151 · related itd-2609212130136102
- itd-123The Intent Audit Says Auditimplemented by spc-28 · related iss-2610262045156888 · related itd-2609212130136102
- itd-124The Conformance Check Calls Itself Lintimplemented by spc-29 · related iss-2610262043515080 · related iss-2610262045222030 · related itd-2609212130136102
- itd-125The Lifeboat Verdict Says What It Isimplemented by spc-30 · related iss-2610262033072029 · related iss-2610262041275614 · related iss-2610262043053279 · related iss-2610262045177576 · related itd-2609212130136102
- itd-126A Team Shares One Bibliography Without Sharing Anyone's Corpusbuilds on itd-76 · related adr-41 · related iss-2610262031350187 · related iss-2610262034102286 · related iss-2610262038595637 · related iss-2610262042473980 · related iss-2610262043322187
- itd-127A Paper Is Reconstructed From the Provenance Ledgerbuilds on itd-76 · related adr-41 · related iss-2610262040442493
- itd-128One canonical YAML scalar resolver: frontmatter exports the single null/bool/quote resolution helper and the capture, lint, lifeboat, and memory decoders all delegate to it, so a cross-package verdict split on any scalar axis becomes unrepresentable
- itd-129Forge mirror as an opt-in adapter: the ledger mirrors out to forge issues one way, the forge id lives in the record schema, closures without import self-heal, and the whole surface is loudly absent without forge authrelated adr-45
- itd-130`abcd update` completes a chosen update in one verbbuilds on itd-105 · builds on itd-108 · built on by itd-2609292106557115 · implemented by spc-32 · related iss-2610262036353820 · related iss-2610262039394542
- itd-131The managed-repo identity gate: the human is the author of record on every commit, before the first oneimplemented by spc-34 · related adr-2610241022541063 · related iss-62 · related itd-2609061543533170 · related itd-91
- itd-132The hook binary survives plugin updatesbuilds on itd-105 · implemented by spc-35 · related adr-2609151706587280 · related adr-46 · related iss-2608210934566221 · related iss-2608210934566222
- itd-133abcd has a face: one pixel-grid identity — duckling mascot, signal-flag logo, lifeboat mark — generated, drift-gated, ready for every surfacebuilt on by itd-112 · built on by itd-144 · implemented by spc-36 · related itd-102 · related itd-112
- itd-134Every abcd-managed CLI greets like abcd does: one command scaffolds a banner for a managed repo, rendered from that repo's canonical identity block — name, tagline, version — as a committed, language-neutral artefact (the generator emits the rendered banner, not code), so a CLI in any language opens with its own identity without hand-drawing anything. Split out of itd-112 at its 2026-08-21 grill: itd-112 keeps abcd's own banner and the colour ladder; this intent carries the managed-repo generator and the per-repo accent question.builds on itd-112 · related iss-2610262036082275 · related itd-112 · related itd-146
- itd-135Iris opens abcdev.app and understands who abcd is for, what they and their facilitator own, and how to install it — from one page rendered from the repositorybuilt on by itd-136 · built on by itd-137 · built on by itd-138 · built on by itd-139 · built on by itd-140 · built on by itd-2610091010348892 · implemented by spc-37 · related adr-2610091010387033 · related adr-47 · related adr-48 · related iss-2610262041269672 · related iss-2610262043135705
- itd-136Alice opens the record explorer and reads the whole development record — every decision, intent, spec and issue as a page, with contributors and references — without reading YAML on GitHubbuilds on itd-135 · built on by itd-137 · built on by itd-139 · implemented by spc-38 · related adr-2610291037481588 · related adr-47 · related adr-48
- itd-137Maya sees how every decision connects — one relationship chart with a date coil and a links-only layout, and a five-lane genealogy of the record over timebuilds on itd-135 · builds on itd-136 · implemented by spc-39 · related adr-47 · related adr-48 · related iss-2610262041254974
- itd-138Bob installs abcd with one checksum-verified command served from the project's own domainbuilds on itd-135 · implemented by spc-40 · related adr-47 · related adr-48 · related iss-2610262034494554 · related iss-2610262039410774 · related iss-2610262045024914
- itd-139Carol's team adopts abcd and gets a readable record the next day, without writing a line of site codebuilds on itd-135 · builds on itd-136 · related adr-47 · superseded by itd-2610032150577708
- itd-140The Generic/Specific Boundary of the Site Generator Is a Gate, Not a Hopebuilds on itd-135 · related adr-47 · related iss-2610262035592770 · related iss-2610262040433257 · related iss-2610262042437551 · related iss-2610262042445075 · related iss-2610262043369188
- itd-141docs-lint enforces the writing style guide's machine-checkable rules: an em dash inside a list item, a lower-case letter opening a list lead-in after its colon, and a capital letter after a semicolon are flagged as findings, with code spans and fenced blocks masked, so the canonical style guide's machine-enforceable subset is a shipped gate rather than a review habit — and the guide marks a rule machine-enforced only once its lint shipsrelated adr-53 · superseded by adr-54
- itd-142The brief-creation interview: abcd elicits a repository's brief in a staged conversation — narrative first, then frontier rounds that ask only what the record cannot yet settle, options at conjectural questions (at most three candidate construals, a ceiling not a target, with a null answer always available), and a per-item confirmation — distilling committed products into the brief and a ledger while the transcript is discarded. Entry is one door for both modes: a brownfield repository arrives pre-populated from embark probe coverage, provenance-stamped and still requiring confirmation; a greenfield repository is the same interview run from the all-blank coverage state. Command-shaped, because it mutates state — abcd ships zero skillsbuilds on itd-90 · related adr-50 · related adr-51 · related adr-55 · related iss-2610262031389232 · related iss-2610262036033754 · related iss-2610262040528498 · related iss-2610262042289741 · related iss-2610262042486043 · related iss-2610262043446144 · related iss-2610262043456762 · related iss-2610262043469929
- itd-143The brief gains a framing chapter under 01-product/ — the macro-why home: one section holds the project's framing, the why behind the why, and receives the brief-creation interview's committed framing products; the brief-lifeboat mapping gains the matching row so a lifeboat carries framing like any other sectionrelated adr-2609021016288378 · related adr-50 · related adr-55 · related iss-2610262031376538 · related iss-2610262034068157 · related iss-2610262040511595 · related iss-2610262042329594
- itd-144Every livery mark has a surface and earns it: the duckling, the lifeboat, and the two-by-two signal-flag icon are placed deliberately across abcd's surfaces instead of sitting as generated-but-unused assets. The lifeboat mark renders when disembark finishes packing a lifeboat and mirrors when embark unpacks one, so the direction of travel reads at a glance; the duckling appears as the mascot wherever the harness greets a human; the icon becomes the website and app icon. Settles the forge/web logo question itd-112 deferred as 'the existing logo stays for now'. Follows itd-133, which shipped the marks deliberately unwired, and consumes itd-112's colour ladder and emission discipline rather than minting its own.builds on itd-112 · builds on itd-133
- itd-145An adopted idea cannot ship uncredited: abcd enforces its own acknowledgement convention mechanically, so a record that cites an external source, standard, or tool without a matching ACKNOWLEDGEMENTS entry fails the record gate and names what is missing. 'Credit in the same change that lands it' stops depending on the author remembering. Seeded by a real miss in this repo: the maritime signal-flag standard the livery logo encodes and the NO_COLOR convention the colour ladder implements both shipped before their credit landed, and nothing caught it.superseded by itd-163
- itd-146abcd's help renders in labelled command groups, and the grouping is gated like every other surface claimbuilt on by itd-2609212113220149 · built on by itd-2609212130136102 · built on by itd-2610090831227812 · implemented by spc-2609212139586554 · related adr-2609212115255771 · related iss-2610262031582207 · related iss-2610262031588576 · related iss-2610262033090287 · related iss-2610262033133368 · related iss-2610262037453214 · related iss-2610262039384176 · related iss-2610262043574593 · related iss-2610262044580425 · related iss-2610262044589669 · related itd-134 · related itd-2609212113220149 · related itd-2609212130136102
- itd-147The brief's surface chapters are a generated reflection of the shipped surface, so a shape claim cannot driftimplemented by spc-2609020906356450 · related adr-2609231028044006 · related adr-2610290238168123 · related iss-2610262031549181 · related iss-2610262033108186 · related iss-2610262036368072 · related iss-2610262037477814 · related iss-2610262041289117 · related iss-2610262043106501 · related iss-2610262045047151
- itd-148Every change starts in its own worktree in abcd's store: the primary checkout is a read-only surface, and abcd blocks mutations there for every session but a declared coordinatorblocked by itd-2609091014076309 · builds on itd-118 · built on by itd-2609221656373558 · implemented by spc-42 · related adr-2609091248200336 · related iss-213 · related iss-2608230847432285 · related iss-2610262044322326 · related itd-2609091014076309 · related itd-2609091416295622 · related itd-2610161621364075 · related itd-2610170634394993
- itd-149abcd handles inbound security advisories and issues, and cuts the release, for every managed repo. The 2026-08-27 security-advisory pilot proved the loop by hand across two independent operators: advisory and issue intake, recall-dedup triage against the ledger, record-first fixes in isolated worktrees, one integration branch, an independent adversarial gate over the assembled diff, auto-merge armed only after APPROVE, and a derived release cut through the semantic-receipt gates. This intent automates that loop as abcd capability for any managed repo, with findings F-A through F-W of the pilot note as the acceptance-criteria source and F-U (re-run every required pass against the final content commit; never transfer a verdict) and F-Q (the two release gates are human-by-design) load-bearing.related adr-2610120558328615 · related itd-2609221842494980
- itd-150Agent worktrees commit without the private name-guard: .abcd/.work.local/ is per-worktree, so every isolated-worktree agent commit runs with the banlist layer absent — loudly warned, per design, but the isolated-agent pattern now systematically bypasses a protection the main checkout has. Candidate remedies: the worktree-creation path seeds a pointer to the primary checkout's store, or the hook falls back to reading the primary worktree's local tierimplemented by spc-43 · related iss-370
- itd-151Five agent prompts read attacker-influenceable input without the itd-5 contract (ruthless-reviewer, security-reviewer, docs-currency-reviewer, intent-auditor, sota-researcher) and agents/ sits outside both lint roots, so no detector exists for the class; the PQ linter (agents/README.md) is the missing detectorimplemented by spc-44 · related iss-278
- itd-152Autonomous cloud runs in sibling repos leaked harness attribution footers and a live session URL into public GitHub artifacts: the harness auto-appends a 'Generated with' footer plus a session link when a PR or issue is created, overriding the repos' Assisted-by-only attribution policy (commit messages stayed clean; the leak surface was PR bodies and issue comments, plus GitHub's public edit history retaining the pre-scrub revision). Leak shape only - no session ids reproduced here. Two remedies needed: (a) every autonomous routine prompt must ban session URLs and harness footers in public text AND mandate a post-create re-read-and-strip of every PR/issue/comment the loop creates, because the append happens outside the model's own text; (b) abcd should detect the class - session-URL and harness-footer patterns belong with the shared privacy pattern set (iss-154 family / itd-74 banlist territory) so audit and docs-lint flag them in any committed or posted text.implemented by spc-2609230612443069 · implemented by spc-45 · related iss-178 · related iss-2608282124231752 · related itd-2610120738075547
- itd-153abcd's remote-config apply verb should enable GitHub native secret scanning AND secret-scanning push protection by default on every managed repo (belt-and-braces alongside the CI gitleaks full-history scan): push protection blocks a secret at push time, earlier than CI, and secret scanning covers the default branch continuously. Enabled by hand on [redacted-user]/abcd 2026-08-27 via PATCH /repos/{o}/{r} security_and_analysis (both were disabled). Notes: push protection requires secret scanning enabled first; both are free on public repos; secret_scanning_non_provider_patterns and secret_scanning_validity_checks remain optional further hardening. Homes: the read-only VERIFY side is itd-92 (the doctor now reports these toggles); the APPLY-by-default belongs to the separate adr-44-bound apply intent itd-92 defers to, adjacent to itd-106 (abcd sets up the CI a repo requires); the desired state should be mirrored in the repo-settings.json sibling (iss-2608270512210664).implemented by spc-46 · related iss-2608270636272755
- itd-154The Cut A §4 manual gate FAILED on assertions 3 and 4 (transcript: .abcd/.work.local/scratch/2026-08-16-s4-transcript.txt, machine: a no-Go Mac with a fresh harness install). After /plugin marketplace add + /plugin install, NO bootstrap line ever appeared at any of three session starts, the plugin root (…/plugins/cache/abcd-marketplace/abcd/<sha>/) contained a full source checkout but no provisioned binary, and every UserPromptSubmit and PreToolUse hook errored 'No such file or directory' for the entire evening — the exact failure family the gate checks for zero of. The command surface functioned only via rung two (the PATH binary the separate one-liner installed), so the no-Go promise is unproven; ahoy install itself reports plugin.root_missing as resolvable:false. Assertions 1, 2 and 5 passed (checksum-verified one-liner with no sudo, abcd v0.5.0; transcript captured; non-interactive install with a clean, path-scrubbed receipt — including a correct abort in a non-repo directory). Per the gate's own rule this BLOCKS Cut B. Environment notes for reproduction: the harness never visibly ran the plugin's SessionStart chain after install (bootstrap.sh emitted nothing — neither success nor refusal, despite loud-staging), and the machine's home dirs are cloud-synced (anomalous stat results, 65535 link counts, multi-minute tree walks in the clone). Detector: the §4 checklist; acceptance: a fresh-machine plugin install yields one bootstrap success line, a provisioned plugin-root binary, and /abcd answering in about a second with no Go.implemented by spc-47 · related iss-253
- itd-155implement the galloping/exponential-doubling probe (trueMatchEnd) that replaces the fixed 512-byte adjacency window in scanAllPatterns/probeAt: the window grows only while a match keeps running into its edge and stops the moment the match ends short of the edge or reaches the real end of line, so a match end is never a truncation artifact. This is the structural fix designed in the 2026-08-08 decision [dcn-2608080000000001](../../../work/decisions/dcn-2608080000000001-iss-189-iss-190-shared-root-cause.md) after bug-hunt rounds 6-8 each BLOCKed on local patches for the same root cause (a truncated window-edge view driving a discard/skip decision reaching further than the ambiguity). It dissolves iss-189 (trailing boundary satisfied by the artificial window edge, spurious over-redaction) and iss-190 (window-capped recovery truncating a token and breaking the recovery chain) outright, without reintroducing the round-6 cost regression: the window grows only for matches genuinely still growing, at the amortized cost class the top-level unbounded match already pays. iss-189 and iss-190 (both superseded by this capture) are its acceptance corpus: their repro shapes must pass without a boundary classifier or a clipped-so-skip special case.implemented by spc-48 · related iss-229
- itd-156The guard tokenizer does not perform brace expansion, so a flag wrapped in a single-element brace group with an empty alternative (git push {--force,} origin main) expands in bash to byte-identical argv --force yet the guard reads the literal token {--force,} and allows it — a Tier-1 blocker miss of the same mutate-the-flag-token shape as the round-6 redirection fix. Distinct from the $'...' quoting gap (this is expansion, not quoting, and breaks no written invariant); recorded for a scoped follow-up because a correct bounded brace-expander is larger than this round's scope.implemented by spc-49 · related iss-2608221457227161
- itd-157The by-links arrangement's non-settling has a LAYOUT half that is still open, and it is a redesign rather than a fix. The renderer half is fixed (the collision resolver no longer demands 1.5 units of padding the published positions never promised, iss-2608231243286557), but the layout itself still publishes overlapping positions, so the chart still never comes to rest on that arrangement — measured 2026-08-23: by date comes to rest, by links does not. Two causes found and NOT fixed, because fixing them changes the picture: the islands are settled by a spring layout with no collision pass at all, and the two rim rows map each record's arc-width onto a circle whose circumference is smaller than the sum of those widths, so the rows are overpacked by construction. Attempted fixes measured: relaxing the linked records alone left 600 overlaps (the rest are on the rim); adding a rim-row growth rule left 367 and pushed the outermost radius from 0.97 to 1.83, visibly changing the picture without settling it. Both reverted. A correct fix places every record — islands, pairs and rim — under one packing rule, which is a design of the arrangement, not a patch to it.implemented by spc-50 · related iss-2608231350127745
- itd-158itd-88's fidelity gap audit found a missing press-release claim: Pass B is promised to ship as a declared exemption in _provenance.json, never a silent gap, but no exemption field or marker exists anywhere in the lifeboat package or the Provenance struct — a promise with no implementing code, recorded in itd-88's Audit Notes (receipt rcp-4d07032fc6ab)implemented by spc-51 · related iss-136
- itd-159the managed .gitignore visibility table has no mode for a public repo that commits its record: on abcd-cli (public, single-repo-curated-release, .abcd/** deliberately in-tree) ahoy install applied the public policy and fenced /.abcd/ and /memory/, contradicting the repo's own boundary that the record is present in every checkout. The visibility table needs a committed-record declaration (config or marker) that suppresses the fencerelated iss-223 · related iss-2609100506269348
- itd-160Eight typed cross-references point at targets absent from the tree — adr-22 supersedes adr-14, adr-15 and adr-17; adr-25 supersedes adr-8; adr-27 supersedes adr-16; adr-28 supersedes adr-18; adr-35 supersedes adr-4 (all retired under retire-the-name); itd-3 names spec_id spc-1 which has no file — and nothing checks supersedes targets today. The 2026-08-21 site investigation counted six; the in-session grep found eight. The planned site build arms the detector via the .abcd/site-baseline.json ratchet, seeded with what the build finds, and the tombstones-or-stubs question (itd-136/itd-137) decides how they renderimplemented by spc-52 · related iss-2608220150157498
- itd-161record-lint cannot see a decision-shaped document filed outside the record storesimplemented by spc-53 · related iss-2608230752354926
- itd-162prepare-this-repo adopt phase is not self-contained in the abcd record: Phase 3-5 reference templates at a machine-local path outside both the abcd repo and the target (pre-commit-config.yaml, prepare-commit-msg, AGENTS.md, DECISIONS.md, NEXT.md). A fresh clone of abcd-cli onboarding a repo would not have them, so the adoption step silently degrades against loud-staging. Detector: an onboarding self-containment check -- every asset the adopt phase applies resolves from within the abcd record or the binary, never an external machine-local path. Acceptance: the Phase 3/4/5 template references in prepare-this-repo.md.implemented by spc-54 · related iss-87
- itd-163A cited source always resolves and an adopted inspiration is always acknowledged: the reference-closure and acknowledgements-mirror gatebuilt on by itd-164 · supersedes itd-145
- itd-164A source is licence-vetted before the record may lean on it: cite refresh records the verdict, the gate reads the committed baselinebuilds on itd-163 · related adr-2610141646525117
- itd-165A failed fidelity verdict becomes work somebody can seerelated iss-2610262034042710
- itd-166A run records what it was actually run withblocks itd-2610161733316518 · built on by itd-2611011230226453 · built on by itd-2611011325403127 · built on by itd-2611031342011261 · implemented by spc-2610170652111963 · related iss-2608290811463906 · related iss-2610161709506207 · related iss-2610262031598665 · related iss-2610262033109267 · related iss-2610262036286227 · related iss-2610262037410328 · related iss-2610262037413056 · related iss-2610262043089096 · related iss-2610262045146746
- itd-167The product thinker answers a stop in a medium they already use, and answers it whenever they get to itrelated adr-2609151528057131
- itd-168The product thinker sets how the system talks to them, and the defaults are plain language and options to choose fromrelated iss-2610262043114601
- itd-169An agent loop that stops says who it is asking and what it needs, and never simply haltsrelated iss-2610262034153896 · related iss-2610262036097307
- itd-170What the product thinker reports after using the product finds its way back to the promise that predicted it
- itd-171A decision points back to the conversation where it was reachedrelated iss-2608290819228175
- itd-172Every record has a short title and a one-line summary a non-engineer can readrelated itd-2609211913453478 · related itd-2609212113220149
- itd-173Verification escalates from the built-in check to an outside audit, and the product thinker picks the rung
- itd-174Each repository configures how far its facilitator is consulted and when it escalatesrelated itd-2609212137129937
- itd-175The product thinker writes down how this could be wrong, and what would show itrelated iss-2610262034045777
- itd-176Whatever ships says how hard anyone looked at it
- itd-177An intent's claims are typed and its scope conditions keep their identity across edits — the readiness gate refuses an intent that leaves a context claim unrecordedbuilt on by itd-2609020625405170 · built on by itd-2609020625405251 · implemented by spc-55 · related adr-2609021016270132 · related iss-2610262034437300 · related iss-2610262037423257
- itd-178Every record written through a command carries its origin and its production mode — stamped by the command, never typed by handbuilt on by itd-2609020625400169 · implemented by spc-56 · related adr-2610241022541063
- itd-179The reasoning behind what was pursued no longer evaporates at the gate — readiness and triage record grounds for the conjecture, not only the decisionimplemented by spc-57 · related adr-57 · related iss-2610262034428117 · related iss-2610262034431772 · related iss-2610262041291369 · related iss-2610262042580667 · related iss-2610262045201587
- 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-86 · built on by itd-2609020625400169 · built on by itd-2609020625400194 · built on by itd-2609020625402518 · built on by itd-2609020625402599 · built on by itd-2609020625405251 · built on by itd-2609020625407419 · implemented by spc-58 · related adr-2609300821558671 · related iss-2610262041299335 · related iss-2610262042575392
- itd-181A shipped intent's scope conditions are dispositioned by the fidelity verdict — what was assumed ex ante and what survived are recorded as different thingsbuilt on by itd-2609020625405170 · built on by itd-2609020625405251 · implemented by spc-59 · related adr-2609021016270132
- itd-182The record's discipline failures are themselves recorded — a lapse is a capture category, timestamped at the lapseimplemented by spc-60
- itd-183The cold reading sees exactly what the assembler passes — positive inclusion, field projection, and a per-run manifestbuilds on itd-86 · built on by itd-194 · built on by itd-198 · built on by itd-199 · built on by itd-2609020625402599 · built on by itd-2609020625405170 · built on by itd-2609020625407419 · built on by itd-2609021003095168 · implemented by spc-61 · related adr-2609021016272867 · related adr-2609021016275803 · related adr-2609021016286571 · related adr-56 · related adr-58
- itd-184Four cold-reading definitions, one blindness core — each position licenses a different output, and none may hold another's licencebuilds on itd-86 · built on by itd-199 · built on by itd-2609021003095168 · implemented by spc-62 · related adr-2609021016286571 · related adr-58 · related iss-2610262044082114
- itd-185One ingest verb validates every cold-reading output — including what the reading was licensed to produce, not only what it sawbuilt on by itd-2609020625400169 · built on by itd-2609020625400194 · built on by itd-2609020625402599 · built on by itd-2609020625405251 · implemented by spc-63 · related iss-2610262036243501 · related iss-2610262036257320
- itd-186The read-block eval falsifies the firewall — planted warm content that reaches a reading fails the build loudlybuilt on by itd-2609020625407419 · implemented by spc-64 · related adr-2609021016272867
- itd-187Amnesia is a repository property, proven by an eval — the same state assembled twice is byte-identical, so no case run is spent evidencing itimplemented by spc-65 · related iss-2610262045054936
- itd-188Machine assistance in maintaining the ledger, without any context that holds both ledger content and a readingbuilt on by itd-2609020625402599 · implemented by spc-66 · related adr-2609021016275803
- itd-189What the widening reading proposes is admitted or declined on the record — grounds on admission, dispositions on declines, and surprises as their own entriesbuilt on by itd-2609020625400194 · built on by itd-2609020625402518 · implemented by spc-67
- itd-190The claim recording gradient: an intent's three claim kinds carry three recording requirements, and the readiness gate holds thembuilds on itd-1 · built on by itd-2609020625405170 · related iss-2610262031362638 · related iss-2610262033578037 · related iss-2610262037151611 · related iss-2610262042332488
- itd-191The selection criteria are a declared, recorded discipline — a candidate is characterised and selected against criteria the record states, never criteria supplied at invocationbuilt on by itd-2609020625407419 · related iss-2610262037160502 · related iss-2610262043197794
- itd-192An acceptance criterion whose producer does not exist is judged by whether this phase wires it, not by whether the narrowing was disclosedrelated iss-2610262031376440 · related iss-2610262033593092 · related iss-2610262040466411 · related iss-2610262042302710 · related iss-2610262043005827 · related iss-2610262043165117
- itd-193A verifier works on a copy: no agent mutates a live worktree to test it, and the tree is proved clean before any act that reads itbuilt on by itd-196 · built on by itd-2609251624540864
- itd-194The reading include table admits only what the exclusion floor can readbuilds on itd-183 · implemented by spc-2609021003136831 · related adr-56
- itd-195A claim about how the code behaves is executable, or it is not madebuilt on by itd-197 · related iss-2610262031396689 · related iss-2610262036040955
- itd-196A capability is rehearsed end to end before it ships, over a real tree, in a throwaway snapshotbuilds on itd-193 · built on by itd-2609020625400445 · related iss-2610262031375064 · related iss-2610262033596296 · related iss-2610262040451252 · related iss-2610262042291241 · related iss-2610262043017551 · related iss-2610262043161268
- itd-197A fact a source can settle is read, not recalledbuilds on itd-195
- itd-198An assembly reports what it would cost before a reading is commissionedbuilds on itd-183 · built on by itd-199 · built on by itd-2609020625400445 · implemented by spc-68 · related iss-2610262036279746 · related iss-2610262043159613
- itd-199A reading is about something narrower than everything, and its scope is a committed, adjustable choicebuilds on itd-183 · builds on itd-184 · builds on itd-198 · built on by itd-2609020625400445 · built on by itd-2609020625407419 · built on by itd-2609021003095168 · implemented by spc-69 · related adr-2609021016272867 · related adr-2609021016286571 · related adr-58 · related iss-2610262031532200 · related iss-2610262036260273 · related iss-2610262036267743 · related iss-2610262042593698
- itd-200A managed repository shows it is managed, and whose answer the loop is waiting on, in the host's status linebuilds on itd-20 · built on by itd-201 · built on by itd-2609212130146198 · implemented by spc-70 · related adr-2610050711287503 · related iss-168 · related iss-2610262031557361 · related iss-2610262033114573 · related iss-2610262034397453 · related iss-2610262036341317 · related iss-2610262037469144 · related iss-2610262039366512 · related iss-2610262041342697 · related iss-2610262043120814 · related iss-2610262043562914 · related iss-2610262045065649 · related itd-2610031214560142 · related itd-2610031215002409
- itd-201Every question abcd's agents put to a human is asked one at a time, in plain language, with options that widenbuilds on itd-200 · built on by itd-2609212137129937 · built on by itd-2610230756259215 · implemented by spc-2610030944505997 · related iss-2610262034402021 · related iss-2610262036304277 · related iss-2610262039376194 · related iss-2610262041393479 · related iss-2610262043114601 · related iss-2610262045007603 · related itd-2609151541116052 · related itd-2609212130146198 · related itd-2610030810350727 · related itd-2610031215002409
- itd-2609020625400169An intent that a reading occasioned says so in its origin, with the run and the item that occasioned itbuilds on itd-178 · builds on itd-180 · builds on itd-185 · implemented by spc-2609020626042168 · related iss-2610262034450748 · related iss-2610262034461571
- itd-2609020625400194An admission and a surprise are written by a verb, and the order the design fixes is a refusalbuilds on itd-180 · builds on itd-185 · builds on itd-189 · implemented by spc-2609020626040342 · related iss-2610262045235833
- itd-2609020625400445A committed preset declares the window it was calibrated for, and the record holds every preset to its declarationbuilds on itd-196 · builds on itd-198 · builds on itd-199 · implemented by spc-2609020626048722
- itd-2609020625402518A reframe occasioned by a reading is recorded as a reframe, joined to what occasioned it, without carrying the construal it replacedbuilds on itd-180 · builds on itd-189 · implemented by spc-2609020626048705 · related adr-2609021016288378 · related iss-2610262041364605
- 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 ledgerbuilds on itd-180 · builds on itd-183 · builds on itd-185 · builds on itd-188 · implemented by spc-2609020626045177 · related adr-2609021016275803 · related iss-2610262045054936
- itd-2609020625405170A principle carries typed claims, its reference, its comparison and its evidence, its statement is readable cold, and it inherits only what heldbuilds on itd-177 · builds on itd-181 · builds on itd-183 · builds on itd-190 · implemented by spc-2609020626042471 · related adr-2609021016270132
- itd-2609020625405251A scope condition is dispositioned from a reading run, keyed to the condition's identity and joined to the item that occasioned itbuilds on itd-177 · builds on itd-180 · builds on itd-181 · builds on itd-185 · implemented by spc-2609020626046252 · related iss-2610262034445775
- itd-2609020625407419A comparative reading receives the widening run's items as its candidate set, and characterises them before anyone admits onebuilds on itd-180 · builds on itd-183 · builds on itd-186 · builds on itd-191 · builds on itd-199 · implemented by spc-2609020626039834 · related adr-2609021016272867 · related iss-2610262036293167 · related iss-2610262041359075
- itd-2609021003095168The invocation is a position and a target state, and the committed preset for the position supplies what the reading is handedbuilds on itd-183 · builds on itd-184 · builds on itd-199 · implemented by spc-2609021004075744 · related adr-2609021016286571
- itd-2609061543533170One verb takes a managed repository's site from the checkout to a live addressbuilds on itd-2609212103568351 · implemented by spc-2609212141407459 · related adr-2609212115255771 · related adr-2609221017021499 · related iss-2609291925387011 · related iss-2610262036415345 · related iss-2610262042028384 · related iss-2610262043356566 · related iss-2610262043369188 · related iss-2610262044330700 · related iss-2610262044347395 · related iss-2610262045493440 · related itd-100 · related itd-131 · related itd-2609212103568351 · related itd-2609221017023290
- itd-2609081951381895abcd ships an OpenAI-compatible API adapter, and a provider serves only the models it listsbuilds on itd-2609170822093401 · built on by itd-2609170822093401 · built on by itd-2609221009495079 · built on by itd-2609301918174237 · implemented by spc-2609221011153746 · related adr-2609221009491186 · related adr-2609221017021499 · related adr-2609300107513982 · related iss-2609291925393913 · related iss-2610262043257570 · related iss-2610262044237764 · related iss-2610262044285635 · related iss-2610262045372683 · related itd-2609201916056194 · related itd-2609221009495079 · related itd-2609221017023290 · related itd-6
- itd-2609090559376002Every Sub-Agent a Session Spawns Leaves the Same Redacted Record Its Main Thread Doesbuilt on by itd-2609091718566731 · built on by itd-2609091718595846 · implemented by spc-2609090624222051 · related adr-2609090636172016 · related adr-29 · related iss-2609081917287384
- itd-2609090746410233A lifeboat packs from a worktree, a branch, or an abandoned feature test, experiment or implementation, not only from a whole repository
- itd-2609090746414083A lifeboat packs from a lab session home, the throwaway experiment's intention, harvest and bundle, with the same coverage honesty as a repository
- itd-2609091014076309Session and agent worktrees live in a machine-scoped store that abcd lists and reclaims, never beside the user's own projectsblocks itd-148 · blocks itd-2610222214476887 · built on by itd-2609201916151817 · built on by itd-2610161621364075 · implemented by spc-2609301811532881 · related adr-2609091014087993 · related adr-2609091248200336 · related adr-2609091248201071 · related adr-2610031751065746 · related iss-2610130501296659 · related iss-2610230014564359 · related iss-2610231003000222 · related iss-2610231011465325 · related iss-2610231125086511 · related iss-2610231125096250 · related iss-2610262031473469 · related iss-2610262037293150 · related iss-2610262039245351 · related itd-118 · related itd-148 · related itd-2609091034175565 · related itd-2609091416295622 · related itd-2609221656373558 · related itd-2610161621364075
- itd-2609091034175565Before an agent starts on an item, it reserves it on the shared remote, and everyone who works on the project sees the reservationbuilt on by itd-2609091416295622 · built on by itd-2609150819440345 · built on by itd-2609151838312703 · built on by itd-2610031259176838 · built on by itd-2610120738075547 · built on by itd-2610170634394993 · implemented by spc-2610031753359849 · related adr-2609091248200336 · related adr-2610031352212697 · related adr-2610120937435856 · related adr-2610150729333337 · related adr-2610161940004937 · related adr-2610222026262980 · related iss-2608220750029993 · related iss-2609020716570699 · related iss-2609240646546286 · related iss-2610262032111048 · related iss-2610262037516372 · related iss-2610262037561390 · related iss-2610262039590757 · related iss-2610262040016204 · related iss-2610262043379064 · related iss-2610262043385436 · related iss-2610262044322326 · related iss-2610262045435815 · related iss-2610262045489203 · related iss-2610262045503347 · related iss-2610262045516387 · related itd-118 · related itd-2609091014076309 · related itd-2609091416295622 · related itd-2609091416304128 · related itd-2609150819440345 · related itd-2610031259176838 · related itd-2610170634394993 · supersedes itd-33
- itd-2609091416295622A session sees the records its peers hold before it mints or fixes onebuilds on itd-2609091034175565 · built on by itd-2609150819440345 · built on by itd-2609201916151817 · built on by itd-2609221656373558 · implemented by spc-2609202056480020 · related iss-2608220750029993 · related iss-2609020716570699 · related iss-2610262044300840 · related iss-2610262045516387 · related itd-148 · related itd-2609091014076309 · related itd-2609091034175565 · related itd-2609091416304128 · related itd-2609150819440345 · related itd-2609201916151817
- itd-2609091416304128capture resolve refuses a record the default branch has already closed, judged by the last fetchrelated iss-2609020716570699 · related iss-2610262037219105 · related itd-2609091034175565 · related itd-2609091416295622
- itd-2609091718566731Transcripts Already on Disk Are Recovered into the Right Repository's Corpus, Under That Repository's Own Redactionbuilds on itd-2609090559376002 · implemented by spc-2609091722230648 · related adr-29
- itd-2609091718595846Any Captured Session Can Be Handed to an Agent as One Self-Contained Artefact, With a Telemetry File Saying What It Costbuilds on itd-2609090559376002 · built on by itd-2610290858096130 · implemented by spc-2609091722269727 · related adr-29 · related iss-2610262036392981 · related iss-2610262043347672
- itd-2609111003026787A gate catches the intent whose work is live while its spec is still openimplemented by spc-2609120450289528 · related iss-2609091642508005 · related iss-2610262045552105
- itd-2609150819432059A managed repository that is not a plugin gets the same release gateimplemented by spc-2609202019026366 · related iss-2609061432214212 · related itd-2609221842494980
- itd-2609150819439571abcd has no supported operation for correcting a factual error inside a durable record, and no documented convention saying what to do instead. The record is deliberately not rewritten, which is right, but "not rewritten" and "wrong" are different states and only the first has a mechanism.related iss-2609100505146979
- itd-2609150819440345Which session holds which worktree, branch or record is coordinated entirely by conversation, so every new session repeats a handshake that nothing records. A session joining work in progress has no way to ask what is already claimed: it messages the peers it can see, waits for replies, and rebuilds a picture that the sessions before it had already built and did not write down. One measured encounter cost four messages and about fifteen minutes before any work began, and the picture it produced is not durable, so the session after that pays again. The convention that a diff you did not make is a peer's work depends on knowing who the peers are and what they hold, which is precisely the thing no artefact carries. The repository already records this gap for the narrow case of detecting a peer session before mutating git state; the wider case is claim rather than presence, and the two want the same substrate. Whatever holds it should be as cheap to write as it is to read, because a coordination record nobody updates is worse than the chat it replaced.builds on itd-2609091034175565 · builds on itd-2609091416295622 · related adr-2610031352212697 · related iss-2609100519122086 · related itd-2609091034175565 · related itd-2609091416295622 · related itd-2609151838312703 · related itd-2609221656373558 · related itd-2610120738075547 · superseded by itd-2610170634394993
- itd-2609150819445595A shipped intent's owed fidelity review is listed, so the debt is paidimplemented by spc-2609202112205096 · related iss-2609100509537730 · related iss-2610262032102172 · related iss-2610262041582285 · related iss-2610262044392775 · related iss-2610262045442294 · related iss-2610262045546558
- itd-2609151138388536Every Decision Is Its Own Record, and the Log Stops Conflictingimplemented by spc-2610110931381316 · related adr-2609151138420062 · related adr-2610110925465593 · related iss-2609100507439414 · related iss-2610262036429463 · related iss-2610262039442943 · related iss-2610262041590949 · related iss-2610262043395075 · related iss-2610262044191365
- itd-2609151516525843A Repository Can Ban A Name On Its First Commit, And A Machine Can Ban One Everywherebuilds on itd-74 · related adr-56 · related iss-2609100506269348
- itd-2609151541116052During the peer-listing planning interview on 2026-09-20, the agent listed the rewritten acceptance criteria in prose and then asked, through the interactive question view, whether the criteria were the product thinker's. The prose was not on screen while the question showed, so the product thinker was asked to confirm text they could not see (iss-2609202058058301). A confirming question has to carry what it confirms.related itd-201 · related itd-2610030810350727 · superseded by itd-2610030810350727
- itd-2609151658486398A release cut publishes the security advisories its fixes close: when the release workflow cuts a version, every draft advisory whose fixing record shipped in that cut is published with the fixed version stamped and its opt-in credits, and an advisory whose record was closed as won't-fix is closed as not a vulnerability, so no fixed advisory sits unpublished after its release and no hand step decides which ones publish
- itd-2609151838312703Sessions under any account, on any machine or in the cloud announce what they are doing through short fixed-form announcements on the shared remote, a person reads everyone's status with one command, and what is really a hold stays a reservationbuilds on itd-2609091034175565 · built on by itd-2609151838327688 · built on by itd-2610170634394993 · implemented by spc-2610150728396006 · related adr-2610031352212697 · related adr-2610150729333337 · related adr-2610222026262980 · related iss-2608220750029993 · related iss-2609091037191879 · related iss-2610142200372105 · related iss-2610150726321422 · related iss-2610150726331622 · related iss-2610262031474937 · related iss-2610262033053387 · related iss-2610262034278916 · related iss-2610262036208370 · related iss-2610262037274982 · related iss-2610262037281449 · related iss-2610262039259706 · related iss-2610262041006295 · related iss-2610262042412794 · related iss-2610262042504165 · related iss-2610262042513525 · related iss-2610262042524170 · related iss-2610262043581439 · related iss-2610262044295915 · related iss-2610262044300840 · related iss-2610262044310958 · related itd-2609150819440345 · related itd-2609151838327688 · related itd-2609221656361680 · related itd-2610100704270254 · related itd-2610170634394993
- itd-2609151838327688An opt-in adapter to a local message broker brings push delivery and cross-machine reach to the session mailbox: with the adapter enabled a session is woken the moment a message arrives, machines on the local network exchange messages without a shared mount, and every delivered message is still mirrored to the mailbox as a record; without it the mailbox works as beforebuilds on itd-2609151838312703 · related iss-2610262042524170 · related itd-2609151838312703
- itd-2609170822093401abcd proposes the model each agent deserves, and facilitates it where it canbuilds on itd-2609081951381895 · builds on itd-2609180517121254 · built on by itd-2609081951381895 · built on by itd-2609201916056194 · built on by itd-2609221009495079 · built on by itd-2609301918174237 · built on by itd-2610161733316518 · built on by itd-6 · implemented by spc-2609180535002478 · implemented by spc-2609251028149555 · implemented by spc-2610281649196051 · related adr-25 · related adr-2609221009491186 · related adr-2609300107513982 · related iss-2609170818061083 · related iss-2610262031505758 · related iss-2610262033059301 · related iss-2610262036163231 · related iss-2610262037365749 · related iss-2610262039253719 · related iss-2610262041018201 · related iss-2610262042426018 · related iss-2610262043598765 · related iss-2610262044146690 · related iss-2610262044285635 · related iss-2610262044485589 · related iss-2610262044499326 · related itd-17 · related itd-2609201916151817
- itd-2609180517121254Every payload a host hands back from a delegated step names the model that produced it and the number of agents that ran, and the ingesting verb refuses one that does notbuilt on by itd-2609170822093401 · related iss-2610262043089096
- itd-2609201916056194A role runs through the command-line harness the operator chose, and every fall back to the host is recordedbuilds on itd-2609170822093401 · builds on itd-2609201916151817 · built on by itd-2609201916151817 · built on by itd-2610161733316518 · built on by itd-2610240922461281 · built on by itd-2610240933025076 · built on by itd-2611031342011261 · built on by itd-6 · implemented by spc-2609221533057881 · related adr-2609221009491186 · related adr-2610222222326104 · related iss-2610262037492393 · related iss-2610262044255432 · related iss-2610262045365573 · related itd-22 · related itd-2609081951381895 · related itd-2610030810370060 · related itd-2610100627454580 · related itd-51 · related itd-6 · supersedes itd-2
- itd-2609201916151817One verb takes a READY intent to delivered, and refuses while a decision is openbuilds on itd-2609091014076309 · builds on itd-2609091416295622 · builds on itd-2609201916056194 · built on by itd-2609201916056194 · built on by itd-2609201925079472 · built on by itd-2609211116005482 · built on by itd-2609212103565953 · built on by itd-2609212103568351 · built on by itd-2610161733316518 · built on by itd-2610240922461281 · built on by itd-33 · built on by itd-59 · built on by itd-6 · built on by itd-82 · built on by itd-97 · implemented by spc-2609202134338445 · related adr-2609291342092738 · related adr-2610222222326104 · related adr-2610310235000654 · related iss-2610262031503691 · related iss-2610262031524343 · related iss-2610262034312865 · related iss-2610262037294601 · related iss-2610262037301480 · related iss-2610262037311796 · related iss-2610262039262634 · related iss-2610262040545166 · related iss-2610262040551548 · related iss-2610262040570378 · related iss-2610262043535279 · related iss-2610262044004875 · related iss-2610262044057318 · related iss-2610262044060780 · related itd-2 · related itd-2609091416295622 · related itd-2609170822093401 · related itd-2610170634394993 · related itd-29 · related itd-50 · supersedes itd-29 · supersedes itd-58
- itd-2609201925079472An autonomous run paces itself by default, and one flag sets the pacebuilds on itd-2609201916151817 · built on by itd-2609211116005482 · built on by itd-2609221656373558 · built on by itd-2610100704270254 · built on by itd-2610240922461281 · built on by itd-2610262127138979 · built on by itd-2611040344170206 · built on by itd-2611041549461012 · built on by itd-2611041549471712 · built on by itd-6 · built on by itd-82 · implemented by spc-2609202134341288 · implemented by spc-2609301921521360 · related iss-2610262032080136 · related iss-2610262037482641 · related iss-2610262041445723 · related iss-2610262043285832 · related iss-2610262045422454 · related iss-2610262045503347 · related itd-2610170634394993 · related itd-29
- itd-2609211116005482`abcd build next` picks the readiest planned intent itself, and writes down whybuilds on itd-2609201916151817 · builds on itd-2609201925079472 · builds on itd-50 · built on by itd-2609212103565953 · built on by itd-2609212103568351 · implemented by spc-2609212015048113 · related iss-2610262032106392 · related iss-2610262037582823 · related iss-2610262043273885 · related iss-2610262044160347 · related iss-2610262044240923 · related itd-78 · related itd-82
- itd-2609211913453478One page maps the record families, and phase, milestone and roadmap are retiredbuilds on itd-2609212103565953 · builds on itd-34 · built on by itd-2609212103568351 · built on by itd-2609212103572513 · implemented by spc-2609212131112235 · implemented by spc-2609230613206890 · related adr-2609212115255771 · related adr-2609292012006845 · related iss-2610262032061118 · related iss-2610262032072943 · related iss-2610262032073819 · related iss-2610262033167999 · related iss-2610262034508480 · related iss-2610262038029972 · related iss-2610262039581980 · related iss-2610262041427822 · related iss-2610262041438494 · related iss-2610262042040605 · related iss-2610262042051056 · related iss-2610262043161268 · related iss-2610262043165117 · related iss-2610262043179497 · related iss-2610262043188086 · related iss-2610262044146391 · related iss-2610262044159830 · related iss-2610262044295915 · related iss-2610262045286894 · related iss-2610262045465811 · related iss-2610262045557535 · related itd-172 · related itd-24 · related itd-2609212103565953 · related itd-2609212137129937 · related itd-42 · related itd-78
- itd-2609212103565953A spec lists its steps, and the build lands them one at a timebuilds on itd-2609201916151817 · builds on itd-2609211116005482 · built on by itd-2609211913453478 · implemented by spc-2609212138246060 · related adr-2609212115255771 · related adr-2609292012006845 · related iss-2610262032001815 · related iss-2610262037500468 · related iss-2610262037509765 · related iss-2610262041398357 · related iss-2610262041402639 · related iss-2610262041419578 · related iss-2610262045422454 · related iss-2610262045557535 · related itd-2609211913453478
- itd-2609212103568351The status board shows Now, Next and Later, computed from the recordbuilds on itd-2609201916151817 · builds on itd-2609211116005482 · builds on itd-2609211913453478 · built on by itd-2609061543533170 · built on by itd-2609212103572513 · implemented by spc-2609212138241908 · related adr-2609212115255771 · related adr-2609292012006845 · related adr-2609301720596683 · related iss-2610262032008964 · related iss-2610262032071046 · related iss-2610262035028747 · related iss-2610262039567036 · related iss-2610262042063245 · related iss-2610262044382852 · related iss-2610262045493440 · related itd-100 · related itd-2609061543533170
- itd-2609212103572513An intent names the release it must land by, and the cut says whether it didbuilds on itd-2609211913453478 · builds on itd-2609212103568351 · implemented by spc-2609212138243443 · related adr-2609212115255771 · related adr-2609292012006845 · related adr-2609301720596683 · related iss-2610262035030115 · related itd-2609231013154443 · related itd-73
- itd-2609212113220149Every verb's help opens with one sentence an agent can act onbuilds on itd-146 · implemented by spc-2609212139583822 · related adr-2609212115255771 · related iss-2610262039556194 · related itd-146 · related itd-172 · related itd-2610090831227812
- itd-2609212130136102abcd's verbs consolidate: modes become flags and five checks become one lintbuilds on itd-146 · implemented by spc-2609212139587510 · related adr-2609212115255771 · related iss-2610262033144314 · related iss-2610262036404974 · related iss-2610262039536939 · related iss-2610262043297244 · related iss-2610262044170732 · related iss-2610262044201056 · related iss-2610262045024914 · related iss-2610262045033573 · related iss-2610262045411383 · related iss-2610262045459641 · related iss-2610262045478245 · related itd-122 · related itd-123 · related itd-124 · related itd-125 · related itd-146 · related itd-2610090831227812
- itd-2609212130146198The status-line badge is true at every stopbuilds on itd-200 · built on by itd-2609212137129937 · implemented by spc-2609212139593041 · related adr-2609212115255771 · related iss-2610262034582374 · related iss-2610262036376499 · related iss-2610262045007603 · related itd-201 · related itd-2609212137129937
- itd-2609212137116617A new capture or draft is matched against the record before it is writtenbuilds on itd-42 · builds on itd-84 · implemented by spc-2609212141417782 · related adr-2609212115255771 · related adr-2609300821558671 · related iss-2610262044221992 · related itd-2609221009495079 · related itd-48 · related itd-87
- itd-2609212137128014abcd lab mechanises the lab conventions three hand-run experiments provedbuilds on itd-22 · built on by itd-2609221009495079 · built on by itd-2609251624540864 · built on by itd-2610040822131032 · built on by itd-2610161733316518 · implemented by spc-2609212141418943 · related adr-2609212115255771 · related iss-2610262032094044 · related iss-2610262045316034 · related itd-59 · related itd-75
- itd-2609212137129937abcd's text names the product thinker or the technical facilitator, never the maintainerbuilds on itd-201 · builds on itd-2609212130146198 · implemented by spc-2609212141412864 · related adr-2609212115255771 · related iss-2610262039584858 · related iss-2610262043197794 · related iss-2610262043202769 · related iss-2610262043210108 · related iss-2610262044373028 · related iss-2610262045454143 · related itd-174 · related itd-2609211913453478 · related itd-2609212130146198 · related itd-97
- itd-2609221009495079abcd's typed judgements can run through a decision adapter, measured in a lab before it decides anythingbuilds on itd-2609081951381895 · builds on itd-2609170822093401 · builds on itd-2609212137128014 · implemented by spc-2609221011151661 · related adr-2609221009491186 · related adr-2609300107513982 · related iss-2609291925398978 · related iss-2610262031524510 · related iss-2610262033055327 · related iss-2610262034326107 · related iss-2610262037348735 · related iss-2610262043598494 · related iss-2610262043598765 · related iss-2610262044512344 · related itd-17 · related itd-2609081951381895 · related itd-2609212137116617 · related itd-82 · supersedes itd-17
- itd-2609221017023290abcd keeps every external credential the same waybuilds on itd-63 · implemented by spc-2609221017544877 · related adr-2609221017021499 · related itd-2609061543533170 · related itd-2609081951381895 · related itd-2610161621364075 · related itd-6
- itd-2609221656361680A managed repository reports back to abcd, and abcd says so at its next startbuilds on itd-4 · implemented by spc-2609221657168936 · related adr-2609221009491186 · related iss-2610262032092604 · related iss-2610262034572130 · related iss-2610262037571084 · related iss-2610262044310958 · related iss-2610262045292501 · related itd-116 · related itd-2609151838312703 · related itd-33
- itd-2609221656373558Two sessions share one run, and the run measures which way of dividing the work is bestbuilds on itd-148 · builds on itd-2609091416295622 · builds on itd-2609201925079472 · built on by itd-2610170634394993 · implemented by spc-2609221657588816 · related adr-2609221009491186 · related adr-2610031352212697 · related itd-2609091014076309 · related itd-2609150819440345 · related itd-2610170634394993 · related itd-33
- itd-2609221842494980A dependency bump lands without a person re-authoring it, and no machine enters the contributor graphbuilds on itd-92 · built on by itd-2609301020001595 · implemented by spc-2609221843355061 · related adr-2609292116133348 · related iss-2609221820487644 · related itd-149 · related itd-2609150819432059
- itd-2609231013154443Every release arrives with a press release composed from what shippedbuilds on itd-67 · builds on itd-73 · built on by itd-2609231507251267 · implemented by spc-2609231435545473 · related adr-2609212115255771 · related iss-2610262033156337 · related iss-2610262035015704 · related iss-2610262039541373 · related iss-2610262045391451 · related iss-2610262045409665 · related itd-24 · related itd-2609212103572513
- itd-2609231434459890abcd's own tests warn before running on an overloaded machinebuilt on by itd-2610262127138979 · implemented by spc-2609231542463113 · implemented by spc-2609232027132755 · related iss-2609210828122412 · related iss-2610262032099691 · related iss-2610262037542283 · related iss-2610262037548530 · related iss-2610262037558450 · related iss-2610262045302788 · related iss-2610262045435815
- itd-2609231507251267Release pages on the project websitebuilds on itd-2609231013154443
- itd-2609251624540864A lab runs one procedure from intention to discardbuilds on itd-193 · builds on itd-2609212137128014 · related iss-2610262031383285 · related iss-2610262032597891 · related iss-2610262037133461 · related iss-2610262043395075
- itd-2609291923559186The consistency pass runs where records are written and names each finding the same way every timebuilds on itd-34 · builds on itd-48 · implemented by spc-2610021456200324 · related adr-2609300821558671 · related iss-2609260926323349 · related iss-2610262039276483 · related iss-2610262041032173 · related iss-2610262042503210 · related iss-2610262044079779 · related iss-2610262044513201 · related itd-62
- itd-2609291924469783Every lint warning rule shares one baseline file that only shrinks, so a new warning fails the change that introduces itrelated iss-46
- itd-2609292106557115A fresh machine installs abcd through one small starter that hands over to a trusted abcd binarybuilds on itd-130 · related iss-377
- itd-2609292107351737A development session's token cost is measured, and set against the size class its spec predictedrelated iss-2608220150157508 · related iss-2608301744251874 · related iss-2608301856299268 · related iss-2610262032595554 · related iss-2610262036076395 · related iss-2610262037171531 · related iss-2610262043179497 · related iss-2610262043347672
- itd-2609292108089653Ingesting and consulting sources are abcd verbs, and no corpus entry is a keyword stubbuilds on itd-76 · related iss-2610262031355278 · related iss-2610262034111313 · related iss-2610262039000162 · related iss-2610262040412521 · related iss-2610262042462569 · related iss-2610262042473980 · related iss-2610262043030522 · related iss-2610262043323769 · related iss-27 · related iss-55
- itd-2609292108373494The grill hands the interview to an installed interviewing skill, and runs its own when there is nonerelated adr-22 · related iss-165 · related iss-2610262034051312 · related iss-2610262040422553 · related itd-2610030810350727
- itd-2609292109005937An opt-in local model checks every prompt for secrets and personal data before it leaves the machinerelated adr-22 · related iss-2608261543489261
- itd-2609292109214516Rule injection is a seam: the native loader stays the default, and an opt-in CARL back end can take it overbuilds on itd-3 · related adr-22 · related iss-2610262043334834 · related iss-64
- itd-2609292109475690Every verb family has a behavioural scenario that drives the built binary end to endrelated iss-2610262039010827 · related iss-48
- itd-2609301020001595A pinned-action bump syncs its scaffold template and lands re-authoredbuilds on itd-2609221842494980 · related adr-2609292116133348 · related iss-209 · related iss-2610262031409019 · related iss-2610262037198530
- itd-2609301918174237A remote provider takes a file-reading agent only as a fixed, blanked, capped bundlebuilds on itd-2609081951381895 · builds on itd-2609170822093401 · related adr-2609221009491186 · related adr-2609300107513982 · related iss-2610262031418522 · related iss-2610262043120814 · related iss-2610262043494574 · related iss-2610262043501753
- itd-2610021503208208Personal git hooks keep running in abcd-managed repositories
- itd-2610030720038073abcd keeps its home folder out of desktop indexing by defaultimplemented by spc-2610031309233367 · related adr-2610030720195401 · related adr-2610031751065746 · related adr-2610031751066232 · related iss-2610241551259104 · related iss-2610262040028651 · related iss-2610262044265126 · related iss-2610262045065649 · related iss-2610262045072539 · related iss-2610262045266820 · related iss-2610262045292501 · related iss-2610262045296807 · related iss-2610262045302788 · related iss-2610262045316034
- itd-2610030810350727Every question abcd asks reads the same way, on a narrow window and a wide onebuilt on by itd-2610030810370060 · built on by itd-2610230756259215 · implemented by spc-2610030944505997 · related adr-49 · related iss-2610241604049754 · related iss-2610262033165546 · related iss-2610262036380647 · related iss-2610262039482748 · related iss-2610262042009257 · related itd-201 · related itd-2609151541116052 · related itd-2609292108373494 · related itd-2610031215002409 · supersedes itd-110 · supersedes itd-2609151541116052
- itd-2610030810370060abcd's interviews run in a plain Terminal, with the same question layoutbuilds on itd-112 · builds on itd-2610030810350727 · built on by itd-2610030821294016 · built on by itd-2610031215002409 · built on by itd-2610230756259215 · built on by itd-2610240823055889 · built on by itd-2610240933025076 · implemented by spc-2610030911534855 · implemented by spc-2610040847280931 · related adr-49 · related iss-2610262040575327 · related iss-2610262044407176 · related itd-2609201916056194 · related itd-2610030821294016
- itd-2610030814013772abcd's projects keep one conventions file, AGENTS.md, and Claude Code reads it directlybuilt on by itd-2610031026190632 · implemented by spc-2610031156364295 · related adr-2610030814023326 · related iss-2609291925136841 · related iss-2610262036446593 · related iss-2610262045254107 · related itd-2610031348087517
- itd-2610030821294016Connecting a model service from inside your coding session looks up the details and offers the choicesbuilds on itd-2610030810370060 · implemented by spc-2610031241482088 · related iss-2610262044407176 · related itd-2610030810370060
- itd-2610031026190632abcd's update check says when a harness is older than abcd needsbuilds on itd-111 · builds on itd-2610030814013772 · built on by itd-2610031325050110 · implemented by spc-2610031342374947 · related iss-2610262033066869
- itd-2610031214560142The board shows a product thinker what waits on them and what comes next, in a few plain linesbuilt on by itd-2610031215002409 · built on by itd-2610032150577708 · built on by itd-2610240913343804 · implemented by spc-2610031844142274 · related adr-49 · related iss-2609201954342967 · related iss-2610031207397996 · related iss-2610262042568717 · related iss-2610262044382852 · related itd-200
- itd-2610031215002409A 'what next?' menu under the board offers the next step, in a Terminal and in a Claude Code sessionbuilds on itd-2610030810370060 · builds on itd-2610031214560142 · implemented by spc-2610031844158884 · related adr-49 · related iss-2609201954342967 · related iss-2610262031474789 · related iss-2610262034261541 · related iss-2610262036232872 · related iss-2610262044392775 · related iss-2610262044474439 · related itd-200 · related itd-201 · related itd-2610030810350727
- itd-2610031259176838Outside contributors reserve work through a draft pull request that abcd honoursbuilds on itd-2609091034175565 · related adr-2610031352212697 · related iss-2610262043379064 · related itd-2609091034175565
- itd-2610031325050110abcd notices a harness update downloaded but not yet runningbuilds on itd-2610031026190632
- itd-2610031348087517Setup asks whether abcd keeps parts of the README current, and whichbuilt on by itd-2610031651058674 · implemented by spc-2610031704338417 · related adr-2611011153058085 · related iss-2609110944498549 · related iss-2610262045017395 · related itd-2610030814013772
- itd-2610031651058674abcd's check reports README parts that have gone stale, and writes nothingbuilds on itd-2610031348087517 · built on by itd-2611011151512956
- itd-2610032150577708The product thinker's dashboard, in a browser through Tailscalebuilds on itd-2610031214560142 · built on by itd-2610032150580455 · built on by itd-2610040740108331 · built on by itd-2610040740122709 · built on by itd-2610040740135705 · built on by itd-2610040754440360 · built on by itd-2610111655362931 · built on by itd-2611041549483696 · implemented by spc-2610040741034208 · related adr-2610032150581128 · related iss-2610262036193171 · related iss-2610262041020990 · related iss-2610262042437551 · related iss-2610262043520946 · related iss-2610262043581439 · related iss-2610262044129717 · related iss-2610262044330700 · supersedes itd-139 · supersedes itd-2610032150580455
- itd-2610032150580455The dashboard from anywhere, through Tailscalebuilds on itd-2610032150577708 · related adr-2610032150581128 · superseded by itd-2610032150577708
- itd-2610040740108331The dashboard on the home network, without Tailscalebuilds on itd-2610032150577708 · related adr-2610032150581128
- itd-2610040740122709Acting from the dashboard: rewriting the brief and approving intentsbuilds on itd-2610032150577708 · related adr-2610032150581128 · related adr-2610091016270711 · related iss-2610100649485756 · related itd-2610091016262335
- itd-2610040740135705The dashboard for more people: the facilitator's view and the team's, configurablebuilds on itd-2610032150577708 · related adr-2610032150581128 · related adr-2610091016270711 · related itd-2610091016262335
- itd-2610040754440360The private dashboard for every abcd-managed projectbuilds on itd-2610032150577708
- itd-2610040754453237The public record site for every abcd-managed projectbuilt on by itd-2610052000411162 · built on by itd-2610052000424067 · related iss-2610262036000485 · related iss-2610262040538618 · related iss-2610262042428344 · related iss-2610262043356566
- itd-2610040817105016Every brief section shows what realises it, and a brief change names what it touchesrelated iss-2610262042541203 · related iss-2610262043106501
- itd-2610040822131032A lab runs end to end from a question the product thinker asksbuilds on itd-2609212137128014 · related iss-2610040758486433
- itd-2610050548126044abcd reminds a session to refresh its handover note only when that session changed the tree
- itd-2610052000411162Anyone can open, edit on their own device and submit the brief of a public abcd-managed project on abcdesign.appbuilds on itd-2610040754453237 · built on by itd-2610052000424067 · related adr-2610091010387033 · related adr-2610091016270711 · related itd-2610091010348892 · related itd-2610091016262335 · superseded by itd-2610091016262335
- itd-2610052000424067A group works on one public project's brief together on abcdesign.app, adds notes, and exports the combined workbuilds on itd-2610040754453237 · builds on itd-2610052000411162 · superseded by itd-2610091016262335
- itd-2610070544145422Someone on Windows installs abcd and it just works: the
- itd-2610070549060530A word in a new idea marks it to revisit, and the board puts it firstrelated iss-2610262039055212 · related iss-2610262042412794 · related iss-2610262042568717
- itd-2610070550516046On the dashboard, a product thinker sees the brief and their ideas together, and puts the ideas in orderrelated iss-2610262037208650 · related iss-2610262040426321 · related iss-2610262042536971 · related iss-2610262043273885
- itd-2610071545369520A person confirms the assistant's verdict on each warned banned-name line instead of judging it alone
- itd-2610071545380041Work about abcd itself goes to abcd as a report, never into a managed repository's own plans
- itd-2610090831227812A person who types `/abcd:` sees the commands people usebuilds on itd-146 · implemented by spc-2610100613109045 · related adr-40 · related iss-2610262036453716 · related iss-2610262036460690 · related iss-2610262037594127 · related iss-2610262042029426 · related iss-2610262043265040 · related iss-2610262043310309 · related iss-2610262043322187 · related iss-2610262043323769 · related iss-2610262044186274 · related iss-2610262044229426 · related iss-2610262044419558 · related iss-2610262044429007 · related iss-2610262044589669 · related iss-2610262044591588 · related iss-2610262045409665 · related iss-2610262045411383 · related iss-2610262045524988 · related iss-2610262045546558 · related itd-2609212113220149 · related itd-2609212130136102 · related itd-2610091918433290
- itd-2610091010348892An opted-in project's record is built at each release onto its own GitHub Pagesblocks itd-2610142145236613 · builds on itd-135 · built on by itd-2610142145236613 · implemented by spc-2610141709461788 · related adr-2610091010387033 · related adr-2610142147242544 · related adr-47 · related iss-2610262036193721 · related iss-2610262041024277 · related iss-2610262042428344 · related iss-2610262042445075 · related iss-2610262043520946 · related iss-2610262044136729 · related iss-2610262044347395 · related itd-2610052000411162 · related itd-2610091016262335 · related itd-2610142145236613
- itd-2610091016262335A team edits its brief together live during a call, on abcdesign.app or on the host's own computerblocks itd-2610161904178040 · built on by itd-2610161733316518 · implemented by spc-2610141709430146 · implemented by spc-2610230609005313 · related adr-2610032150581128 · related adr-2610091016270711 · related adr-2610141949110653 · related adr-2610161400542916 · related iss-2610230519103295 · related iss-2610230519116460 · related iss-2610230519122686 · related iss-2610262042536971 · related iss-2610262044119054 · related itd-2610040740122709 · related itd-2610040740135705 · related itd-2610052000411162 · related itd-2610091010348892 · supersedes itd-2610052000411162 · supersedes itd-2610052000424067
- itd-2610091918433290Agents keep memory notes with /abcd:memory, recalled when they matterbuilds on itd-3 · built on by itd-2610111655362931 · implemented by spc-2610111627213138 · related adr-2610091918443997 · related iss-2610262034298178 · related iss-2610262036131057 · related iss-2610262039286595 · related iss-2610262040588956 · related iss-2610262040599781 · related iss-2610262042452621 · related iss-2610262042462569 · related iss-2610262043574593 · related iss-2610262044344649 · related iss-2610262044356372 · related iss-2610262044370559 · related iss-2610262044373028 · related itd-2610090831227812 · related itd-2610111655362931 · related itd-36 · related itd-39
- itd-2610100627454580An agent's text comes back from abcd's rewriter written for its reader and within its limitsrelated iss-2610262036101688 · related iss-2610262042556788 · related itd-2609201916056194
- itd-2610100704270254An abcd run sets how many sub-agents it keeps alive by the models they run onbuilds on itd-2609201925079472 · related iss-2610262042504165 · related iss-2610262043285832 · related itd-2609151838312703 · related itd-2610170634394993 · related itd-2610222215485265
- itd-2610110940216682Every change is checked in full once, on exactly what landsrelated iss-2610262042381184 · related iss-2610262042399506
- itd-2610111655362931On the dashboard, the product thinker and facilitator review memory notes and promote the ones worth keepingbuilds on itd-2610032150577708 · builds on itd-2610091918433290 · related adr-2610091918443997 · related iss-2610262034130871 · related iss-2610262043210108 · related itd-2610091918433290
- itd-2610111707085098Each session takes a persona name, shown in the status line and the session list, unique across the machinebuilt on by itd-2610281253044600 · built on by itd-2611031342011261 · implemented by spc-2610152057143798 · related iss-2610111701536641 · related iss-2610241613191748 · related iss-2610262034598939 · related iss-2610262042019151
- itd-2610112239022766Private security reports stay private until their fix shipsimplemented by spc-2610120557432880 · related adr-2610120558328615
- itd-2610120738075547Work handed to a cloud session comes back, or says why notbuilds on itd-2609091034175565 · implemented by spc-2610120941441282 · related adr-2610120937435856 · related iss-2610120724251698 · related iss-2610120729071657 · related iss-2610120729076366 · related iss-2610120729083126 · related iss-2610120729087253 · related iss-2610120729094755 · related iss-2610262037376558 · related iss-2610262042556788 · related itd-107 · related itd-152 · related itd-22 · related itd-2609150819440345
- itd-2610140858048004abcd's home keeps itself out of a dotfiles repositoryimplemented by spc-2610140858477542 · related adr-2610140859394097 · related iss-2610262044370559
- itd-2610141646126492A librarian turns sources into a quoted reading packbuilt on by itd-2610141646452213 · built on by itd-2610142116477426 · related adr-2610141646525117
- itd-2610141646452213Ideate starts from a source through the librarianbuilds on itd-2610141646126492 · builds on itd-2610141646454347 · builds on itd-2610141646456128 · related adr-2610141646525117 · related adr-2610142116480836 · related adr-2610300908239458 · related iss-2610141647294219
- itd-2610141646454347An ideate verdict proves its own legsbuilt on by itd-2610141646452213 · built on by itd-2610141646456128 · implemented by spc-2610142138047122 · related adr-2610142116480836 · related adr-2610300908239458 · related iss-2610141647304982 · related iss-2610141647307807 · related iss-2610141647308358 · related iss-2610141647313018 · related iss-2610141647315880
- itd-2610141646456128A private ideate verdict stays privatebuilds on itd-2610141646454347 · built on by itd-2610141646452213 · related adr-2610141646525117 · related adr-2610142116480836 · related adr-2610300908239458 · related iss-2610090740139804 · related iss-2610090742488191 · related iss-2610090748299348 · related iss-2610141647309012
- itd-2610141646463379A reviewer's extra check must name what it protects
- itd-2610141646467500Ingested pages stay private until a person promotes themrelated adr-2610141646523373
- itd-2610141646469491A cheap watcher wakes an agent only when something needs action
- itd-2610141956319695A deferred finding is its own captured recordrelated iss-2610262034072525 · related iss-2610262034081102 · related iss-2610262036024309 · related iss-2610262042284906 · related iss-2610262043101146
- itd-2610142116477426A research question becomes a shared, citable notebuilds on itd-2610141646126492 · related adr-2610141646525117 · related iss-2610100649495706
- itd-2610142145236613abcd's own record is built onto its GitHub Pages like any project'sblocked by itd-2610091010348892 · builds on itd-2610091010348892 · implemented by spc-2610142146250176 · related adr-2610142147242544 · related adr-47 · related adr-48 · related itd-2610091010348892
- itd-2610150602547271The facilitator's mode gates the mergebuilds on itd-97 · built on by itd-2610290858115394 · built on by itd-2610301750162657 · built on by itd-2610301850454860 · built on by itd-2611011325428560 · implemented by spc-2610161609350616 · related adr-2610150603484802 · related adr-2610240850193281 · related iss-2610262034286775 · related iss-2610262036211949 · related iss-2610262039290078 · related iss-2610262043535279 · related iss-2610262043542024 · related iss-2610262044094024
- itd-2610161016391855A stuck drain lane hands itself backbuilt on by itd-2610161016401115 · implemented by spc-2610161044461448 · related iss-2610161015368630 · related iss-2610161015381750 · related iss-2610161015410527 · related iss-2610262037525523
- itd-2610161016394967Drains on several accounts share the workbuilt on by itd-2610161016401115 · implemented by spc-2610161044461448 · related iss-2610152125101468 · related iss-2610160957404827 · related iss-2610161015370582 · related iss-2610161015371794 · related iss-2610161015387318 · related iss-2610161015393523 · related iss-2610161015397586 · related iss-2610161015400509 · related iss-2610161015422836 · related iss-2610262032088777 · related iss-2610262037591851 · related iss-2610262045489203
- itd-2610161016401115Drains run unattended and visiblybuilds on itd-2610161016391855 · builds on itd-2610161016394967 · implemented by spc-2610161044461448 · related adr-2610222222326104 · related iss-2610161015417715 · related iss-2610161015422306 · related iss-2610161015433495 · related iss-2610161015434746 · related iss-2610161015448977 · related iss-2610161015457468 · related iss-2610262044274697
- itd-2610161616086564After a plugin update, abcd offers to bring the repository's setup up to datebuilds on itd-105 · builds on itd-111 · implemented by spc-2610170635097509
- itd-2610161617096084After a plugin update, abcd says what changed for this repositorybuilds on itd-105 · builds on itd-111 · implemented by spc-2610170635097509
- itd-2610161621364075The agents abcd launches on its own work inside a sandbox the operating system enforcesbuilds on itd-2609091014076309 · implemented by spc-2610161751056096 · related adr-2609091248200336 · related adr-2610161621415708 · related adr-2610240850193281 · related adr-42 · related itd-148 · related itd-2609091014076309 · related itd-2609221017023290 · related itd-2610222215485265
- itd-2610161647248332abcd finds out what the forge can do before choosing a routebuilt on by itd-2610261025516272 · related iss-2610161632245527
- itd-2610161710315026Unattended runs reach only a declared list of hosts
- itd-2610161710316538Drains and builds a person's session drives report how isolated they were
- itd-2610161733316518One task done across a model matrix, re-runnablyblocked by itd-166 · builds on itd-2609170822093401 · builds on itd-2609201916056194 · builds on itd-2609201916151817 · builds on itd-2609212137128014 · builds on itd-2610091016262335 · implemented by spc-2610161949559050 · related adr-2610161733400551 · related adr-2611011231015519 · related iss-2610140652230444 · related iss-2610161709506207 · related iss-2610161734413178 · related iss-2610161734428291 · related iss-2610161801358637 · related iss-2610161928115039 · related iss-2610161938458308 · related iss-2610262031545672 · related iss-2610262043101146 · related iss-2610262044146690
- itd-2610161904178040People who think in Emacs can edit the brief with Emacs keysblocked by itd-2610091016262335
- itd-2610170634394993Headless agents in parallel coordinate through the shared remote, not conversationbuilds on itd-2609091034175565 · builds on itd-2609151838312703 · builds on itd-2609221656373558 · built on by itd-2610222029228127 · built on by itd-2610241331131356 · implemented by spc-2610230758581403 · related adr-2610222026262980 · related adr-2610222026265719 · related iss-2609100519122086 · related iss-2610140638074587 · related iss-2610161634043273 · related iss-2610161639025702 · related iss-2610162306239284 · related iss-2610262037257443 · related iss-2610262039043469 · related iss-2610262039059270 · related iss-2610262042513525 · related itd-115 · related itd-148 · related itd-2609091034175565 · related itd-2609151838312703 · related itd-2609201916151817 · related itd-2609201925079472 · related itd-2609221656373558 · related itd-2610100704270254 · related itd-2610170638184486 · related itd-2610222029228127 · related itd-2610222215485265 · related itd-78 · related itd-82 · supersedes itd-2609150819440345
- itd-2610170638184486Every session keeps a checklist on disk, so no run stalls and no stall spreadsbuilt on by itd-2610180912189125 · built on by itd-2610222029228127 · built on by itd-2610240850336695 · implemented by spc-2610230805429429 · related adr-2610222026265719 · related adr-2610240850193281 · related iss-2610170619247185 · related iss-2610222026223032 · related iss-2610262036224651 · related iss-2610262041043651 · related iss-2610262044279216 · related itd-2610170634394993 · related itd-2610180912189125 · related itd-2610222029228127
- itd-2610171228577260A product thinker settles a visual design in rounds that abcd runs end to endrelated iss-2610170713227840 · related iss-2610180913376757
- itd-2610180912189125A session left to work on never stops while it has workbuilds on itd-2610170638184486 · built on by itd-2610240850336695 · built on by itd-2611041549461012 · built on by itd-2611041549471712 · implemented by spc-2610180914469489 · related adr-2610181003541997 · related adr-2610222026265719 · related adr-2610240850193281 · related iss-2610170619247185 · related iss-2610262039417690 · related iss-2610262043268358 · related iss-2610262044279216 · related itd-2610170638184486
- itd-2610222029228127Every session's checklist reaches a shared copy and the phonebuilds on itd-2610170634394993 · builds on itd-2610170638184486 · related iss-2610262044129717 · related iss-2610262044136729 · related itd-2610170634394993 · related itd-2610170638184486
- itd-2610222214476887One command shows everything a repository has left lying around, and clears what is provably finishedblocked by itd-2609091014076309 · implemented by spc-2610230730269295 · related iss-2610222001116066 · supersedes itd-118
- itd-2610222215485265abcd drain --drive works through the ledger from a plain terminalimplemented by spc-2610230813348813 · implemented by spc-2611051628562376 · related adr-2610222222326104 · related iss-2610222000271964 · related iss-2610262037323830 · related iss-2610262040552734 · related iss-2610262044274697 · related iss-2610262044503777 · related itd-2610100704270254 · related itd-2610161621364075 · related itd-2610170634394993
- itd-2610230756259215Every question abcd asks passes its check before the person sees itbuilds on itd-201 · builds on itd-2610030810350727 · builds on itd-2610030810370060 · built on by itd-2610301914350541 · implemented by spc-2610301917245442 · related iss-2610230745597968 · related iss-2610301855200679
- itd-2610230856403803A build run's dependent lane cannot start until its predecessor has merged into the default branch: readiness reads a predecessor as landed only when its lane is done, its pull request an ancestor of the default branch, so a step that needs another waits a whole preflight and merge-queue cycle (about one to two and a half hours each on 2026-10-22) before it opens. Stacked changes are standard practice for dependent work (Graphite, Sapling and ghstack stacks, and merge queues taking a stack in order), and on 2026-10-22/23 that shape was rolled by hand twice: merge-gate steps 2 and 3, and model-matrix step 2 stacked on the route branch. Building it is more than a fix: the dependent lane's pull request is based on the predecessor's branch, the stack merges in order, and a lane rebases (and re-stamps what it resolved) when the predecessor changes.related iss-2610230856272073
- itd-2610240823055889Setting abcd up is short, plain, and finishesbuilds on itd-2610030810370060 · built on by itd-2610240918547728 · built on by itd-2610240918594138 · built on by itd-2610240919030303 · implemented by spc-2610241007434505 · implemented by spc-2610242112593216 · related adr-2610241022330872 · related adr-2610241101463288
- itd-2610240850336695The person grants their sessions what they may do alone, until a timebuilds on itd-2610170638184486 · builds on itd-2610180912189125 · built on by itd-2610241015120503 · built on by itd-2611031342000215 · built on by itd-2611041549483696 · related adr-2610240850193281 · related itd-2610301750162657
- itd-2610240913343804No surprises: abcd says up front what it will do on its own and what it will askbuilds on itd-2610031214560142
- itd-2610240918547728Every contributor commits as themselvesbuilds on itd-2610240823055889 · implemented by spc-2610241007568207 · related adr-2610241022541063
- itd-2610240918594138abcd installs the tools it needs for the person alone, checkedbuilds on itd-2610240823055889 · implemented by spc-2610241008092356 · related adr-2610241057124151
- itd-2610240919030303Setup offers to put abcd's folder on the PATHbuilds on itd-2610240823055889 · implemented by spc-2610241008191355 · related adr-2610241022330872
- itd-2610240922461281The review set is a setting, in model classesbuilds on itd-2609201916056194 · builds on itd-2609201916151817 · builds on itd-2609201925079472 · implemented by spc-2610240951109420
- itd-2610240933025076abcd plans unattended and asks only what a person ownsbuilds on itd-2609201916056194 · builds on itd-2610030810370060
- itd-2610241015120503The person and the repository agree when abcd may merge, and what a cloud session may dobuilds on itd-2610240850336695 · related adr-2610240850193281
- itd-2610241331131356The session view reads live agent state from a workspace managerbuilds on itd-2610170634394993
- itd-2610261025516272Private repos land checked work without renting CIbuilds on itd-2610161647248332 · related adr-2611011327164895 · related iss-172 · related iss-2609012313465609 · related iss-2610110939559446 · supersedes itd-115
- itd-2610262127138979A preflight waits for its turn as one whole runblocks itd-2610262140595217 · builds on itd-2609201925079472 · builds on itd-2609231434459890 · built on by itd-2610262140595217 · implemented by spc-2610262202438999
- itd-2610262140595217abcd records how each preflight on a machine behavedblocked by itd-2610262127138979 · blocks itd-2610262141001890 · builds on itd-2610262127138979 · built on by itd-2610262141001890 · built on by itd-2611011325403127
- itd-2610262141001890abcd adjusts how many preflights run at once from what it recordedblocked by itd-2610262140595217 · builds on itd-2610262140595217
- itd-2610271130017437A finding with a safe fix is fixed where it is found
- itd-2610281253044600The status line says what each session is working onbuilds on itd-2610111707085098
- itd-2610290239150589The brief reads as the design and why, and each command's behaviour is written once, in the page agents followrelated adr-2610290238168123
- itd-2610290746077716abcd audits and applies a repository's GitHub settingsimplemented by spc-2610290749113317
- itd-2610290858096130A person hands their unfinished and private work on a repository to another account, computer or colleague, and it arrives whole and privatebuilds on itd-2609091718595846 · related iss-2610290730196083
- itd-2610290858115394A repository's maintainers hold its quality gate: a contributor's change waits for a maintainer's approval, and only a maintainer starts a release, adopts an intent or makes private work publicbuilds on itd-2610150602547271 · related iss-2610290730539347
- itd-2610300955026531Agents can work under a forge account of their own
- itd-2610300955031405A merge approval can require a security key touch
- itd-2610300955049260Approve a merge from the dashboard or a web app
- itd-2610301327282266abcd's help fits the screen it is read on
- itd-2610301346085246An agent learns how to call abcd from the abcd it runsbuilt on by itd-2610301428378830 · implemented by spc-2610301431075964 · related adr-2610301638558260
- itd-2610301428378830abcd tells an agent what to do next, after a refusal and after a successbuilds on itd-2610301346085246 · implemented by spc-2610301431108175 · related adr-2610301638558260
- itd-2610301428390406An agent can practise a filled-in form before it countsimplemented by spc-2610301431131636
- itd-2610301750162657abcd's unattended work is spot-checked against specs and intentsblocked by itd-2610301850454860 · builds on itd-2610150602547271 · builds on itd-82 · built on by itd-2611031342000215 · implemented by spc-2610301925429250 · related itd-2610240850336695
- itd-2610301850454860abcd records how each change landedblocks itd-2610301750162657 · builds on itd-2610150602547271 · builds on itd-82 · implemented by spc-2610301950480609
- itd-2610301914350541A repository sets the layout limits of abcd's questionsbuilds on itd-2610230756259215 · implemented by spc-2610301950037469
- itd-2611011151475128Every documentation surface is rendered from its one homebuilds on itd-102 · built on by itd-2611011151512956 · built on by itd-2611011239589823 · related adr-19 · related adr-2610031751065746 · related adr-2610142147242544 · related adr-2611011153058085 · related adr-53
- itd-2611011151512956Hand-written text in a rendered page is caught and offered back to its sourcebuilds on itd-2610031651058674 · builds on itd-2611011151475128 · builds on itd-61 · built on by itd-2611011239589823 · related adr-2611011153058085
- itd-2611011230226453Agents abcd starts on your API key stay within the budget you setbuilds on itd-166 · built on by itd-2611031342011261 · built on by itd-2611040344170206 · related adr-2611011231015519 · related iss-2610100913096346
- itd-2611011239589823A project's how-to guides and learning material stay current with the productbuilds on itd-2611011151475128 · builds on itd-2611011151512956 · related adr-2611011153058085
- itd-2611011325403127Every landing shows what it cost and the next run's estimatebuilds on itd-166 · builds on itd-2610262140595217 · built on by itd-2611011325421304 · built on by itd-2611011325449761
- itd-2611011325421304A one-package change is checked in minutes, not the whole suitebuilds on itd-2611011325403127 · implemented by spc-2611012047503720 · related iss-2611011343052330
- itd-2611011325428560A solo private repo can self-attest its gates, labelled sobuilds on itd-2610150602547271 · related adr-2611011327164895
- itd-2611011325430933A machine the person owns checks agents' work independently
- itd-2611011325449761New repos offer a choice of check profiles with their costsbuilds on itd-2611011325403127
- itd-2611011333366788abcd resolves every layered setting through the sharedrelated adr-2611011332427073
- itd-2611011813155166A repository switches an abcd verb or project gate off
- itd-2611011813162141A repository names a sequence of abcd steps a person runsrelated adr-2611011813190527
- itd-2611011813175068The product thinker approves a goal's scope once
- itd-2611012048006057abcd's load gate waits for memory as it waits for loadimplemented by spc-2611020732419632 · related iss-2611011737317454
- itd-2611012123486967Raising a spending cap needs the person's touch
- itd-2611012123505400Hosted CI reuses test results that cannot have changed
- itd-2611012200551577Every reading of git state goes through internal/gitutil
- itd-2611031342000215The status line shows each role what it needs, in a table a repository can tunebuilds on itd-2610240850336695 · builds on itd-2610301750162657 · builds on itd-2611031342011261
- itd-2611031342011261abcd keeps a per-session ledger of every agent it launchesbuilds on itd-166 · builds on itd-2609201916056194 · builds on itd-2610111707085098 · builds on itd-2611011230226453 · built on by itd-2611031342000215 · built on by itd-2611041549461012 · built on by itd-2611041549471712 · built on by itd-2611041549483696 · implemented by spc-2611041701500441 · implemented by spc-2611050023402644 · related iss-2610100913096346 · related iss-2611020719494343 · related iss-2611031146255825 · related iss-2611031337115764
- itd-2611040344170206Unattended work runs on a named profile, one per way of payingbuilds on itd-2609201925079472 · builds on itd-2611011230226453 · related iss-2610100602595553 · related iss-2610100913095172 · related iss-2610230716454430 · related iss-2611032326573729 · related iss-2611032327111678
- itd-2611041549461012A session that takes over a run steps on from what abcd wrote downbuilds on itd-2609201925079472 · builds on itd-2610180912189125 · builds on itd-2611031342011261 · implemented by spc-2611041706004822 · implemented by spc-2611050505250705 · related adr-2611050740453233 · related iss-2610110915210571 · related iss-2610121528179959 · related iss-2610241107435264 · related iss-2610241414414823 · related iss-2611022247128872 · related iss-2611032348373007 · related iss-2611040337228910
- itd-2611041549471712A person stops the unattended runs of each account that chose a folder, with one commandbuilds on itd-2609201925079472 · builds on itd-2610180912189125 · builds on itd-2611031342011261 · implemented by spc-2611041705580524 · implemented by spc-2611050505220309 · related adr-2611050740453233
- itd-2611041549483696An unattended run writes one private daily digest pagebuilds on itd-2610032150577708 · builds on itd-2610240850336695 · builds on itd-2611031342011261 · related iss-2610130501353955
- spc-2intent-lifecycle-automationimplements itd-80
- spc-3lifeboat-coverage-experimentimplements itd-88
- spc-4start-the-transcript-clockimplements itd-89
- spc-5folder-classificationimplements itd-40
- spc-6issue-captureimplements itd-4
- spc-7abcd-intent-quoted-text-create-symmetricimplements itd-46
- spc-8epic-to-spec-terminologyimplements itd-43
- spc-9an-intent-that-is-not-planned-cannot-be-implemented-abcd-gaiimplements itd-94
- spc-10derived-versioningimplements itd-73
- spc-11installable-versioned-pluginimplements itd-67
- spc-12disembark-grounds-a-lifeboat-s-open-questions-on-a-repo-s-toimplements itd-95
- spc-13disembark-reads-a-repo-s-naming-and-internals-conventions-inimplements itd-96
- spc-14abcd-scaffolds-a-hardened-changelog-driven-release-gate-intoimplements itd-93
- spc-15alice-reads-one-page-and-knows-exactly-where-abcd-stands-inimplements itd-100
- spc-16abcd-teaches-repo-agents-the-shell-commands-they-must-neverimplements itd-103
- spc-17every-citation-abcd-publishes-is-provably-alive-and-honestlyimplements itd-101
- spc-18abcd-gates-a-new-idea-before-it-becomes-a-record-entry-reseaimplements itd-104
- spc-19your-repo-says-the-same-thing-about-itself-everywhere-becausimplements itd-102
- spc-20name-banlistimplements itd-74
- spc-21a-fresh-plugin-install-just-works-the-hook-binary-survivesimplements itd-105
- spc-22a-stale-abcd-never-answers-silently-every-surface-that-runsimplements itd-111
- spc-23development-instructions-live-in-the-right-tier-abcd-managesimplements itd-117
- spc-24an-issue-graduates-into-an-intent-without-retyping-abcd-captimplements itd-119
- spc-25a-resolved-issue-points-at-what-fixed-it-abcd-capture-resolvimplements itd-120
- spc-26type-the-id-get-your-next-move-abcd-id-dispatches-on-a-recorimplements itd-121
- spc-27the-registry-cannot-wave-its-hands-every-surface-file-carrieimplements itd-122
- spc-28the-intent-audit-says-audit-abcd-intent-review-becomes-abcdimplements itd-123
- spc-29the-conformance-check-calls-itself-lint-abcd-audit-becomes-aimplements itd-124
- spc-30the-lifeboat-verdict-says-what-it-is-disembark-oracle-becomeimplements itd-125
- spc-31source-provenance-ledgerimplements itd-76
- spc-32`abcd update` — fetch, verify, swap, in one verbimplements itd-130
- spc-33abcd-mints-collision-proof-record-ids-across-parallel-agentsimplements itd-114
- spc-34The managed-repo identity gate — detect the wrong author/committer, establish only on confirmimplements itd-131
- spc-35hook-binary-to-persistent-data-dirimplements itd-132
- spc-36One pixel-grid identity: the livery package, its generator, and the drift-gated SVG assetsimplements itd-133
- spc-37iris-opens-abcdev-app-and-understands-who-abcd-is-for-what-timplements itd-135
- spc-38alice-opens-the-record-explorer-and-reads-the-whole-developmimplements itd-136
- spc-39maya-sees-how-every-decision-connects-one-relationship-chartimplements itd-137
- spc-40bob-installs-abcd-with-one-checksum-verified-command-servedimplements itd-138
- spc-41The bare-invocation banner: baked identity, half-block livery art, and the exported colour ladderimplements itd-112
- spc-42every-change-starts-in-its-own-worktree-the-primary-checkoutimplements itd-148
- spc-43agent-worktrees-commit-without-the-private-name-guard-abcd-wimplements itd-150
- spc-44five-agent-prompts-read-attacker-influenceable-input-withoutimplements itd-151
- spc-45autonomous-cloud-runs-in-sibling-repos-leaked-harness-attribimplements itd-152
- spc-46abcd-s-remote-config-apply-verb-should-enable-github-nativeimplements itd-153
- spc-47s4-gate-failed-bootstrap-provisioned-no-binaryimplements itd-154
- spc-48scanner-adjacency-galloping-probe-structural-fiximplements itd-155
- spc-49the-guard-tokenizer-does-not-perform-brace-expansion-so-a-flimplements itd-156
- spc-50by-links-layout-publishes-overlapping-positionsimplements itd-157
- spc-51provenance-lacks-pass-b-exemption-markerimplements itd-158
- spc-52dangling-supersedes-and-spec-targets-nothing-checks-themimplements itd-160
- spc-53record-lint-cannot-see-a-decision-shaped-document-filed-outsimplements itd-161
- spc-54adoption-templates-outside-recordimplements itd-162
- spc-55Claim typing and scope-condition identityimplements itd-177
- spc-56Origin and production-mode keys, stamped by the commandimplements itd-178
- spc-57Grounds at conjecture granularityimplements itd-179
- spc-58Reading records and disposition records: two acts, two writesimplements itd-180
- spc-59Scope-condition disposition at verdict ingestimplements itd-181
- spc-60The lapse log: a capture category, timestamped at the lapseimplements itd-182
- spc-61The cold-reading input assembler: positive inclusion at field granularity, a pathless bundle, and a hashed per-run manifestimplements itd-183
- spc-62Four cold-reading definitions: one verbatim blindness core, four objects, four licences no definition may borrowimplements itd-184
- spc-63The cold-reading output contract: a strict per-position schema, a supply-regime gate, and a staged ingest that leaves evidence or nothingimplements itd-185
- spc-64The read-block eval falsifies the firewallimplements itd-186
- spc-65Amnesia is a repository property, proven by an evalimplements itd-187
- spc-66The scribe: ledger-only context, authors nothingimplements itd-188
- spc-67Step-2 admission records: schemas now, command enforcement next cycleimplements itd-189
- spc-68The size report: a per-kind cost on every assembly, a test kind split from source, and a version that cannot misreport its tableimplements itd-198
- spc-69The scope operand: a reading is commissioned about something, in a closed grammar, from a committed presetimplements itd-199
- spc-70abcd-s-presence-should-be-visible-in-the-host-harness-s-statimplements itd-200
- spc-2609020626039834The comparative channel: one widening run's candidates, two fields each, characterised before anyone admits oneimplements itd-2609020625407419
- spc-2609020626040342The admission and surprise verbs: one act, two records, and the ruled order held as a refusalimplements itd-2609020625400194
- spc-2609020626042168The reading-occasioned origin: promote stamps the run and the item it graduated, and the stamp primitive refuses the kind without themimplements itd-2609020625400169
- spc-2609020626042471The knowledge record becomes a read object: A principle carries typed claims, projects its statement, and inherits only what heldimplements itd-2609020625405170
- spc-2609020626045177The scribe verb: an allow-list assembler, an authoring-refusing ingest, and a per-run context stamp the transcript store can checkimplements itd-2609020625402599
- spc-2609020626046252A second writer into the disposition surface: `abcd intent condition` dispositions one scope condition from a reading item or a delivered intentimplements itd-2609020625405251
- spc-2609020626048705The reframe record: `capture reframe` writes one `rfm-N` keyed on the committed fingerprints of the three frame surfaces before and after, joined to the reading item, disposition or surprise that occasioned itimplements itd-2609020625402518
- spc-2609020626048722One committed entry per position, in three parts: the object set, the kinds within it and the window it measures at, held by an eval that re-measures every entry on every committed changeimplements itd-2609020625400445
- spc-2609020903498198The brief describes every surface that ships, or the intent does not reach shippedimplements itd-60
- spc-2609020906356450The brief's surface chapters carry a generated appendix that cannot driftimplements itd-147
- spc-2609021003136831The include table declares what the floor parses, the floor refuses the markdown it cannot resolve, and the manifest marks every item it did not examineimplements itd-194
- spc-2609021004075744The invocation is a position and a target state: the scope operand and the override stamp leave, and the committed preset for the position is applied by the assemblerimplements itd-2609021003095168
- spc-2609090624222051A session's sub-agents are captured through the completion event, with lineage the record carries in fieldsimplements itd-2609090559376002
- spc-2609091722230648The recovery half: transcripts on disk are ingested into a named destination, and composite records are repaired in placeimplements itd-2609091718566731
- spc-2609091722269727One session, one artefact, one telemetry file: what `history reconstruct` renders and what it refuses to assertimplements itd-2609091718595846
- spc-2609120450289528A gate catches the intent whose work is live while its spec is still openimplements itd-2609111003026787
- spc-2609180535002478abcd proposes the model each agent deserves, and facilitates it where it canimplements itd-2609170822093401
- spc-2609201955277614launch-payload-render-parityimplements itd-66
- spc-2609201955279019launch-preflight-gate-suiteimplements itd-65
- spc-2609202019026366abcd-launch-cannot-set-up-the-release-flow-for-a-managed-repimplements itd-2609150819432059
- spc-2609202056480020a-session-sees-the-records-its-sibling-worktrees-hold-beforeimplements itd-2609091416295622
- spc-2609202112205096a-debt-nothing-lists-owed-fidelity-reviewsimplements itd-2609150819445595
- spc-2609202134338445one-verb-takes-a-single-intent-from-ready-to-delivered-withoimplements itd-2609201916151817
- spc-2609202134341288an-autonomous-implementation-run-paces-itself-by-default-andimplements itd-2609201925079472
- spc-2609211751376504reflect-commandimplements itd-24
- spc-2609211854150455rp-reviews-into-flowimplements itd-28
- spc-2609211859391533three-intent-kindsimplements itd-34
- spc-2609211905174684memory-unificationimplements itd-36
- spc-2609211918551301coherence-aware-grillimplements itd-42
- spc-2609211921272106intent-fidelity-reviewer-roles-2-3implements itd-48
- spc-2609211924346308loop-toward-acceptanceimplements itd-50
- spc-2609211930059886review-queue-auto-drain-fidelity-gateimplements itd-53
- spc-2609211950427074rp-mcp-only-integrationimplements itd-6
- spc-2609211955339422setup-wizard-explains-installsimplements itd-63
- spc-2609211957080006plugin-metadata-lockstep-updateimplements itd-69
- spc-2609212015048113abcd-build-next-picks-the-readiest-planned-intent-itself-wriimplements itd-2609211116005482
- spc-2609212015054359drain-ledger-triageimplements itd-82
- spc-2609212131112235one-page-in-the-glossary-maps-abcd-s-record-families-and-howimplements itd-2609211913453478
- spc-2609212138241908the-bare-abcd-status-board-and-the-site-s-status-page-showimplements itd-2609212103568351
- spc-2609212138243443an-intent-names-the-release-it-must-land-by-and-the-cut-saysimplements itd-2609212103572513
- spc-2609212138246060a-spec-lists-its-steps-and-the-build-lands-them-one-at-aimplements itd-2609212103565953
- spc-2609212139583822every-verb-s-help-opens-with-one-sentence-an-agent-can-actimplements itd-2609212113220149
- spc-2609212139586554abcd-s-help-renders-in-labelled-command-groups-and-the-groupimplements itd-146
- spc-2609212139587510abcd-s-verbs-consolidate-ahoy-s-three-modes-become-flagsimplements itd-2609212130136102
- spc-2609212139593041the-status-line-badge-is-true-at-every-stop-an-abcd-managedimplements itd-2609212130146198
- spc-2609212141407459abcd-sets-up-a-managed-repository-s-release-rendered-site-enimplements itd-2609061543533170
- spc-2609212141412864abcd-s-own-text-names-the-product-thinker-or-the-technicalimplements itd-2609212137129937
- spc-2609212141417782a-new-capture-or-draft-is-matched-against-the-record-beforeimplements itd-2609212137116617
- spc-2609212141418943abcd-lab-mechanises-the-lab-conventions-three-hand-runimplements itd-2609212137128014
- spc-2609221011151661abcd-s-typed-judgements-can-run-through-a-decision-adapterimplements itd-2609221009495079
- spc-2609221011153746abcd-ships-an-openai-compatible-api-oracle-adapter-the-firstimplements itd-2609081951381895
- spc-2609221017544877abcd-keeps-every-external-credential-the-same-way-oneimplements itd-2609221017023290
- spc-2609221533057881abcd-runs-a-delegated-agent-through-a-command-line-model-runimplements itd-2609201916056194
- spc-2609221657168936a-repository-abcd-manages-reports-back-to-abcd-itself-oneimplements itd-2609221656361680
- spc-2609221657588816two-orchestrator-sessions-in-one-user-account-share-animplements itd-2609221656373558
- spc-2609221843355061a-dependency-bump-lands-without-a-person-re-authoring-it-aimplements itd-2609221842494980
- spc-2609230612443069Routine prompts carry the outbound policyimplements itd-152
- spc-2609230613193436Scaffolded release gate: CI-name wiring, the receipts check and the protocolimplements itd-93
- spc-2609230613204830Every surface file carries its sub-verb tableimplements itd-122
- spc-2609230613206687The banner fits 66 columnsimplements itd-112
- spc-2609230613206890Glossary pointers, the family lint and the mental modelimplements itd-2609211913453478
- spc-2609230613208843Staleness behaviour is calibrated per platformimplements itd-111
- spc-2609231435545473The release cut writes RELEASE.md from the press releases of the intents it shippedimplements itd-2609231013154443
- spc-2609231542463113The load check: preflight and the eval harness warn about strays and extreme load, and never refuseimplements itd-2609231434459890
- spc-2609232027132755stray-rule-silent-bandimplements itd-2609231434459890
- spc-2609251028149555A failed fix round escalates one tier, and a provider route stays on its allowlistimplements itd-2609170822093401
- spc-2609301811532881The worktree store: `abcd ahoy worktree add|list|prune`, one lane primitive, and a notes archive beside itimplements itd-2609091014076309
- spc-2609301921521360the-budget-check-and-the-rate-limit-checkpointimplements itd-2609201925079472
- spc-2610021456200324The consistency pass at commit time: a stable finding key, cross-document lint codes, chunked review, and a pre-commit gateimplements itd-2609291923559186
- spc-2610030911534855a-person-can-run-abcd-s-interviews-in-a-plain-terminalimplements itd-2610030810370060
- spc-2610030944505997asking-and-layoutimplements itd-201 · implements itd-2610030810350727
- spc-2610031156364295evaluate-whether-claude-md-can-be-removed-safely-now-thatimplements itd-2610030814013772
- spc-2610031241482088connecting-a-model-service-from-inside-claude-code-works-outimplements itd-2610030821294016
- spc-2610031309233367abcd-keeps-its-home-folder-out-of-desktop-search-by-defaultimplements itd-2610030720038073
- spc-2610031342374947when-a-person-runs-abcd-s-check-on-purpose-abcd-also-saysimplements itd-2610031026190632
- spc-2610031704338417when-abcd-sets-up-a-project-it-asks-the-owner-whether-abcdimplements itd-2610031348087517
- spc-2610031753359849Reservations on the shared remote: `abcd reserve`, one liveness judgement, and the build, drain and land integrationimplements itd-2609091034175565
- spc-2610031844142274when-you-type-abcd-in-a-terminal-or-ask-for-the-board-in-aimplements itd-2610031214560142
- spc-2610031844158884under-the-board-a-short-what-next-menu-offers-the-few-stepsimplements itd-2610031215002409
- spc-2610040741034208a-product-thinker-opens-abcd-s-dashboard-in-a-web-browser-onimplements itd-2610032150577708
- spc-2610040847280931plain-terminal-interviews-remaining-workimplements itd-2610030810370060
- spc-2610100613109045a-person-who-types-abcd-sees-only-the-commands-people-useimplements itd-2610090831227812
- spc-2610110931381316append-only-logs-conflict-on-every-mergeimplements itd-2609151138388536
- spc-2610111627213138memory-recallimplements itd-2610091918433290 · implements itd-39
- spc-2610120557432880when-someone-reports-a-security-hole-inimplements itd-2610112239022766
- spc-2610120941441282a-person-hands-an-item-from-theirimplements itd-2610120738075547
- spc-2610140858477542abcd-s-home-keeps-itself-out-of-aimplements itd-2610140858048004
- spc-2610141709430146the-product-thinker-and-the-technicalimplements itd-2610091016262335
- spc-2610141709461788anyone-who-opens-abcdev-app-finds-theimplements itd-2610091010348892
- spc-2610142138047122an-ideate-verdict-proves-its-own-legsimplements itd-2610141646454347
- spc-2610142146250176abcd-s-own-development-record-is-builtimplements itd-2610142145236613
- spc-2610150728396006sessions-announce-what-they-are-doingimplements itd-2609151838312703
- spc-2610152057143798the-status-line-should-show-whichimplements itd-2610111707085098
- spc-2610161044461448drain-many-accountsimplements itd-2610161016391855 · implements itd-2610161016394967 · implements itd-2610161016401115
- spc-2610161609350616The facilitator's mode gates the mergeimplements itd-2610150602547271
- spc-2610161751056096a-person-who-leaves-abcd-to-run-on-itsimplements itd-2610161621364075
- spc-2610161949559050a-product-thinker-who-wants-to-knowimplements itd-2610161733316518
- spc-2610170635097509after-updateimplements itd-2610161616086564 · implements itd-2610161617096084
- spc-2610170652111963each-run-should-record-the-modelimplements itd-166
- spc-2610180914469489A session left to work on never stops while it has workimplements itd-2610180912189125
- spc-2610230609005313Live-session setup on the cloud in the two steps the intent promisesimplements itd-2610091016262335
- spc-2610230730269295`abcd sweep`: one dry run over every leftover, and `--apply` for what is provably spentimplements itd-2610222214476887
- spc-2610230758581403several-headless-agents-work-oneimplements itd-2610170634394993
- spc-2610230805429429every-abcd-session-keeps-a-checklist-onimplements itd-2610170638184486
- spc-2610230813348813abcd-drain-run-from-a-plain-terminalimplements itd-2610222215485265
- spc-2610240951109420a-person-sets-how-many-models-reviewimplements itd-2610240922461281
- spc-2610241007434505a-person-sets-abcd-up-in-a-repository-inimplements itd-2610240823055889
- spc-2610241007568207every-person-who-commits-to-a-repositoryimplements itd-2610240918547728
- spc-2610241008092356when-abcd-needs-another-tool-such-as-aimplements itd-2610240918594138
- spc-2610241008191355when-the-folder-abcd-installs-into-isimplements itd-2610240919030303
- spc-2610242112593216setup-question-budgetimplements itd-2610240823055889
- spc-2610262202438999A preflight waits for its turn as one whole runimplements itd-2610262127138979
- spc-2610281649196051consult-only-advisor-roleimplements itd-2609170822093401
- spc-2610290749113317abcd audits and applies a repository's GitHub settingsimplements itd-2610290746077716
- spc-2610301431075964An agent learns how to call abcd from the abcd it runsimplements itd-2610301346085246
- spc-2610301431108175abcd tells an agent what to do next, after a refusal and after a successimplements itd-2610301428378830
- spc-2610301431131636An agent can practise a filled-in form before it countsimplements itd-2610301428390406
- spc-2610301917245442Every question abcd asks passes its check before the person sees itimplements itd-2610230756259215
- spc-2610301925429250abcd's unattended work is spot-checked against specs and intentsimplements itd-2610301750162657
- spc-2610301950037469A repository sets the layout limits of abcd's questionsimplements itd-2610301914350541
- spc-2610301950480609abcd records how each change landedimplements itd-2610301850454860
- spc-2611012047503720A one-package change is checked in minutes, not the whole suiteimplements itd-2611011325421304
- spc-2611020732419632abcd's load gate waits for memory as it waits for loadimplements itd-2611012048006057
- spc-2611041701500441abcd keeps a per-session ledger of every agent it launchesimplements itd-2611031342011261
- spc-2611041705580524A person stops the unattended runs of each account that chose a folder, with one commandimplements itd-2611041549471712
- spc-2611041706004822A session that takes over a run steps on from what abcd wrote downimplements itd-2611041549461012
- spc-2611050023402644The launch ledger reaches the status line and a run's own summaryimplements itd-2611031342011261
- spc-2611050505220309the-stop-reaches-the-terminal-driveimplements itd-2611041549471712
- spc-2611050505250705the-restart-reads-the-forge-and-theimplements itd-2611041549461012
- spc-2611051628562376drain-drive-live-proof-and-key-routeimplements itd-2610222215485265
- iss-1launch phase ownership contradicts across the record: phase-1-ahoy.md and build-sequence.md make install plus launch the first milestone, but 04-surfaces/04-launch.md says full launch builds in Phase 5. ADR-bound.blocks iss-4 · blocks iss-5
- iss-2release-version source of truth conflicts: roadmap README tracks releases by plugin.json; ADR-31 derives versions from shipped intents; 04-launch.md still describes --version and phase-completion tiering. ADR-bound.
- iss-3phase membership and lifecycle directories disagree: planned intents (itd-20, itd-24, itd-29, itd-46) appear in no phase Scope, while draft itd-43 is scoped into Phase 0/1 yet listed later-phase. ADR-bound.blocks iss-7 · blocks iss-8
- iss-4phase count mismatch: 04-scope.md, 03-out-of-scope.md and 06-delivery README say six phases (Phase 0-5), but roadmap phases README has Phase 0-6 with Phase 6 as lifeboat round-trip.blocked by iss-1
- iss-5disembark and embark status banners point to the wrong phase: 02-disembark.md says Phase 4, 03-embark.md says Phase 5, but phase-6-lifeboat.md owns both.blocked by iss-1
- iss-6command inventory mismatch: 04-scope.md lists seven user-facing commands; 04-surfaces README lists nine (adds /abcd and /abcd:reflect).
- iss-704-scope.md hand-maintains intent counts (thirteen phased intents) that the phase docs and planned corpus have outgrown.blocked by iss-3
- iss-803-out-of-scope.md omits current drafts itd-74 and itd-75 while including scoped itd-43; regenerate from the actual draft corpus.blocked by iss-3
- iss-9glossary output path is inconsistent: Phase 3 writes to foundation/terminology while the record uses brief/glossary and ADR-30 names that the glossary home.
- iss-10Phase 0 user-command wording contradicts: phase-0-substrate.md says Phase 0 carries /abcd:intent review; phases README says Phase 0 has no user-facing command.
- iss-11agent count drift: 01-agents.md declares 16 agents; press-release, 04-scope and 05-prompt-quality still say 15.
- iss-12memory shipped versus planned is ambiguous: docs say spc-38/spc-39 shipped, but itd-36 lives in planned and intents README says shipped is empty until Go capabilities ship.
- iss-13current-state brief files carry stale status narration (spc-X shipped, today only stubs ship) inside canonical design contracts, against ADR-5.
- iss-14stale deep links: 04-surfaces README and 01-agents.md point to the intent reviewer as 05-intent.md section 6, but that section now appears later.
- iss-15capture wrote a schema-required created field into the record-lint root, so running capture broke record-lint. This drove moving the ledger to work/issues and dropping created/updated. Fixed by refactor/capture-ledger-schema-tier.
- iss-16itd-66 carries a NON-CANONICAL / do-not-implement banner while being itd-65's declared blocker; reconcile the intent body with the native spec that owns the render contract
- iss-17itd-50 sits in planned/ but carries an implementation-complete AC reconciliation table; verify actual state and move through the shipped/ audit-notes path if true
- iss-18phase-order violation: Phase 0 scopes itd-37 whose declared blocker itd-36 is Phase 2; split the hard-on-half edge (capture half vs memory-routing half) or reschedule
- iss-19phase-3 doc asserts itd-27 depends on itd-42 while itd-42's own prose asserts the reverse (it extends the grill itd-27 built); adjudicate direction — first live catch for the itd-78 phase-consistency lint
- iss-20the launch cluster (itd-65/66/67 critical, itd-72 major) is scheduled in no phase Scope section — the silent-stall pattern itd-78's lint should catch; schedule or record why not
- iss-21itd-8 and itd-16 cite the launch intent as itd-launch by name, not number — a dangling-reference class the itd-78 graph lint should flag; re-point to the concrete itd
- iss-22itd-6 sits in planned/ while its own banner records supersession-in-framing by ADR-25 (one optional adapter among many); lifecycle look needed
- iss-23itd-36 is partially superseded by adr-28 (launch-gate framing rewritten); reconcile body with the ADR before its spec plans
- iss-24changelog fragments for abcd-managed repos: per-change entries land as files in a fragments directory (towncrier pattern) and are assembled into CHANGELOG.md at release, so concurrent PRs never conflict on the Unreleased block; candidate abcd verb/discipline — assembly could hook the release gate
- iss-25related_sources frontmatter for record-store documents (intents, ADRs, research notes): machine-readable acknowledgment of the sources that informed a document — public sources by CSL key, confidential sources by a random opaque per-source id assigned at ingest (NEVER a content hash: hashing an obtainable document is verifiable by outsiders and breaks confidentiality). Needs schema sanction in record-lint, an id-resolution path via the local corpus, and add-source generating ref_id. Complements the ledger's used_in field (the corpus-side half, already shipped).
- iss-26sources corpus retrieval seam: the MVP is the current native store (per-source folders, text.md extraction, grep-based consult — shipped) and retrieval/processing becomes a pluggable seam with opt-in deeper backends, mirroring the spec seam pattern (native minimal default, adapter for depth): a RAG backend (RAG-Anything, already downloaded locally, has its own content processor that could replace pandoc/pdftotext extraction and serve semantic retrieval) and/or a CMS backend. Adapter contract, not a rewrite: consult and ingest skills keep one surface; the backend is configuration.
- iss-27corpus tooling graduates into the Go core: the sources-corpus contract (per-source folders with location-as-classification, CSL-JSON metadata, append-only provenance ledger, banlist projection) is proven by the user-tier script MVP; absorb it as a native abcd sources/ingest verb family, converging with the itd-36 provenance substrate (internal/core/provenance: licence detection, citation generation, source-hash registry) rather than porting standalone. The scripts remain the reference implementation until the native verbs are wired; /abcd:consult and /abcd:ingest keep one surface across the swap.related itd-2609292108089653
- iss-28scaffold a hermetic git environment for tests that shell out to git: any test invoking git as a subprocess can read the developer's real ~/.gitconfig (identity, aliases, includeIf, hooks path) — non-determinism and identity leakage into fixtures — or, via one un-scoped call (missing -C/cwd) or corrupted repo state, mutate the ambient repo's config, refs, or history. Per-call temp-repo scoping is defence-in-breadth only; the robust fix also isolates the git environment. Ship a shared hermetic-git helper in the generated test scaffolding, per target language (Go gitIsolatedEnv(), pytest fixture, shell shim), that pins HOME and XDG_CONFIG_HOME to a per-test temp dir, sets GIT_CONFIG_GLOBAL/GIT_CONFIG_SYSTEM to /dev/null (or GIT_CONFIG_NOSYSTEM=1), supplies identity via GIT_AUTHOR_*/GIT_COMMITTER_* env rather than git config, sets GIT_TERMINAL_PROMPT=0 and core.hooksPath=/dev/null, and is always combined with scoping to the temp repo — documented in the scaffolded repo's testing conventions/AGENTS.md so it is the path of least resistance. Optional enforcement: a lint/pre-commit check flagging git subprocesses in test code that bypass the helper, turning convention into guarantee. Exactly the cross-repo hygiene the scaffolder exists to standardise; removes a whole class of flaky-test and repo-pollution bugs.
- iss-29fail-closed capture surface: a misspelled capture subcommand (e.g. capture resovle) is swallowed as capture text and files a NEW issue instead of erroring (internal/surface/cli/cli.go:455) — a typo becomes a ledger mutation; --json errors emit raw Go text, not JSON (internal/surface/cli/cli.go:165), and abcd docs lint without a config surfaces a raw file error. Detector (per unrecognized-input-never-writes): a surface test convention where every mutating verb has a malformed-input case asserting an error, a did-you-mean for near-misses, and no write occurred, plus a --json error-shape contract test. Acceptance corpus: the three instances above — the detector is proven when it flags all three.
- iss-30memory ingest input-boundary defects: HTTP status is never checked so 404/500 error pages are silently ingested as source content (internal/core/memory/ingest.go:558-575); tilde expansion mangles ~user paths into home+user concatenations (ingest.go:579-584); a --keep-original failure after the page write reports total failure although pages and registry were durably mutated (ingest.go:301-311); CRLF pages are accepted by parseFrontmatter but rejected by splitFileFrontmatter so hashes and summaries silently degrade (yaml.go:558-591); the URL-ingest success path, content-type handling, PDF extraction, and original-storage are untested, as are YAML block scalars and double-quoted escapes. Detector: an ingest-boundary test suite — fetch status matrix, content-type matrix, CRLF round-trip, tilde cases, partial-failure reporting, parser-parity cases. Acceptance corpus: the six instances above.
- iss-31launch dry-run cannot pass on its own repo: the identity scanner hard-fails on /dev/null as a local-username false positive (internal/adapter/scanner/identity.go:230) so the launch gates can never pass here; the launch payload omits skills/ and every file its own fallback instructions depend on (.abcd/config/launch-payload.json); globRegexpCache in the bundle resolver is an unsynchronized package-level map — a data race if the transport-agnostic core is ever driven concurrently (internal/core/launch/bundle.go:559). Detector: a dogfood gate — CI runs abcd launch --dry-run against this repo and expects a pass, plus -race coverage of concurrent resolver use. Acceptance corpus: the three instances above; the dogfood gate fails on all of them today.
- iss-32atomic-write consolidation: four independent temp-file+rename implementations with divergent durability — internal/fsutil.WriteFileAtomic (file fsync + parent-dir fsync), ahoy marker.go writeFileAtomic (no parent fsync, mode-preserving), capture roots.go writeFileAtomic (no parent fsync despite a doc comment claiming durability), memory writer.go durableWrite (parent fsync, O_EXCL naming); isRealDir is likewise duplicated (ahoy store.go vs fsutil). internal/fsutil itself has zero tests. Detector (per one-canonical-primitive): a lint flagging private redefinitions of the canonical names (writeFileAtomic, isRealDir) outside internal/fsutil, plus a fsutil crash-safety test suite; consolidation then drains behind the armed lint. Acceptance corpus: the three non-canonical copies and the duplicate isRealDir.
- iss-33RE-SCOPED 2026-09-09 against the shipped tree. Every instance in the original
- iss-34refusal guards with zero coverage: the launch bundle symlink-dereference and scripts-deny guards (internal/core/launch/bundle.go:339), the memory quotation-budget and licence-detection compliance checks (internal/core/memory/lint.go:225), and the memory ask --file-back write path (internal/core/memory/ask.go:354) are all untested. A guard fails silent: when it regresses the system keeps working and simply stops refusing. Detector (per guards-prove-themselves): a convention that every refusal path ships a test presenting the forbidden input and asserting the rejection, its error shape, and the absence of side effects; a pairing lint between declared invariants and named tests is the promotion path. Acceptance corpus: the five guard paths above.
- iss-35brief-vs-shipped-surface reconciliation: 05-internals/08-skills.md claims abcd ships zero user-facing skills and six top-level commands while 04-surfaces/README.md itself tables nine and /abcd:consult and /abcd:ingest are shipped; the shipped skills violate the brief criterion that any artefact mutation is a command, not a skill; the skills/ layout described (abcd-ahoy, commit-attribution, secrets-and-pii) is fictional vs the real consult/ and ingest/; the implemented, user-reachable abcd docs lint and abcd history verbs have no home in 04-surfaces at all; the operator-internal paragraph contradicts the commands/ directory that exists. Detector (per spec-moves-with-the-surface): a record-lint cross-check that every entry under commands/ and skills/ resolves to a brief surface row, and every brief surface row resolves to a shipped or explicitly staged surface. Acceptance corpus: each falsified claim above — the check fails on all of them today. Fix amends the criterion or the surface in one change, never silently.
- iss-36retired-name banlist population: roughly fifty stale references to retired locations and identifiers survive in the record, and the drift outlived a dedicated same-day consistency pass — development/activity (38 refs in the brief), .work/issues and bare .work/ as a root path (11 refs), scripts/abcd/, .abcd/logbook, .flow/, .github/workflows/lint.yml and lint-corpus.yml, --since-staged, and the python-lint-names pattern narrowly missing bare intent_lint (used by intents/README.md and adr-34). Detector (per retire-the-name and fix-the-detector): add each retired spelling to record-lint banned_tokens with allow_context for genuinely historical passages, widen the intent_lint pattern, then drain the references BEHIND the armed bans — never ahead of them. Acceptance corpus: the reference counts above; the bans are proven when they flag all ~50 on first run and the count ratchets to zero.blocks iss-56
- iss-37Phantom enforcement claims: developer docs describe gates that do not run as described. Re-scoped by the 2026-08-03 maintainer disposition to three doc-claim instances, each a claim about the local pre-push gate or CI:
- iss-38hand-maintained index drift: intents/README.md corpus listings have drifted from the filesystem; commands/README.md lists three of the seven plugin verb files; internal/README.md still describes core as two capabilities with adapter/scanner as a planned seam; the repo README Layout omits skills/ from the plugin surface. Detector (per adr-5 derive-dont-store): hand enumerations of sibling files are generated or deleted — a lint flags a README that enumerates directory contents by hand, or the enumeration is emitted by tooling with a drift test. Acceptance corpus: the four stale indexes above.
- iss-39record schema validation: adr-6 is cited as a live design input but does not exist and no successor records superseding it; adr-12 is not marked superseded by adr-32; itd-47 and itd-49 sit in superseded/ without supersession frontmatter; the superseded/ lint exemption is broad enough to hide content-rule violations. Detector: a mechanical record-schema check — every prose handle (adr-N, itd-N, iss-N) resolves to a file; supersession is bidirectional (superseded-by and supersedes both present); filenames match their patterns; every lifecycle directory is covered by a catch-all so no state escapes linting; the superseded/ exemption narrows to content rules only. Acceptance corpus: the four instances above.
- iss-40one canonical glossary: 02-constraints/04-naming.md maintains a term registry that competes with the brief glossary/ directory; glossary/ is itself stale (contexts and terms missing from its own index, a validation command that does not exist) and is invisible to the brief — neither README.md nor 00-meta.md mention it. Detector: a single-registry rule enforced by a glossary lint — one canonical home, terms in the record resolve to it, the index derived rather than hand-kept, and a banlist entry for the retired registry location once merged. Acceptance corpus: the competing registry, the missing index entries, and the phantom validation command.
- iss-41lifecycle cannot represent delivered work: v0.1.0 shipped capability from a drafts-stage intent while shipped/ sits empty, so the record goes quiet exactly where it matters; the canonical later-phase list in 03-out-of-scope has drifted from the filesystem it claims lockstep with (superseded itd-47 still listed; drafts itd-76/77/78 missing). Detector (per reality-is-filable): define the interim delivery-state rule (how shipped capability is represented before Phase 4), then a lifecycle lint — no CHANGELOG delivery entry whose intent still sits in drafts/, and out-of-scope lists derived from the filesystem. Acceptance corpus: the v0.1.0 drafts-stage shipment and the two out-of-scope list drifts.
- iss-42record orientation currency: CONTEXT.md is stale on the record trust caveat — its single most important orientation fact; phase-shift updates are not a required handoff step so the staleness recurs structurally; record README routing claims point at moved locations; research/ contradicts its own naming convention. Detector: a handoff checklist rule (a phase shift or trust-caveat change requires a CONTEXT.md update in the same change) plus banlist coverage for the moved routing targets. Acceptance corpus: the four instances above.
- iss-43README capability currency. Re-scoped by the 2026-08-05 maintainer disposition to one surviving instance; the original three-claim corpus is closed as filed.
- iss-44plugin surface parity: commands/abcd/ahoy.md drives only the bare read-only detect while the CLI registers install, uninstall, doctor, and dry-run — doctor and dry-run are read-only so a keep-mutation-away-from-agents policy cannot explain their absence, and the landing commit claimed the sub-verbs were wired through the plugin command; every plugin command remedy for abcd not on PATH says make build, which cannot produce an on-PATH abcd; plain-CLI abcd memory ask output is headed as a plugin slash command. Detector: a surface-parity check — every CLI sub-verb is reachable from the plugin markdown or carries an explicit scoping note, and remedy text is exercised by a test. Acceptance corpus: the three instances above.
- iss-45surface-layer boundary leaks: slug derivation — business logic every front door needs — lives in the CLI surface (internal/surface/cli/cli.go:623) so each future front door must reimplement it; cmd/record-lint is a second binary front door duplicating abcd docs lint --config --root, and as a CI gate it has no tests; skills/consult and skills/ingest bypass the abcd binary entirely, their engine being unversioned scripts in the user home (converges with iss-27 corpus-tooling absorption and the script-first-mvp bounds). Detector: a transport-agnostic-core boundary check — decisions live below the surface, front doors only format; one binary front door per capability. Acceptance corpus: the three leaks above.
- iss-46lint scope holes and gate parity: link-lint does not cover all committed markdown; the persona rule is absent from docs-lint; record-lint blocking semantics are inconsistent between local and CI and there is no warn-baseline ratchet; gofmt is missing from make preflight though attributed to it; repo-local hooks activation and its provisioning dependency are undocumented. Detector (per ratchet-not-big-bang): a lint scope matrix (which rule covers which tree, checked into the record) plus baseline-ratchet support in record-lint so new rules arm immediately against frozen violations. Acceptance corpus: the five holes above.related itd-2609291924469783
- iss-47generated CLI reference with a drift test: generate the verb reference pages from the cobra command tree and wire a go test that fails when the committed pages drift from the tree — replacing the phantom freshness gate that docs/reference/cli/README.md currently claims (see phantom-enforcement-claims). A sibling project runs exactly this shape: generated CLI docs gated by a drift check inside the normal test run. Acceptance corpus: the reference pages that do not exist today; the drift test is proven by regenerating after any verb change.
- iss-48behavioural end-to-end coverage: evals/smoke_test.go is structural only (help renders, no panic) — no scenario drives the built binary through a real verb round-trip (capture an issue, resolve it, list it; ahoy install into a temp repo; memory ask against a fixture substrate). Detector: a small scenario suite against the cross-compiled binary, one scenario per verb family, run in CI on both platforms. Acceptance corpus: the verb families with zero behavioural e2e today — capture, ahoy, memory, docs, history, launch.related itd-2609292109475690
- iss-49record cosmetics batch: an orphaned .gitkeep; two verbatim doctrine blocks duplicated in the record; the ACKNOWLEDGEMENTS ccpm entry was added retroactively against its own same-change rule; the brief lacks a one-page arc42 crosswalk and an open-questions precedence line; 05-personas.md should be rewritten role-first with personas.json as the roster source of truth. Low individual impact; batched so the cleanup pass has one handle. Detector: none warranted beyond the existing lints — this is the residue after detector-shaped clusters were extracted, fixed directly per the fix-the-detector one-off bound.
- iss-50Adopt Decided/Implemented as the fixed value set for the wiring-status field on brief surface rows. The convention serves the spec-moves-with-the-surface practice: a surface row that names a verb must state mechanically whether the verb is merely decided or actually implemented, because it was the absence of exactly this state that produced the empty-shipped/ incident, where a surface documented as shipped had nothing behind it. Detector: the spec-moves-with-the-surface cross-check reads the wiring-status field mechanically, so any row missing the field or carrying a value outside the two-token vocabulary fails the check; acceptance is the cross-check parsing every surface row without a free-text fallback.
- iss-51Extend the banlist so that every banned_tokens entry carries a successor mapping (old token to new token) and names the context in which the ban applies, with allow-contexts kept narrow and enumerable. The convention serves vocabulary hygiene without collateral damage: a term retired in one context may legitimately persist in another, and global bans over polysemous terms are false-positive generators that train people to ignore the lint. This extends the iss-36 banlist work. Detector: the record-lint banlist schema rejects entries lacking a successor or a named context, and acceptance is a lint run where every ban fires only inside its declared context and each hit reports the successor to use.
- iss-52Every corpus source carries an epistemic tier — peer-reviewed, preprint, practitioner, or ai-generated — recorded at ingest time and surfaced by consult, so that the trust level of a source travels with the source rather than living in the reader's head. The convention serves evidence discipline: AI-generated sources support nothing on their own and may only corroborate claims grounded elsewhere, and a consult result that hides tier invites laundering weak evidence into strong claims. Detector: the ledger lint refuses influence edges whose source lacks a tier; acceptance is an ingest path that cannot register a source without one and a consult output that displays it.
- iss-53Every mutating verb's brief surface row carries at least one If/Then unwanted-behaviour clause in the EARS pattern (If <unwanted condition>, then the system shall <refusal or recovery>), making the refusal a first-class, testable spec item before any code exists. The convention serves specification completeness: unwanted-behaviour handling is the dominant omission class in specs, and a row that only describes the happy path leaves the fail-closed behaviour to be invented at implementation time. This feeds the iss-29 fail-closed test convention, which needs a spec-level clause to test against. Detector/acceptance: a surface-row lint flags any mutating verb whose row lacks an If/Then clause, and each clause maps to at least one fail-closed test.
- iss-54ADR frontmatter selectively gains three argument fields: related_principles (which standing principles the decision leans on), a confidence qualifier, and revisit_when — the rebuttal slot naming the conditions under which the decision no longer holds. The convention serves decision durability: an ADR that records only the choice invites re-litigation, while one that records its confidence and its expiry conditions tells a future session exactly when reopening is legitimate. Adopt the fields selectively per the 2026 template-comparison evidence rather than the full heavyweight argumentation set, which adds ceremony without proportionate recall value. Acceptance: new ADRs carry the three fields where they apply, and a revisit_when condition coming true is sufficient grounds to reopen without further debate.
- iss-55Six public corpus entries are keyword stubs with no document text — five practitioner SDLC pieces and one harness-engineering post — and they yielded zero extraction candidates in the 2026-07-09 tool-extraction pass, so the corpus claims coverage it cannot deliver. The fix serves retrieval honesty: backfill the full texts via the ingest path, and attach the on-disk PDF to the already-registered research-integrity paper entry so its text is queryable too. Detector: a corpus lint flags any text.md stub whose ledger entry claims a fetchable URL; acceptance is a lint run with zero such stubs and a consult query over the six entries returning document text rather than keywords.related itd-2609292108089653
- iss-56iss-36 lists .abcd/logbook as a retired location, but the shipped binary writes there: memory lint reports go to .abcd/logbook/memory/ (internal/core/memory/lint.go) and the scanner skip-list references .abcd/logbook/pii-scan/. Adjudicate before any logbook ban is armed; the logbook token was deliberately left OUT of record-lint banned_tokens.blocked by iss-36
- iss-57capture --source has no autonomous-agent provenance value: agent-finding means a review agent's finding, but an autonomous run's self-observation has no honest source enum; the run had to reuse agent-finding. Candidate: add an agent-observation (or autonomous-run) source.
- iss-58history capture requires a bootstrapped ~/.abcd/history store, so the autonomous run cannot dogfood transcript capture until ahoy install runs on this repo (ahoy doctor: 12 detection gaps). Also the error says 'run abcd install' but the real verb is 'abcd ahoy install' — misleading remediation text.
- iss-59Two-layer verification lesson from the iss-36 sweep: 73 mechanical fixers + per-file grep-verify reported 100% clean, yet a 4-segment judgement review found ~30 real truth defects (invented homes for unmigrated material, false present-tense capability claims). For the run seam (itd-29/Phase 5) and any future corpus sweep: grep-verify proves pattern absence, never truth; a sweep is done only after a judgement review layer passes. Also: fix agents given precise per-finding instructions applied 100% cleanly — precision of the fix list, not agent capability, was the quality lever.
- iss-60Subagent incident during the context_status_free build: the implementation agent reverted temporary test mutations with 'git checkout -- lint.go' and wiped its own uncommitted implementation (recovered verbatim, gates re-verified). Agent-hygiene rule for the run seam and prompts: agents revert edits with the editor, never with git; git-based revert over an uncommitted tree is destructive. Same hazard family as iss-28's ambient-git exposure.
- iss-61skills/ ships in the tree (consult, ingest, prepare-this-repo) but is absent from .abcd/config/launch-payload.json includes, so a cut release artifact would silently drop the plugin's skills. Found while reconciling 04-launch.md against the dry-run bundle (23 files, no skills paths). Either payload drift (add skills/ to includes) or deliberate exclusion that the brief must state.
- iss-62abcd-managed repos must guarantee the user's chosen git identity (name + email) is honoured on every commit. ahoy doctor should detect when the effective git author/committer identity diverges from the user's GitHub identity — a stray repo-local user.name/user.email override (e.g. a sandbox 'Test User <test@example.com>' shadowing the global identity), or committer != author — and, rather than silently setting it, PROPOSE a default (the global git identity, or the gh-authenticated account) and ASK the user to confirm before writing repo-local config. Motivation: a repo-local 'Test User <test@example.com>' override silently authored/committed 54 commits (pushed to origin) before detection this run, forcing a history rewrite + force-push to correct. A managed-repo identity gate at ahoy/doctor time catches it before the first commit.related itd-131
- iss-63iss-62 identity-gate follow-ups from security review (advisory, non-blocking): (1) the pre-commit shell guard mis-parses a pinned name containing an escaped double-quote (sed truncates it), blocking even a correctly-configured identity — fail-closed but a usability bug; WritePin also emits that escaped form. Consider delegating to 'abcd ahoy identity-check' when on PATH, or a more robust JSON parse. (2) A programmatic caller passing ApprovedCategories{ConfigChange:true} (without --yes) still auto-pins the current identity; deliberate per-category approval, flagged as a conscious choice.
- iss-64Make rule-injection a seam: keep the native Go loader (itd-3) as the floor, add an opt-in 'carl' backend so a user with CARL installed can route to it. Per adr-22 native-default + easy-onboard-a-better-external. Config rules.backend: native | carl.related itd-2609292109214516
- iss-65scanner serialized-finding secret cross-leak (BLOCK) + scan hygiene: Finding.MarshalJSON rebuilds the snippet from the full source line but masks only THIS finding own token, so a second secret on the same line (minified JSON, collapsed .env, a=X; b=Y) is serialized verbatim (finding.go:124). Also isText caps the UTF-8 sniff at 8192 bytes and utf8.Valid fails when the cut splits a multibyte rune, misclassifying a valid >8KB text file as binary and skipping the scan (scanner.go:338); ScanBundle drops an unreadable file with a bare continue instead of surfacing it in Unscanned (scanner.go:269); per-repo pii.json skip-lists have a severity floor but no coverage floor (scanner.go:128). Detector: two-secrets-one-line redaction test; mid-rune isText case; unreadable-file-surfaced case; skip-list coverage floor. Corpus: sweep C14/C17, C15, C18, P10.
- iss-66rules loader trust-boundary (itd-3): an untrusted per-repo .abcd/rules.json can silence default guardrail domains — Merge() ORs the global kill switch (rules.go:156) and mergeDomain lets an override set any default domain dormant, so a cloned repo suppresses all rule injection (P15); session-state lives in a predictable shared /tmp path (os.TempDir/abcd-rules-state, sha256(session).json, session defaults to constant default) letting a local co-tenant suppress injection fail-open (inject.go:99, P14); Load() Lstats rules.json then os.ReadFile re-resolves by name, a symlink-swap TOCTOU (rules.go:132, C19). Detector: override cannot disable a default guardrail/kill-switch; state under UserCacheDir+ownership check; open-once O_NOFOLLOW+fstat. Corpus: P15, P14, C19.
- iss-67intent lifecycle fidelity gaps (itd-80): Plan accepts an Acceptance-Criteria section with no top-level bullet (hasAcceptanceCriteria only checks non-blank) so the intent plans then perpetually dead-letters at ingest (countAcceptanceCriteria==0) — Plan and ingest disagree on has-criteria (intent.go:108, C9/seed8); review ingest appends the audit below the template Empty-until placeholder instead of clearing it on first verdict (seed3); ReEmitReview documents a re-park but silently no-ops on an already-INGESTED/DEAD_LETTER receipt (review.go:188, C10/seed10); DEAD_LETTER re-ingest rewrites byte-identical content instead of a no-op (seed9). Detector: Plan and ingest share countAcceptanceCriteria; first-verdict-clears-placeholder; terminal-receipt re-emit; idempotent deadletter. Corpus: C9, seed3, C10, seed9.
- iss-68spec store hardening (itd-80): spec.Create writes a Summary/TODO body — decide the minimal native-spec body and make record-lint tolerant (spec.go:135, seed4); ensureDir/ensureRealDir only Lstat the leaf so a symlinked ancestor (specs/, intents/) is followed — literal guard or honest comment (seed5, spec+intent); readRepoFile Lstat then ReadFile re-resolves the path (symlink TOCTOU) and the size cap is not atomic — open-once O_NOFOLLOW+fstat+LimitReader (store.go:225, P7); Close Lstat-exists-then-Rename is racy and os.Rename silently overwrites — no-replace primitive (store.go:212, P8); maxIntentSpecNum silently drops a non-null unparseable spec_id, fail-open reservation scan (store.go:146, P5). Corpus: seed4, seed5, P7, P8, P5.
- iss-69frontmatter canonical consolidation + delimiter bug: internal/core/lint (frontmatterFields) and internal/core/memory (parseFrontmatter/splitFileFrontmatter) each carry their own frontmatter scanner instead of internal/core/frontmatter — migrate both, behaviour-preserving, separate refactor commit (seed1); note memory needs nested-map values (source:) the flat scanner lacks — widen or scope. Bug: the canonical scanner closing-delimiter check compares the CR-trimmed line to exactly triple-dash, so a closing triple-dash with a trailing space/tab is not recognised and body lines leak as fields — TrimRight before both delimiter checks (frontmatter.go:37, C5). Corpus: the two lint/memory copies + the delimiter case.
- iss-70record-lint receipt-gate hardening (VSA gate): checkReceiptGate does not bind a receipt to the gate it attests — one genuine PROMOTE receipt satisfies EVERY required gate by copying it to each path (lint.go:601, C16); ArmReceiptGate keeps committer-editable required_gates when the caller supplies an empty list, fail-open arming (config.go:136, P9); workflowStepNames captures nested name keys (with: name:) as gate step names (lint.go:857, P4). NOTE C16 adds policy.detector to the receipt JSON schema — a record-lint CONTRACT change, surface for maintainer sign-off before landing. Detector: mismatched policy.detector BLOCKED per gate; empty arming fails closed; only step-indent name captured. Corpus: C16, P9, P4.
- iss-71capture ledger concurrency + unvalidated ForceID: transition() (resolve/wontfix) takes no flock (only reservePath does) so two concurrent conflicting transitions on the same iss split-brain it across two status dirs — permanent corruption, findIssue then always ErrDuplicateIssueID (workflow.go:129, C4); reservePath builds a path from and O_EXCL-creates a placeholder for ForceID BEFORE validateStrict checks it against the iss-id regex, a pre-validation filesystem touch/traversal (alloc.go:91, P13). Detector: hold the ledger flock across findIssue+commitTransition; reject a non-matching ForceID before any filesystem op. Corpus: C4, P13.
- iss-72core.Status.IsGitRepo=false in a linked git worktree or submodule: isDir(.git) requires a directory but .git is a regular gitfile (gitlink) in worktrees/submodules, so a genuine checkout reports not-a-git-repo (core.go:47, C1). Detector: an exists-not-isDir check for .git with a worktree fixture. Corpus: C1.
- iss-73Relocate memory-lint logbook output and scanner skip-paths from .abcd/logbook/ (a retired location per iss-36) to .abcd/.work.local/logs/, the gitignored runtime-artefact tier. Maintainer adjudication of iss-56 (2026-07-12): runtime artefacts belong in .work.local/logs/, not a tracked dir. Sites: internal/core/memory/lint.go writes .abcd/logbook/memory/lint dirs; internal/adapter/scanner/scanner.go defaultSkipFragments references .abcd/logbook/pii-scan/ and audit-history/. Fix both plus tests; once the binary no longer writes there the .abcd/logbook retired-location ban (iss-36/iss-56) can be armed. Actionable fix behind iss-56 adjudication.
- iss-74Duplicate iss-56 id: two open issues share id iss-56 — iss-56-iss-36-lists-abcd-logbook-as-a-retired.md and iss-56-managed-pre-commit-gates.md. The allocator scans max N across open/resolved/wontfix under flock+O_EXCL, so a collision implies a manual add that bypassed it or an allocator gap. Ledger-integrity bug: derived priority, blocked_by edges, and resolve/wontfix by id are all ambiguous while two files answer to iss-56. Detector (per unrecognized-input-never-writes / ledger integrity): a capture/record-lint check that ids are unique across the three status dirs; acceptance corpus = the two iss-56 files. Fix: renumber the later-created one to the next free id and repoint any inbound blocked_by.
- iss-75abcd lacks an always-latest / dev install mode for dogfooding: 'abcd ahoy install' symlinks a pinned built binary and there is no plain bin/abcd, so tracking live development required a hand-rolled ~/.local/bin/abcd wrapper that runs 'go build -C <repo> && exec' on each call (rebuild-from-source, fail loudly on a broken build). This manual workaround means abcd's own install path does not cover the dogfooding case. Consider 'abcd ahoy install --dev' / a track-latest mode, or bless+document the wrapper as the sanctioned dogfood path. Recorded per the golden rule: a manual workaround must be captured, never silently bypassed, so abcd can be fixed.
- iss-76cli.Run now routes all command errors through the --json envelope, so any verb that returns a bare *fs.PathError (os.ReadFile/os.Open failures not wrapped by core) emits the absolute local path into machine JSON output, violating no-absolute-paths-in-machine-output. iss-29 sanitised the docs-lint config-load branch specifically; the systemic fix is to sanitise PathError-bearing errors at the Run() boundary (or audit which errors reach the envelope). Detector: a table test that runs each verb's known filesystem-error path under --json and asserts the envelope carries no absolute path. Pre-existing as stderr text; newly widened to --json by cli.Run.
- iss-77launch payload completeness: .abcd/config/launch-payload.json includes only [.claude-plugin, commands, scripts, docs, README, LICENSE, .gitignore] and omits agents/ and hooks/, both of which exist and are auto-discovered Claude-Code plugin surfaces (agents are referenced by the harness; hooks are the prompt-router injection transport). The iss-31 'omits skills/' instance is now STALE (no skills/ dir — reclassified to commands/abcd/ on 2026-07-11, already shipped via the commands include). Deciding the exact public includes set (do agents/ and hooks/ ship as-is? do hooks reference a binary path that must resolve post-install?) is design-shaped — maintainer call. Detector: a bundle-completeness test asserting every auto-discovered plugin surface dir is either included or explicitly excluded-with-reason.
- iss-78launch dry-run cannot fully pass on this repo even after iss-31's three instances are fixed: .abcd/config/version-location.json is absent, so CheckLockstep reports the contract unreadable and retention refuses on an empty (non-SemVer) version. This is the un-self-installed source-repo state, not a code defect, but it blocks the 'abcd launch --dry-run is green on its own repo' dogfood gate. Resolve by running the version-location decision setup (or documenting the repo as pre-launch). Needed before the aggregate launch dogfood gate (a CI/test that dry-run is green) can be armed.
- iss-79fifth divergent atomic write: internal/core/memory/ingest.go storeOriginal (~:806) is an inline temp(.memtmp,O_EXCL)+fsync+rename durable write that iss-32's consolidation left untouched — it is inline, not a named func, so TestNoNonCanonicalAtomicWritePrimitives (name-based) cannot catch it, and it was outside iss-32's named 4-copy corpus. It differs from canonical fsutil.WriteFileAtomic: no parent-dir fsync, no explicit chmod. Consolidate it onto fsutil.WriteFileAtomic(target, material.rawBytes, 0644) (keeping the pre-existing sources-dir symlink guard), OR extend the canonical-primitive detector to catch inline temp+rename sequences. Safe today (has its own symlink guard); this is a completeness/consistency follow-up.
- iss-80Record id allocators (itd-N, spc-N, iss-N) are branch-local: parallel agents on separate branches each scan for max+1 and mint the SAME id. Two intents both claimed itd-82 and both merged to main (PRs #46, #47). The iss-N allocator hit the same class before (iss-77 collision, manually renumbered to iss-79; class recorded as iss-74). Resolving a collision forces a renumber, which breaks the record's stated 'ids are capture-stable, never renumbered' invariant -- so the minting scheme, not the renumber, is the defect. This capture is the MINTING half: a collision-free allocation scheme is needed (forge-minted / random-suffix / timestamp / reserve-registry -- SOTA under research). The DETECTION half is armed separately: intent_lifecycle now blocks duplicate intent ids.
- iss-81Machine output surfaces absolute local paths OUTSIDE the cli.Run error-identity scrub added in iss-76. Two instances found in the iss-76 security re-review: (1) 'memory ingest <abs-path>' — materialFromLocal EvalSymlinks-resolves the user's source argument and embeds the resolved absolute path in a custom IngestError (internal/core/memory/ingest.go:655,658,663,667). It lies outside cwd/home, so scrubPaths' root-redaction and PathError base-name reduction both miss it. Low severity: it is the user's own argument and carries no developer identity for out-of-home paths (a ~/x argument still redacts to ~/x). (2) STRONGER, separate surface: the capture SUCCESS envelope emits an absolute 'path' field, e.g. {"path":"<home>/.abcd/work/issues/open/iss-N-...md"} — a full home/cwd-rooted path emitted unbidden on the SUCCESS path, which the error-only scrubPaths never sees. Detector (per unrecognized-input-never-writes / no-absolute-paths-in-machine-output): extend the per-verb --json table to assert no absolute path in BOTH the success and error envelopes for verbs echoing store/source paths; fix by rendering repo-relative or base-name paths at those sites. Acceptance corpus: the ingest error sites and the capture success 'path' field above.
- iss-82Sixth divergent inline atomic write, and a detector-coverage gap: internal/core/rules/inject.go SaveState open-codes a durable write as os.CreateTemp + Write + Close + os.Rename with NO fsync and no parent-dir fsync -- weaker crash-safety than even the storeOriginal inline write iss-79 consolidated. It is not routed through fsutil.WriteFileAtomic, and the iss-79 detector (TestNoInlineAtomicWriteSequences) keys on os.O_EXCL + os.Rename so it does NOT flag the CreateTemp+Rename idiom. Fix: route SaveState through fsutil.WriteFileAtomic, and broaden the canonical-primitive detector to also flag inline os.CreateTemp + os.Rename sequences (watch it flag inject.go, then drain). Deferred from iss-79 to keep that change scoped to storeOriginal. Acceptance corpus: inject.go SaveState; the broadened detector must flag it before the fix and pass after. Found during iss-79 correctness review.
- iss-83The /abcd:run protocol has no precondition that the PLAN file itself exists: its fail-closed check covers a missing or malformed mandatory PLAN *field* (ROLE / RECOVER STATE) but not a wholly-absent PLAN *file*. In the drain #2 run the /loop fired against a PLAN_PATH that did not resolve on HEAD because the plan was being authored concurrently in another worktree and only merged mid-session (HEAD moved 54fef5f -> 137f8de under the running session). The runner correctly fail-closed but the gap invited synthesizing a substitute plan. Fix (protocol robustness): add an explicit step 0 — resolve PLAN_PATH on current HEAD; if the file does not exist, STOP and report without synthesizing a replacement plan (synthesis re-introduces the guess-the-gate risk fail-closed exists to prevent). Add an operational note: a plan-driven loop must only be launched after its PLAN is merged to the branch it reads. Secondary: at burst start git fetch + re-derive HEAD rather than trusting the session-start snapshot — here both the snapshot and NEXT.md were stale (NEXT.md described already-committed itd-81 work as uncommitted). Acceptance: the protocol names a missing-plan-file STOP distinct from missing-field, and forbids substitute-plan synthesis.
- iss-84Managed pre-commit gates: the interim prepare-this-repo skill offers the secrets and absolute-path pre-commit config from a private template directory outside the repo. The gate belongs to the configuration layer itself: a core-owned surface should install and maintain commit gates in managed repos, replacing the template copy. Seeded from the scaffold-repo retirement analysis; relates to the pluggable safety gate draft (itd-62).related itd-62
- iss-85Managed attribution config: AI-disclosure attribution (prepare-commit-msg hook adding the kernel-style trailer, hooksPath wiring, AGENTS.md section) is installed by the interim prepare-this-repo skill from a private template directory. No intent covers the configuration layer owning attribution setup in managed repos; it should, so the per-repo attribution policy is declared and enforced by the tool rather than a hand-copied hook.
- iss-86abcd has no read-only convention-audit surface, and the binary gap model is disjoint from the prepare-this-repo skill audit. abcd ahoy --json on a partially-scaffolded repo reports only abcd own install-plumbing gaps (config.json, rules.json, marker blocks, history store) and is silent on the gaps the onboarding skill exists to fix: the missing committed .abcd/work/ tier, the absent AGENTS.md conventions router, and durable decisions leaking into the gitignored layer. The entire Phase 2 gap report had to be produced by hand. Detector: a read-only abcd audit (or extended ahoy doctor) verb that checks the three-tier layout, decision-durability, docs Diataxis/tense, and privacy -- every convention the skill audits by prose. Acceptance corpus (Manuscripts dogfood): (a) missing .abcd/work/ tier undetected, (b) decisions/ vs decisions/adrs/ layout drift undetected, (c) whole convention audit done manually. This is the single highest-value onboarding gap: it is what would make prepare-this-repo engine-backed instead of agent-glue.
- iss-87prepare-this-repo adopt phase is not self-contained in the abcd record: Phase 3-5 reference templates at a machine-local path outside both the abcd repo and the target (pre-commit-config.yaml, prepare-commit-msg, AGENTS.md, DECISIONS.md, NEXT.md). A fresh clone of abcd-cli onboarding a repo would not have them, so the adoption step silently degrades against loud-staging. Detector: an onboarding self-containment check -- every asset the adopt phase applies resolves from within the abcd record or the binary, never an external machine-local path. Acceptance: the Phase 3/4/5 template references in prepare-this-repo.md.related itd-162
- iss-88abcd ahoy classifies a repo with a partial or stray .abcd/ as folder_kind managed-repo even when adopted is null and index_registered is false -- managed reads as abcd manages this when it only means abcd could. No folder_kind value distinguishes a stray .abcd/ built by another workflow from an abcd-adopted repo. Observed on Manuscripts, whose .abcd/development/ was hand-built with zero abcd involvement yet is reported managed. Related: iss-62 managed-repo-identity-gate. Detector: a folder_kind vocabulary that separates adopted from merely-abcd-shaped; acceptance is ahoy --json on a hand-built .abcd/ not reporting managed.
- iss-89abcd defects found while dogfooding a target repo have no ledger home: abcd capture writes only to the cwd repo .abcd/work/issues/, so capturing an abcd bug found while onboarding repo X would either pollute X ledger (wrong repo) or require re-running with abcd-cli as cwd. Surfaced during the Manuscripts B1 dogfood -- these seven captures had to be routed to abcd-cli by hand. Seed: a capture routing option that targets the abcd repo (or an upstream/--repo flag) for tool-defect captures. Acceptance: capturing an abcd defect from within a target repo lands it in abcd ledger without a manual cd.
- iss-90abcd docs lint is unusable inside a target repo without a plugin root: with ABCD_PLUGIN_ROOT/CLAUDE_PLUGIN_ROOT unset it reports plugin_root_status missing and cannot run, so the read-only doc-currency check the prepare-this-repo skill implies is unreachable when onboarding an external repo. Detector: docs lint runs against any repo docs/ given only a cwd (no plugin-root prerequisite), or fails loudly with a one-line remedy per loud-staging. Acceptance: abcd docs lint in a repo with docs/ but no plugin root.
- iss-91prepare-this-repo Phase 3 describes .abcd/.work.local/ as NEXT.md plus scratch/ plus logs/ only, giving no guidance for pre-existing non-standard members. Manuscripts .work.local/ carries WORKLOG.md, DECISIONS.local.md, and SLICE_START (load-bearing for its own autonomous-run cadence); adoption must preserve them but the skill is silent on how. Concrete instance of the broader onboarding-nonstandard-file-placement-interview seed. Detector: the adopt phase enumerates every pre-existing .work.local member and proposes a disposition. Acceptance: the three Manuscripts members above.
- iss-92Maintainer hunch (record only; do not implement, and map against SOTA during design per prefer-sota). Onboarding should follow a strict playbook that identifies every non-standard file in a target repo (e.g. Manuscripts WORKLOG.md, DECISIONS.local.md, SLICE_START), matches each against abcd canon, and proposes where it belongs -- presented interview-style so the maintainer picks from a recommended default they can accept or override (verifier-selects-gates-decide). This generalises the narrower worklocal-nonstandard-members-no-migration finding into the adopt-phase UX. The interview mechanism is a hypothesis, not a decision: the SOTA for convention-onboarding/scaffolding UX must be researched and adversary-filtered for fit before adopting. Detector/acceptance (to firm at design): an adopt run that emits a per-non-standard-file placement proposal with a recommended default the user accepts or overrides.
- iss-93adr-35 leaves two paths by which disembark still writes into the source repo: the Pass-0 dev-sync stage (writes .abcd/work/reviews, .abcd/memory, .abcd/work/issues into the repo) and the backgrounded-execution checkpoint (.abcd/logbook/disembark/<ts>/_state.json). adr-35 promises disembark is read-only over the source and that a test hashes the tree before and after, so both must move out-of-tree (under <dest>, or under ~/.abcd/voyage/<source-root-sha>/) or be excluded from the disembark path entirely. adr-35 does not settle where they go — a design decision owed before the packer ships.
- iss-94The intent corpus still specifies the pre-adr-35 lifeboat model: itd-2, itd-8, itd-9, itd-10, itd-13, itd-15, itd-19, itd-22 and itd-24 variously use the retired 'disembark to home' signature, the in-tree .abcd/lifeboat/ home, or the in-tree .abcd/development/voyage/ path (itd-9's acceptance writes voyage provenance in-tree — the exact path that would fail abcd's own privacy-hygiene audit rule). The brief, glossary and roadmap were reconciled to adr-35; the intents were deliberately NOT rewritten, because an intent is a proposal with its own lifecycle and silently rewriting nine of them inside an unrelated change is worse than tracking the drift. Each reconciles when it is next planned.
- iss-95Wiring the Stop hook does NOT by itself start the transcript clock: history.Capture requires ~/.abcd/history/<root-sha>/transcripts/ to already exist and deliberately never creates it (ownedDirsReal validates the store's dirs are real, not symlinks). That dir is bootstrapped by 'abcd ahoy install'. On a machine where install has not run — including this one, where ~/.abcd/ does not exist at all — 'hook session-end' fails closed, logs to stderr, exits 0, and captures NOTHING. Silently. That is precisely the failure mode itd-89 exists to prevent: a hook that appears wired while the corpus never accrues. Decide: (a) the hook bootstraps the store itself (changes Capture's stated precondition, and a hook creating dirs is a trust-boundary act the ownedDirsReal discipline deliberately avoids), or (b) 'ahoy install' stays the sanctioned bootstrap and the not-installed case is made LOUD rather than a stderr line nobody reads (e.g. ahoy doctor already flags history.bootstrap_missing as a required gap). Until this is settled, itd-89's acceptance is met in code but not on any machine that has not installed.
- iss-96Now that transcripts are captured automatically on every session end, the scanner's secret-pattern coverage becomes load-bearing in a way it was not when capture was a manual verb nobody ran. Verified by live test: the bundled patterns DO catch anchored tokens (AKIA... access key IDs, ghp_/gho_/sk-ant- style prefixes) and absolute home paths, but they do NOT catch unanchored high-entropy values — an AWS SECRET access key (the 40-char base64 value, no prefix), a bare password, or a generic API token with no recognisable prefix all pass through into the store verbatim. This is the standard prefix-matching limitation and is pre-existing, not a regression; the point is that the blast radius changed. Consider entropy-based detection or the opt-in gitleaks adapter for the transcript path specifically, where the input is unstructured prose rather than curated source.blocks iss-125
- iss-97ahoy.Detect reads CLAUDE.md/AGENTS.md/config via plain os.ReadFile with no size cap or O_NONBLOCK, unlike the hardened session-end transcript read; a FIFO or multi-GB file at cwd could hang or slurp any hook that calls Detect (session-start, session-end, ahoy verbs). Harden Detect's marker/config reads to match maxTranscriptBytes plus a non-blocking open.
- iss-98disembark evidence/what-didnt grounds only on git reverts; repos that abandon via deletion or dead branches (not revert) report blank. Extend the Tier-0 adapter to also read files deleted after substantial history and branches abandoned unmerged — the graveyard adapter already gathers this.
- iss-99disembark has no adapter scanning code for TODO/FIXME markers, so evidence/open-questions is blank on any repo without a native record even when the code is full of TODOs. Add a conventions-tier adapter that greps tracked files for TODO/FIXME/XXX.
- iss-100disembark has no conventions-tier adapters for constraints/naming, glossary, or internals, so these ground only from an authored abcd brief. Add adapters reading GLOSSARY.md / docs/glossary (naming, glossary) and docs/architecture / package layout (internals) so a repo with conventional docs but no abcd record still grounds them.
- iss-101registerRepo does an unlocked load-modify-write of ~/.abcd/history/index.json (loadHistoryIndex -> mutate -> writeHistoryIndex, apply.go), and bootstrapHistory is check-then-act. WriteFileAtomic prevents torn files but not lost updates (last rename wins), so two concurrent 'abcd ahoy install' runs from different worktrees can drop a repo registration or clobber the registry with an empty Repos list, erasing lineage/supersedes links set on explicit user confirmation. Deferred from the multi-agent bug hunt (was B30): a correct fix needs an inter-process O_EXCL/flock lock in ~/.abcd/history held across the load-mutate-write, with a re-load inside the lock and bootstrapHistory creating index.json with O_EXCL. The registerRepo sequence spans an interactive prompter.Confirm (re-founding lineage), so the lock must NOT be held across that prompt (risk of blocking other processes on user input). Low severity, self-heals on next install. Needs a dedicated change.
- iss-102cleanOrphanPlaceholders (capture/alloc.go) runs locklessly from mutationPreamble at the start of every Capture/Resolve/Wontfix, while commitCapture (workflow.go) fills the reserved placeholder OUTSIDE the ledger flock. A capture stalled >60s between reservation and commit can have its just-committed issue file deleted: the sweep's Lstat passes (size 0, aged) then the stalled commit's atomic rename lands, then the sweep's os.Remove deletes the fully-committed file — after Capture returned success. Deferred from the multi-agent bug hunt (was B26): a pre-unlink re-check (orphanStillRemovable: re-Lstat + SameFile + size==0) already mitigates the common interleaving, but full elimination requires running the sweep AND the commit write under withLedgerLock (the commit write path is in workflow.go). Low severity; data-loss only under a >60s stall plus concurrency.
- iss-103gitutil.CheckIgnored returns an empty map for every non-zero git exit, conflating 'nothing ignored' (exit 1) with 'git cannot answer' (exit 128 not-a-repo/corrupt, or git absent). This is intentional fail-open and correct for the audit-rule callers (which guard with InRepo). The one reachable defect was the launch bundle's finalize calling it unguarded, so a git failure silently admitted every gitignored file to the release bundle — that is already fixed (was B18: launch now uses a fail-closed checkIgnoredStrict). Recorded from the multi-agent bug hunt (was B23) for the record: consider lifting a strict, error-returning CheckIgnoredStrict into gitutil so the launch package need not keep its own copy, while preserving the fail-open CheckIgnored for audit. Nitpick / tech-debt; no live defect remains.
- iss-104intent quoted-text create treats any non-subcommand first token as create text (no suspectedTypoedSubcommand guard like capture): 'abcd intent paln "x"' files a draft instead of erroring; consider porting capture's typo heuristic for symmetry
- iss-105the intent verb family (plan/link/review/ingest and now quoted-text create) has no plugin markdown surface (no commands/abcd/intent.md) — pre-existing gap against the wired-from-both-surfaces boundary; itd-46's old-system scope bullets assumed one existed
- iss-106GL002 stripInlineCode restores the whole line on an unpaired trailing backtick (and mishandles double-backtick spans), so a closed code span containing an enforced synonym plus a later stray backtick fires a spurious blocker — fails toward over-flagging, never misses drift; found by burst-5 correctness review, not present in current corpus
- iss-107ahoy install --visibility <v> --yes reports 'already up to date' without applying the explicitly requested visibility on an already-configured repo: skip-if-set beats an explicit flag — stepConfigValues short-circuits when repo.visibility is validly set (internal/core/ahoy/apply.go:196) and ValueOverrides are only consulted on the config-gap path (apply.go:179->220), so the flag silently no-ops; an explicit flag value should either apply as an update or error loudly, never silently skip (maintainer hit this from another repo and hand-edited its config)
- iss-108iss-35 semantic release gate was self-referential under changelog-driven auto-release (adr-37): it armed receipt_gate with the tagged commit but read receipts from that commit's own tree, which can never hold a receipt naming itself. Dormant while private, it fail-closed the first public release (v0.3.0).
- iss-109ahoy manual-guard reads carry a residual Lstat->ReadFile TOCTOU: verifyHookManifest (store.go), and gitignore.go read sites (~72, ~181) each do Lstat+IsRegular+size-cap then a separate os.ReadFile, so a type/symlink swap between check and read is not refused on the same fd. iss-97 converged the six bare-unguarded ahoy reads onto fsutil.ReadGuarded (single-fd O_NOFOLLOW|O_NONBLOCK+cap); these three were left because their structured signals (verifyHookManifest reason strings; gitignore bool flags + the write-path oversize refusal) need preserving, so the convergence is not mechanical. Route them through ReadGuarded too, preserving those signals, to close the TOCTOU and reach one guarded-read mechanism. Sibling of iss-97.
- iss-110agents/CHANGELOG.md and agents/README.md are plain docs (the itd-5 prompt-version log; a readme) but the plugin agent-loader globs agents/*.md, so both are mis-registered as agents (abcd:CHANGELOG, abcd:README appear in the harness agent list). They have no agent frontmatter and are not invokable workers. Fix: either move these docs out of agents/ (e.g. to .abcd/development/ or a docs path) or make the loader skip non-agent files (require agent frontmatter). Surfaced by the derived-changelog plan adversarial review, which had assumed the abcd:CHANGELOG slot was free for a new composer agent.
- iss-111The open-questions marker pattern admits a bare uppercase word followed by whitespace, so prose that merely mentions a marker matches. Measured against this repository the adapter reports 42 markers across 11 files at medium confidence, and every one is documentation about markers rather than a work marker. The precision cost lands on repos that document their own conventions. Options: require the trailing colon or parenthesis, or drop the bare-word alternative for the ambiguous markers only. spc-12 fixes the current pattern, so this is a design revisit.
- iss-112WalkFiles caps the number of regular files it returns, but fs.WalkDir calls ReadDir(-1) on every directory it enters, so a single directory holding millions of entries balloons memory before the file cap can apply. The maxWalkFiles doc comment claims the walk stays bounded in memory, which is only true of the returned slice. ListDir already bounds this with ReadDir(maxDirEntries); the walk does not share that guard. Found by an independent security review of the itd-95 diff.
- iss-113convOpenQuestionsSource's truncation evidence names only the "%d-file walk cap", but WalkFiles now also truncates on its directory cap and its depth cap, so a walk stopped by either reports a cause it did not hit. The three affected strings are the searched note, the blank's qualified question, and the non-blank scan note. convInternalsSource words the same note as "walk cap (N entries, M levels deep)"; the two should say the same thing. Found by an independent security review of the itd-96 diff.
- iss-114WalkFiles opens every directory through os.Root.FS(), which re-resolves the whole path from the containment root one component at a time, so a walk costs O(entries x depth) component opens. Measured post-fix: a 60000-directory tree at depth 30 takes 10.5s for one probe (two adapters walk it concurrently). The depth and directory caps bound this, but the constant is high. os.Root.OpenRoot would let the walk hold a sub-root per directory and open each child in O(1). Found while fixing the unbounded-walk finding in the itd-96 review.
- iss-115There is no uniqueness lint for spec ids, so two concurrent branches always mint the same spc-N. abcd mints the next free id from the local tree, so any two branches cut from the same base collide silently: the itd-73/itd-67 programme and the itd-95/itd-96 programme both minted spc-10 and spc-11 on 2026-07-21. The collision is invisible on each branch and only appears on merge, where it breaks the bidirectional intent-spec link in BOTH directions at once — 'itd-95 names spc-10, but spc-10 claims itd-73' and 'itd-67 names spc-11, but spc-11 claims itd-96' — because whichever spec wins the store lookup leaves the other intent's link dangling. iss-74 added an issue-id uniqueness lint; specs need the same guard, and record-lint is the natural home so CI catches it on the PR rather than a human catching it at merge. Consider also whether minting should reserve ids in a way concurrent branches cannot duplicate.
- iss-116The WalkFiles skip set covers only Node and Go dependency trees, so a Python .venv, a Rust target/, __pycache__, dist/, build/ and Pods/ are walked as if they were the team's own source. Two consequences on a record-less repo: the open-questions adapter cites a vendored dependency's TODO as this project's open question, and because fs.WalkDir reads directories in lexical order a large dot-prefixed dependency tree can consume the 50000-file walk cap before the project's own src/ is reached. Found by an independent review of the itd-95 diff; spc-12 names the current skip set, so widening it is a design revisit rather than an implementation fix.
- iss-117abcd capture resolve and intent seedDraft cannot set impact, so the tool's own path produces a record the new issue_impact_valid and intent_impact_valid blockers reject
- iss-118DECISIONS.md and ACKNOWLEDGEMENTS.md are multi-writer single files, the merge-hotspot shape that one-writer-per-file rules out. DECISIONS.md was the only textual conflict of the two-programme merge (resolved by hand as a union of both sides). The remedy is a design call per the principle's bounds: per-decision records (full atomicisation, which needs a new id family plus an armed uniqueness detector) or a merge=union gitattribute (smallest fix, legitimate because the ledger's entries are anonymous dated lines that never need identity). ACKNOWLEDGEMENTS.md is the same shape at lower traffic.
- iss-119AGENTS.md declares the Assisted-by trailer for AI-assisted commits, but nothing enforces it: the repo commits only pre-commit and pre-push hooks, and the global hooks are pure dispatchers. The ad3fc38 merge commit landed on a PR branch without the trailer and no gate objected. Per one-writer-per-file's sibling lesson (a convention without an armed check is silently violated under load), either a commit-msg check validates the trailer on AI-assisted commits or the miss rate is accepted explicitly.
- iss-120Sequential record ids are minted from the local tree, so two parallel programmes mint the same next id — both took spc-10, spc-11, iss-110 and iss-111, costing four renumber commits across the episode. This generalises iss-115 (spec ids lack a uniqueness lint): issue and intent ids have armed detectors via the shared validateIDUnique primitive, spec and ADR ids have none, and detection-after-collision is the only mitigation anywhere. The design call is whether detection everywhere is enough or minting itself should be made collision-free (id-range leases per programme, mint-at-merge), which trades away human-readable sequential ids.
- iss-121The brief's surface chapters fail the iss35 brief-surface crosscheck at full depth: 102 unique discrepancies across the 16 surface chapters plus the skills internals page (54 false-claim, 16 undocumented-surface, 13 fictional-layout, 13 stale-count, 6 criterion-violation). Examples: 02-disembark.md describes a dev-sync verb, an agent-dispatch pack flow, and a backgrounded 'disembark to' sub-verb, none of which the binary ships; 01-ahoy.md omits seven shipped install flags and the identity-pin write. The v0.4.0 release is blocked fail-closed at receipt_gate until the record is reconciled and the crosscheck PROMOTEs. Full findings preserved in the local scratch tier (2026-07-22-iss35-crosscheck files).
- iss-122The iss35 crosscheck's scope and depth are unpinned, so the gate is not reproducible: v0.3.0's receipt records zero findings four days ago while a full-depth run (17 brief docs, both directions, 22 checkers) returns 102 discrepancies, and the receipt's own promptHash field is the literal 'no-pinned-prompt' admission. The maintainer choosing briefDocs per run means two honest runs of the same gate can disagree by two orders of magnitude; the gate needs a pinned input manifest and depth so a PROMOTE means the same thing every release.
- iss-123Round-4 residue of the brief reconciliation: nine precision-grade discrepancies remain after three fix rounds (102 -> 52 -> 25 -> 9), all empirically verified by the checkers and none of the judgement-flip-flop class. Examples: bare ahoy prints a next-step line only for unmanaged kinds but the criterion says any folder kind; embark's manifest verification excludes the post-pack synthesis layer while the chapter claims blanket tamper-evidence; a live bundle (spc-83-operator-surfaces, itd-20+itd-24) contradicts the no-live-bundles claim; the persona_registry lint checks personas.json, not the markdown page named as SSOT; history capture idempotency keys on (sha256, session, kind), not content hash alone. Full findings in the local scratch tier (2026-07-22-iss35-crosscheck-round4 file). The geometric tail also suggests the detector at 22-checker depth has a nonzero noise floor per fresh run — the pass threshold question belongs to iss-122.
- iss-124Review receipts and the review bar have no home or path for repos-we-don't-own: itd-83 fires reviewer agents only in managed repos and itd-28's receipt store is in-tree only, so outbound PRs to foreign repos carry unfalsifiable prose self-attestations ('Reviewed adversarially; no exploitable path found') instead of receipt-backed claims — the evaluator-inside-the-loop shape itd-58's A4 exploit gate refuses. Live specimen: the maintainer's PR #868 to a third-party repo (2026-07-21, reviewed 2026-07-25 with SOTA + adversarial passes). iss-89 is the routing precedent (foreign-repo work products need a home outside the cwd repo). Two seeds ride on this capture rather than as fresh intents: (1) a same-act deferred-hardenings discipline — any hardening a change consciously defers must exist as a filed, cited issue before the change is presented (generalises workaround-records-the-defect beyond abcd's own defects; mechanically lintable: a PR-body 'Deferred' line without an issue id is detectable); (2) a receipt-backed PR-comment adapter for outbound contributions — receipt lands at home per itd-28, a Stage-1-sanitised rendered summary posts to the forge; SOTA review found the receipt-plus-comment position unoccupied (verdict-as-comment is saturated, SLSA v1.2 leaves review attestations explicitly undefined).
- iss-125Hostnames are absent from the Stage-1 redaction pattern list: itd-28's write-time sanitiser enumerates home-dir paths and provider secrets (AWS/GCP/Azure/Cloudflare/GitHub/Anthropic/OpenAI/Stripe/Slack/JWT/PEM) but no hostname patterns, and the transcript scanner's coverage gaps are already tracked as iss-96 — yet the PII discipline forbids posting real hostnames anywhere. Live specimen: a saved third-party PR page (reviewed 2026-07-25) shows two real machine hostnames leaked into public PR comments by a resident review fleet, including a '.fritz.box' home-router LAN name — exactly the class a Stage-1 net must catch before any abcd-produced artefact (review receipt, rendered PR comment, transcript) leaves the machine. Fix belongs in the scanner seam's canonical pattern set (one-canonical-primitive), not a per-surface copy; detector first: add hostname fixtures (LAN suffixes like .local/.fritz.box/.lan, machine-name shapes) to the scanner's acceptance corpus and watch them flag before widening the patterns.blocked by iss-96
- iss-126intent Reconcile ships planned intents into shipped/ without stamping impact, so a no-impact seed passes plan and reconcile then trips the intent_impact_valid blocker on a record produced entirely by the tool's own verbs; a plan-or-ship verb must be able to stamp impact (sibling of the iss-117 class, found by its review)
- iss-127repo-local load-modify-write sites remain unguarded after the iss-101/102 class fix: intent transitions (review.go, lifecycle.go — strongest candidate), ahoy config.json stepConfigValues, gitignore/marker block rewrites, and the CHANGELOG release path all do load-mutate-write without a lock; they lack the home-global cross-worktree exposure the fixed sites had, so risk is same-worktree concurrency only
- iss-128registerRepo's best-effort history paths lose signal silently in two edges the iss-101/102 reviews confirmed: (1) a history-lock contention timeout skips registration with no surfaced note (apply.go registerRepo discards the withHistoryLock error); (2) under concurrent double-install of the same new repo with divergent re-founding answers, the lock loser takes the refresh branch which never consults linkLineage, silently dropping a human-approved lineage link with no lineageConflict message
- iss-129four bespoke LOCK_EX flock loops remain (memory/writer.go, intent/create.go, spec/store.go, history/store.go) now that fsutil.WithFileLock is the canonical inter-process lock primitive; consolidate them onto it (one-canonical-primitive) — pre-existing, no defect, pure debt
- iss-130era-gating tradeoff residue from iss-122: deleting release-gate/manifest.json from the content tree disarms the three new procedural refusals (manifest presence IS the era marker, per the decided design F) — the backstop belongs in release.yml (require the manifest to exist for any release newer than v0.4.0), which is CI config and needs maintainer sign-off; until then a committer who removes the manifest silently reverts the gate to pre-manifest rules
- iss-131gate-hardening nitpicks from the iss-122 reviews, none blocking: (1) the manifest read in receipt_gate uses unbounded os.ReadFile where the sibling convention is fsutil.ReadGuarded (trusted committed file, self-DoS only — but it is the unhardened sibling the bughunt spine says to sweep); (2) receipt.example.json's manifestHash is not test-pinned against manifest.json so a manifest edit silently stales the example; (3) receipt parsing tolerates duplicate JSON keys (Go last-wins) — an audit-legibility gap under the attestation trust model, not an escalation
- iss-132three documentation lines that literally quote a marker with its delimiter (TODO followed by colon) still self-match after the iss-111 fix and are irreducible under the issue's two bounded options; closing them needs a different mechanism, e.g. skipping fenced or inline-code marker examples in Markdown
- iss-133the probe adapters' truncation message says the rest of the tree was not walked, but the per-directory read bound added for iss-112 can set truncated while the walk completed everything else; the over-warning is in the conservative direction, not a loud-staging violation, but the message is imprecise about WHAT was truncated
- iss-134readDirBounded's doc comment claims sorted-by-name determinism, which holds only at or under the bound; a directory exceeding the bound yields a readdir-order subset that is then sorted, so WHICH entries survive is nondeterministic (loud via truncated, consistent with ListDir, pathological trigger only)
- iss-135WalkFiles start-boundary divergence for a non-dot start: a start dir named in the skip set would now be walked and a regular-file start returns nil; unreachable today (both callers pass dot) — flag for any future caller passing a non-dot start
- iss-136itd-88's fidelity gap audit found a missing press-release claim: Pass B is promised to ship as a declared exemption in _provenance.json, never a silent gap, but no exemption field or marker exists anywhere in the lifeboat package or the Provenance struct — a promise with no implementing code, recorded in itd-88's Audit Notes (receipt rcp-4d07032fc6ab)related itd-158
- iss-137probe and coverage ship as CLI verbs only: the plugin markdown surface (commands/abcd/disembark.md) documents plan and pack alone, while itd-88's press release headlines /abcd:disembark probe and coverage — either the surface doc grows the two verbs or the intent's diverged claim is the accepted record (dispositioned in itd-88's Audit Notes)
- iss-138payments protocols have no recorded position: the itd-100 terminology crosswalk found the record silent on agent-led payments (AP2 at the FIDO Alliance, x402, the two-vendor Agentic Commerce Protocol). The crosswalk row is WATCHING because a REJECTS needs a recorded reason; this capture is where that reason gets decided — likely out-of-scope-by-design for a development-configuration tool, but that is a maintainer call, not an inference. Detector: the crosswalk row cites this id; resolving it means recording the position and updating the row.
- iss-139SKILL.md compatibility watch: the record rules abcd ships zero skills (commands-only namespace; any state mutation is a command). The external Agent Skills spec (agentskills.io) is unversioned, draft-stage, and without a standards-body steward, but multi-vendor adoption is real. If a findings-only skill ever ships, SKILL.md is the accepted executable form — this capture tracks the spec's maturation (versioning, stewardship, the Experimental fields) so that decision is made against current facts. The itd-100 crosswalk's REJECTS row cites this id.
- iss-140AGENTS.md stewardship citation watch: abcd's AGENTS.md router predates the format's contribution to the Agentic AI Foundation (Linux Foundation, December 2025). The standardisation strengthens the bet, but the record nowhere cites the AAIF stewardship; the itd-100 crosswalk row now does so from docs/. Resolving this means deciding whether the brief's install/router surfaces should cite the external standard, and watching for spec versioning under the foundation.
- iss-141tamper-evident receipts: receipts and review directories are hash-anchored and manifests are verified, but nothing is cryptographically signed and there is no append-only chain over the receipt history — integrity evidence, not proof against a capable insider. itd-16 (hash-chain/Merkle audit umbrella, draft) is the design home; this capture tracks the narrower question of whether the existing receipt flow should become tamper-evident (RFC 9162-style verifiable log or signing) independent of the full audit umbrella. The itd-100 crosswalk's tamper-evidence row cites this id.
- iss-142prompt-quality brief self-contradiction: 05-prompt-quality.md states PQ001-PQ006 are shipped by spc-8, while 06-lint.md declares the PQ family a design target with no PromptLinter in internal/core/lint — the code sides with 06-lint. An instance of the iss-37 phantom-enforcement class, surfaced by the itd-100 docs-currency review when the crosswalk nearly repeated the phantom claim. Detector: enforcement-claims-are-facts sweep over the brief's Shipped-by annotations; acceptance corpus: the two contradicting lines.
- iss-143tagline three-variant drift: the repo runs three different self-descriptions — README strapline (an opinionated, intent-driven development framework for product thinkers), plugin.json description (host-agnostic configuration layer for development ... usable as a plugin in compatible agent harnesses), and AGENTS.md (a host-agnostic configuration layer for development). The drift is itself the finding: one-canonical-primitive wants a single recorded tagline (a DECISIONS.md line, or the brief's product chapter as the home) with per-surface renderings derived from it. Adopting any new wording without that consolidation just mints a fourth variant. Surfaced by the 2026-07-27 tagline assessment. Detector: a positioning-currency check that the three surfaces render from one recorded home.
- iss-144shell-hazard incident, first corpus entry: in another locally managed repo, an agent ran mkdir -p under a scratch dir, then cd, then rm -rf * in one && chain. The && made it accidentally safe (rm only after a successful cd); with separate statements or a ; separator, a failed cd would have left the harness's persistent cwd at the repo root and rm -rf * would have deleted the working tree. Failure class: destruction chained after cd + cwd-relative glob, one character between harmless and catastrophic. Safe successor: destructive commands name an absolute path and never rely on cwd or a glob. This incident and the agent's own post-mortem are the first acceptance-corpus entry for the shell-hazard registry (teach + enforce planes); guard fixture must prove the block fires on exactly this shape.
- iss-145receipts gate process integrity, not maintainability: candidate principle surfaced by the 2026-07 software-factories critique (primary observation: RL rewards fast oracles — tests pass in seconds — while bad architecture's cost function is measured in months, so maintainability has no fast oracle and models are not penalised for eroding it). Consequence for abcd: no receipt or deterministic gate can certify design quality; that verdict stays human (verifier-selects-gates-decide), and the maintainer merge on every PR is load-bearing, not ceremony. Candidate homes: a principle file or a brief mental-model line; adoption is the maintainer's call.
- iss-146guard-bash false positive class: a compound command chaining a gh write verb with a LOCAL command taking an absolute path argument (gh pr merge ... ; git worktree remove /abs/path) is blocked by the line-level privacy regex, which cannot see that the path never reaches GitHub. Second guard incident of 2026-07-27 (the first, blocking --no-verify, was a true positive). Both are fixture material for itd-103's calibration corpus: this one is a known-good case the TNR floor must protect; the workaround (split the compound) is recorded here so the friction is not silent.
- iss-147guard.Load reads .abcd/guard.json from the WORKING TREE, so a disabled:true (or a retiered blocker) takes effect on the very next command, before anyone reviews it — spc-16 and the shipped docs both say the only escape is a committed, reviewable override, and nothing enforces the committed half. Reachable in one move: an agent writes .abcd/guard.json and the guard itself allows that write. Mitigated at the front door in itd-103 wiring (a disabled registry now warns UNGUARDED on every command, and abcd ahoy reports OFF) but not enforced. Proper fix is core-side: refuse a disabled:true that is not in HEAD, or drop the committed claim from spc-16. Found by the security reviewer on the itd-103 wiring branch.
- iss-148guard registry coverage gaps found while wiring itd-103 (registry content, not matching semantics): a push whose refspec carries a leading plus is a force in disguise and no entry describes it; xargs, timeout and exec are absent from the matcher's wrappers set, so a hazard launched through one of them is not seen; a backtick command substitution is not followed, while the dollar-paren form is; and a wrapper that IS in the set defangs an entry the moment it carries its own flags, because only the wrapper name is stepped over — `sudo <hazard>` is seen, `sudo -u bob <hazard>` is not, and the same holds for `env -i` and `time -p`. That last one is the sharpest: it turns an entry the registry does describe into an allow with one extra token, and it is the only item here that a facilitator would reasonably assume was covered. Candidates for the admission gate as the registry grows from reality; the wrapper-flag item is matcher-side (`commandOf` in internal/core/guard/match.go), not registry content.
- iss-149The positioning check bounds each surface read to 1 MiB but nothing bounds the number of surfaces a committed registry may declare, so one abcd audit run over a hostile repo can be made to hold an unbounded multiple of that cap. Detector: a Config.Validate test that refuses a registry declaring more than a fixed surface count.
- iss-150A committed positioning registry may name a surface inside .git (ValidRelPath accepts .git/config and it is inside the containment root), so abcd identity --json quotes .git/config — including a credential-bearing remote URL — into SurfaceResult.Found. Pre-existing; not an escape, and the output reaches only the operator's own stdout. Detector: a Config.Validate test refusing surface candidates under .git/. Found during the itd-102 containment review.
- iss-151itd-103 shipped only ONE of its two promised planes: the execution-time guard plane is fully wired (abcd guard check/hook, ahoy health), but the TEACHING plane — the rules loader injecting matched shell-safety rules before shell-heavy work, per spc-16 'Two planes, one registry' — is not built; there is no guard/safety/hazard domain in internal/core/rules/. All four itd-103 ACs concern the guard plane only, so the fidelity review is 3 MET/1 MWC, but the intent headline ('two planes') is only half delivered. Wire the teaching plane as a rules-loader safety domain sourced from the same bundled hazard registry, or amend the intent's scope.
- iss-152brief-surface crosscheck residual (non-deterministic tail after 4 tier-full rounds, 27 items fixed): (1) 04-surfaces/01-ahoy.md bare-render enumeration omits the guard: health line the shipped bare 'abcd ahoy' now prints (5 lines not 4); (2) 04-surfaces/07-memory.md:104 enumerates 4 launch dry-run gates but marker-block and documentation-auditor are Status:not_implemented (Phase-5 deferred) stubs — only secret/PII scan + installability smoke actually run. Both minor brief-internal staleness, no user-facing doc affected (docs-currency PROMOTE). Deferred from v0.4.1 release gate via disposition; fix in a brief-currency sweep.
- iss-153privacy-hygiene absPathRe flags /Users/Shared/... (and would flag /Users/Guest/...) — macOS system directories, not usernames. Exempt well-known non-user segments after /Users/ so product code that legitimately uses /Users/Shared does not need per-line waivers.
- iss-154privacy-hygiene detects only absolute home paths — no network-identifier patterns (IPv4 incl. CGNAT/tailnet 100.64/10, hostnames, device names, ports-in-context). Field incident: an agent committed a Tailscale investigation (tailnet IP, two device hostnames, firewall posture, service port, presence/away patterns) into a public repo's committed tier and audit passed it silently. The v1 deferral note names only emails and private-repo names; network identifiers are not even recorded as deferred.
- iss-155three-tier-layout verifies tier presence and the .work.local gitignore but never that local-tier artefacts are absent from committed tiers — a NEXT.md, scratch/, or logs/ under .abcd/work/ or .abcd/development/ passes clean. Field incident: NEXT.md (handover file, local-tier by convention) lived at .abcd/work/NEXT.md in a public repo and carried host infra details; no rule flagged the misplacement.
- iss-156PII rules domain cannot fire on the incident that most needs it: recall keywords (secret, token, credential, pii, redact, hostname, email) miss network/infra contexts (tailscale, vpn, ip, firewall, network, reachability), and the injected rule text carries no never-commit-hostnames-IPs-live-data rule at all — that rule exists only in the parent CLAUDE.md privacy section. An agent writing up a Tailscale investigation gets zero PII injection and zero relevant rule text even if it did.
- iss-157shared scanner (launch dry-run, lifeboat pack, history capture) has token-shaped secret patterns and identity matchers (username, email, home path, github remote) but no network-identifier patterns — a lifeboat pack or launch bundle carrying a tailnet IP, device hostnames, or firewall posture ships clean. Same root gap as the audit rule; fix belongs in the shared primitive, not per-surface.
- iss-158no commit-time gate for user-private identifiers: the canonical home for this is itd-74 (name-banlist, in drafts/) — its private-banlist layer (local untracked file + committed guard hook, refuse by entry-key only, never echoing the value) is exactly the gate this incident needed. This issue is NOT a new primitive: it records the field evidence that itd-74's scope must include machine identifiers (hostnames, tailnet IPs/prefixes, device names), not only harness/project names, and that the incident strengthens the case for promoting itd-74 out of drafts (a maintainer decision). Generic patterns (iss-154/157) catch shapes; only the banlist catches this user's actual names. Prior art at skill level: the confidential-sources sync-banlist guard; dogfood prototype already live per itd-74's own record. Complements, does not replace, iss-154.
- iss-159hazard registry has no entries for destructive GitHub remote operations: 'gh repo delete' and 'gh api -X/--method DELETE repos/{owner}/{repo}' both verdict allow. Field evidence: the user-level guard-bash.sh hook blocks both (repo deletion is human-only; second layer behind the missing delete_repo scope) — that hand-wired hook is the prior art to lift into the bundled registry defaults, same prototype-to-product path as itd-74. Registry entries should mirror the hook's nuances: quote-tolerant token matching (already native), depth-limited api paths (DELETE on deeper repo subpaths stays allowed), and the block message naming the human-only successor.
- iss-160The installed plugin surface exposes a spurious /abcd:README command: the harness registers every markdown file under commands/ as a slash command, so the folder's own README.md leaks into the command list. The doc needs a home or form that the command loader ignores.
- iss-161Plugin verbs render as /abcd:abcd:<verb> instead of /abcd:<verb>: the verb files live in commands/abcd/, and the harness maps a commands/ subdirectory to a namespace segment, so the directory name duplicates the plugin prefix. Verbs need to live flat under commands/ (or the subdirectory renamed away from the plugin name) for the documented /abcd:<verb> surface.blocks iss-162
- iss-162The surface's own guidance is unreachable under the double namespace: ahoy's next-step output (and the command docs) reference /abcd:ahoy and skill-style args like 'install', but the harness registers the verb as /abcd:abcd:ahoy — following the printed instruction yields 'Unknown command: /abcd:ahoy' / 'Args from unknown skill: install'. The rendered guidance must match the registered command names, whatever iss-161 settles on.blocked by iss-161
- iss-163The ahoy install config prompts are unexplainable to a first-time user: core's Prompter interface passes bare enum values only (Prompt(key, choices, def) — e.g. oracle_backend: host-delegated|native|cli|api|mcp) with no per-choice help text, no definition of what an 'oracle' is, and no consequence statement (cost, credentials, tools needed). A host agent rendering the prompt has to invent descriptions, which can be wrong or circular ('native — uses the native backend'). Canonical plain-language descriptions for every choice belong in core, surfaced by every front door.blocks iss-164
- iss-164The ahoy install completion summary is written for abcd's implementers, not its personas: it leads with insider vocabulary ('managed repo', 'canonical marker blocks', 'the identity gate', 'plugin root not resolvable (machine-scope)') and raw internals (ABCD_PLUGIN_ROOT/CLAUDE_PLUGIN_ROOT, the history-index path) without saying what any of it means for the user's work. An Iris (product thinker) or Nia (facilitator) cannot tell what just changed, which items need action, or why they'd care. Like iss-163, core emits result data with no user-facing explanation layer; each reported item needs a plain-language 'what this is / why it matters / what, if anything, you should do' framing at every front door.blocked by iss-163
- iss-165The grill/interview capability should follow the basics-built-in, SOTA-delegated pattern: when an external state-of-the-art interviewing skill is installed in the host (the maintainer names Matt Pocock's grill skill), abcd's grill delegates to it; when absent, abcd offers its own comprehensive built-in interview instead. Same stance as the oracle boundary: the external skill is an opt-in dependency, never a requirement.related itd-2609292108373494
- iss-166ahoy install --yes silently skips the optional identity-pin category: the flag is documented as approving every resolvable change category without prompting, and it reports 'already up to date', yet the interactive path still offers the optional pin (.abcd/config/identity.json). Either --yes covers optional categories too, or its help and the completion output must say optional categories are excluded and how to apply them.
- iss-167The ahoy install confirmation prompt only accepts answers from a real TTY: piped 'y' and pseudo-TTY attempts all arrive as declines, so a host agent cannot drive the interactive path at all. For an agent-first tool every prompt needs a non-interactive answer channel (flags per category, stdin when not a TTY, or a --prompt-answers input) — TTY-only confirmation makes the agent report failure and hand the step back to the human.
- iss-168abcd's presence should be visible in the host harness's status line / command line: a managed repo shows an 'abcd-managed' indicator (and possibly guard health) so the user can tell at a glance whether the current session is under abcd management without running a command. Needs a per-host adapter (e.g. a statusline hook) with the usual basics-built-in stance.related itd-20 · related itd-200
- iss-169ahoy install writes a .gitignore fence that contradicts the tool's own tier convention: visibilityEntries (internal/core/ahoy/gitignore.go:26) ignores .work/ for private repos and .abcd/, memory/, .work/ for public — but the canonical three-tier layout commits .abcd/development/ and .abcd/work/ and gitignores only .abcd/.work.local/. Neither .work/ nor memory/ exists at repo root in that layout, so the installed fence ignores phantom paths while leaving .abcd/.work.local/ tracked — the exact state abcd audit (rule_layout.go) then flags. The code comment cites the brief's visibility table §1, so the brief may be stale alongside the code; the public-visibility set needs rethinking against the actual layout, not just a path swap.
- iss-170resolvePluginRoot's ancestor-walk fallback defeats the install layout ahoy itself creates: os.Executable() (internal/core/ahoy/store.go:92) is used without filepath.EvalSymlinks, so when abcd is invoked through the pinned PATH symlink the walk scans the symlink's ancestors (~/.local/bin, ~, /) and never finds hooks/ — a permanent phantom 'plugin root not resolvable' gap on exactly the layout ahoy install writes. Neither env var is set in a normal shell (CLAUDE_PLUGIN_ROOT exists only inside harness hook invocations), so the fallback is the path that matters. Fix is EvalSymlinks before the walk, plus a test invoking through a symlink watched failing first.
- iss-171The PATH-install detector and installer assume one blessed layout: binTarget defaults to /usr/local/bin/abcd (sudo territory abcd cannot assume) and symlink detection only recognises that exact target, so a working ~/.local/bin/abcd symlink install — the field-standard single-user location used by uv/pipx/rustup-class tools — reports symlink.missing, a false gap; the detector is itself running as abcd from PATH while reporting abcd not installed. Letting ahoy install 'fix' it would write a symlink to <plugin-root>/abcd without validating the target exists — a dangling symlink shadowing the working install. Redesign per fix-the-detector and no-sudo: detection scans PATH for abcd, resolves symlinks (EvalSymlinks, same seam as iss-170), classifies dev-shim/owned/foreign; install defaults to ~/.local/bin (create if needed), adopts an existing owned install in place, does system-wide dirs only behind an explicit --bin-dir flag failing loudly when unwritable, never escalates privileges, refuses to create a symlink whose target does not exist; '~/.local/bin not on PATH' becomes its own loud gap with the printed one-line fix (script-first: print the export line, do not auto-patch shell profiles as the first rung).
- iss-172abcd-managed repos need PR-queue hygiene when branch protection requires up-to-date branches: a queued auto-merge PR whose base moved sits BEHIND forever because GitHub auto-merge never updates branches. Two delivery rungs per basics-built-in/SOTA-delegated: (1) protocol-level now — after arming auto-merge, poll mergeStateStatus and run gh pr update-branch on BEHIND (works with the agent's own token, CI triggers normally); (2) scaffolded CI later — abcd scaffolds an update-branch workflow into managed repos, which requires a PAT/GitHub-App secret because the default GITHUB_TOKEN's pushes do not trigger workflows (the recursion suppression trap), or points at a merge queue where the plan allows. Same scaffolding family as itd-93's release gate; same merged-work-hygiene family as itd-95.related itd-107 · related itd-2610261025516272
- iss-173three-tier-layout's local-artefact placement check matches exact names directly under a committed tier only — residual evasions flagged at review: a nested artefact (a NEXT.md one directory below a tier root), a NEXT.md at the .abcd/ root itself (one directory off the modelled incident), and lowercase name variants on case-sensitive filesystems all pass clean. Widening (depth, roots, case folding) must not start flagging legitimate tier content.
- iss-174mergeDomain replaces a domain's recall and rules arrays wholesale, so a repo that overrides either array silently withholds every later security upgrade to the bundled defaults: internal/core/rules/rules.go copies the override array over the base one instead of unioning, with no schema bump and no notice, so a repo that pinned PII recall or PII rules before iss-156 keeps the old set and never sees the new network keywords or the never-commit-network-identifiers rule line. Per-field merge is the documented and wanted behaviour for state, but for security-bearing arrays the quiet outcome is a stale ruleset that looks current. Options to weigh: union rather than replace for recall/aliases (additive, no loss), a distinct replace-vs-extend marker in the override, or at minimum a loud diagnostic in abcd rules naming which bundled entries an override is withholding. First activated by the iss-156 PII upgrade, which is why it is captured now. Prior disposition to weigh when triaging: iss-66 (resolved, rules-loader trust boundary) document-accepted the adjacent risk that an override can weaken a default guardrail domain (its P15); this entry is the distinct case of an override silently withholding later upgrades rather than deliberately silencing a domain.
- iss-175abcd capture writes ledger files without a trailing newline: 170 of 174 files under .abcd/work/issues/ lack one, including entries the verb writes today. The writer is the source; individual files fixed by hand only mask it. Found while fixing the iss-156 entry's EOF during review follow-up.
- iss-176The public banned-names family lives at .abcd/docs-lint.json, which the installed .gitignore fence ignores under visibility public, so the layer that claims to be committed and CI-enforced is untracked exactly where public exposure is the risk
- iss-177ahoy install reports every written artefact as an absolute filesystem path, so an install receipt pasted into an issue or a transcript carries the developer's home directory and username
- iss-178Autonomous cloud runs in sibling repos leaked harness attribution footers and a live session URL into public GitHub artifacts: the harness auto-appends a 'Generated with' footer plus a session link when a PR or issue is created, overriding the repos' Assisted-by-only attribution policy (commit messages stayed clean; the leak surface was PR bodies and issue comments, plus GitHub's public edit history retaining the pre-scrub revision). Leak shape only - no session ids reproduced here. Two remedies needed: (a) every autonomous routine prompt must ban session URLs and harness footers in public text AND mandate a post-create re-read-and-strip of every PR/issue/comment the loop creates, because the append happens outside the model's own text; (b) abcd should detect the class - session-URL and harness-footer patterns belong with the shared privacy pattern set (iss-154 family / itd-74 banlist territory) so audit and docs-lint flag them in any committed or posted text.related itd-107 · related itd-152
- iss-179adr-29 and adr-25 still narrate adr-6 in prose, but adr-6 is in no store and is absent from all git history (the ADR set landed in one import commit; 0004/0006/0008/0014-0018 were never migrated, and every one but 0006 is accounted for by a successor's supersedes). adr-29 states in its own body that adr-6's decision stands and that adr-29 does not supersede it, so the supersession vocabulary cannot record it and neither ADR body should be rewritten to paper over it. iss-39 closed the machine-readable half (the two related_adrs entries, and the two brief pages that cited it). The surviving prose sites are adr-29 lines 24, 39, 43, 56, 60, 63, 71 and adr-25 lines 51, 80; adr-29's line 43 in particular still says it "links to ADR-6" now that the frontmatter link is gone, which is the residual made legible rather than hidden.
- iss-180itd-85 shipped whole but still sits in intents/drafts/: abcd audit ships with all five v1 rules, the tri-state exit and the prepare-this-repo wiring the intent scopes, yet the intent was never promoted, so the record cannot say the capability is delivered. Promotion is blocked on the shipped/ schema, which requires a non-null spec_id and an impact value the intent has never carried (there is no spc-N for the audit verb). Disposition: mint or retro-link a spec via /abcd:intent link, set impact, run the fidelity review, and move drafts/ -> shipped/. Until then the v0.2.0 CHANGELOG entry describes abcd audit without citing itd-85 (iss-41).
- iss-18106-lint.md section 1 (the lint-code namespace) is a catalogue of a predecessor project's Python-era implementation — the `IL001`–`RC007` code families and the class names they cite (`IntentLinter`, `BundleLinter`, `PromptLinter`, `SpecLinter`) describe code this repo does not carry. Re-filed here from iss-37 (2026-08-03 maintainer disposition), which is re-scoped to its three doc-claim instances.
- iss-182Three build-plumbing comments still describe the pre-push gate and CI by an older, smaller shape. Same class as iss-37 (claims must match reality), in living files its re-scope does not cover, and no ledger entry records them until now. The fix direction is the same bar: state what actually runs, verified against the recipe or workflow beside the comment.
- iss-183The blanket `.abcd/` exclusion claim that iss-43 corrected in the README survives across the record. Recorded rather than fixed there, because the disposition scoped iss-43 to one README line.
- iss-184guard tokenizer heredoc misparse: an unquoted arithmetic left-shift with an identifier operand (e.g. `$((1<<shift))`) is misparsed as a here-document start by isDelimStart (tokenize.go:206, accepts any word starting with a letter/underscore) plus readHeredocDelim (tokenize.go:249, terminates the delimiter word on ')'). skipHeredocBodies (tokenize.go:264) then scans for a line equal to the bogus delimiter, finds none, and silently swallows every subsequent line of the command before it reaches command position. A dangerous command on a later line (git push --force, rm -rf, gh repo delete, etc.) is never seen by Registry.Check and the guard returns VerdictAllow with no error — a silent fail-open, not the loud could-not-answer path the shim reserves for unparsable input. Confirmed live via both CLI front doors (internal/surface/cli/guard.go: guard check and guard hook). The literal-digit form (1<<20) is unaffected; only identifier/variable operands trip it. Reproducing test: internal/core/guard/tokenize_test.go, TestArithmeticShiftByIdentifierIsNotAHeredoc.
- iss-185scanner leaves a second back-to-back secret token undetected and unredacted, and the fail-closed residual re-scan reports clean anyway. Fixed-length token patterns (e.g. github_pat_ at patterns.go:93) require a leading \b; when two same-family tokens are concatenated with no separator, the first regex match consumes bytes up through the second token's first byte, leaving word/word at the junction so the second token's \b can never match. ScanText (scanner.go:274) therefore returns only one finding. Redact's fingerprintSpan keeps 2 raw alnum bytes at the tail of the masked span (scanner.go:393), so the junction stays word/word after redaction too — the second token survives completely raw in the output. Because the boundary never recovers, history.Capture's stage-two residual check (history.go:159, blockingResidual) re-scans the redacted text, finds nothing, and writes the record to disk with a live secret still in it, directly violating history's documented fail-closed guarantee ('a stored record can never contain a live secret'). Distinct from iss-65 (Finding.MarshalJSON snippet cross-leak in serialized findings, already fixed) — this is a ScanText/Redact detection gap in the scan pass itself. Reproducing test: internal/adapter/scanner/, TestConcatenatedSecretsBothDetected.
- iss-186capture.commitTransition writes the destination file before removing the source (workflow.go:255-273); a non-ENOENT os.Remove(src) failure (EPERM/EROFS/EIO — e.g. a read-only remount or restrictive ACL on the source status dir) returns an error after dst already landed, with no rollback of dst. The same issue id is now present in two status directories (e.g. both open/ and resolved/). findIssue (alloc.go:383) then rejects any further transition on that id as ErrDuplicateIssueID, so it can never again be resolved or wontfixed on a healthy filesystem — no repair verb exists; recovery requires manually deleting one copy. scanLedger-based reads (List/Status) do not dedupe either, so the id also double-counts. Confirmed with a real non-ENOENT unlink failure (ext4 immutable attribute on the source dir, which blocks unlink even as root, unlike chmod). Reproducing test: internal/core/capture/workflow_test.go, TestTransitionRemoveFailureDoesNotStrandIssueInTwoDirs.
- iss-187rules.Merge panics with 'assignment to entry in nil map' (rules.go:193) when the base RuleSet's Domains field is nil and the overlay has at least one domain key. cloneRuleSet (rules.go:524) only allocates out.Domains when the source map is already non-nil, so a base like RuleSet{SchemaVersion: 1} (a Validate-accepted, valid zero-ish value) crashes on merge, contradicting Merge's own doc comment ('New domain keys are added') which promises no such precondition. The sibling loader guard.Merge (internal/core/guard/config.go:77-79) gets this right, explicitly allocating out.Entries when nil before the same kind of loop — Merge is simply missing that guard. Not reachable today: RuleSet.Load's only call site passes Merge(Defaults(), over), and Defaults() always has non-nil Domains, so this is a latent exported-API contract defect rather than a live crash — it becomes live the moment any caller merges onto a non-Defaults() base (e.g. a future multi-tier overlay starting from an empty RuleSet). Reproducing test (recover-guarded): internal/core/rules/, TestMergeNilBaseDomainsAddsNewKeys.
- iss-188scanner adjacency recovery misses greedy over-consumption in open-ended-quantifier secret patterns. iss-185's fix (scanAllPatterns, scanner.go) recovers a second token that immediately abuts a first with no separator ONLY when the first pattern is fixed-length (its match always ends exactly where the second token begins, so probing every pattern's boundary-free variant at that one byte offset is sufficient). A pattern whose quantifier is open-ended (e.g. `\bghp_[A-Za-z0-9]{36,}`, `\bsk-ant-[A-Za-z0-9_-]{40,}`, `\bsk_live_[A-Za-z0-9]{20,}`) instead greedily consumes as many class-matching bytes as are available, including a following token's own leading bytes when those happen to fall inside the same character class — shifting the true junction earlier than the reported match end, before scanAllPatterns' adjacency probe ever runs. Concrete repro: `"ghp_" + strings.Repeat("a",36) + "ghp_" + strings.Repeat("b",36)` — the first `ghp_` pattern's `{36,}` class run consumes the 36 a's AND the second token's leading "ghp" (all alnum), stopping only at the second token's `_` (not in `[A-Za-z0-9]`); ScanText reports exactly ONE finding covering `ghp_aaaa...aaaghp`, and the second token's `_bbbb...bbb` tail survives Redact completely raw with the fail-closed residual re-scan reporting clean — the same "can never contain a live secret" violation iss-185 was filed for, just for the open-ended-quantifier pattern family instead of the fixed-length one. Distinct from iss-185 (closed): that fix's mechanism (probe every pattern at a match's reported end) is necessary but not sufficient — this needs a bounded backward search (shrink the greedy match's end toward its start, checking at each candidate cut whether the shortened match is still valid for its own pattern AND some pattern's boundary-free variant matches there) without becoming O(line length) per match, since these patterns' matches can legitimately be very long (base64 blobs, minified files) and an unbounded backward scan across every byte would be a new resource-exhaustion risk on exactly the kind of large single-line input a secret scanner must handle. Surfaced by an adversarial pre-PR security review of iss-185's fix (bug-hunt loop round 3), not by the round's own hunt; not fixed in that PR to keep its diff scoped to the exact bug iss-185 named and to avoid shipping an unbounded-cost search under review pressure. Affected pattern families: github_pat (ghp_/ghs_/gho_/ghu_/ghr_), anthropic, openai_project, openai_svcacct, stripe_live, stripe_test, slack, jwt_shaped — every bundled pattern with an open (`{n,}`) rather than fixed (`{n}`) quantifier.
- iss-189adjacency probe's trailing \b can be satisfied by the window edge instead of real content, causing a spurious over-redaction. scanAllPatterns (scanner.go) slices the line to a bounded window (line[end:min(end+512,len(line))]) before running each pattern's adjacencyProbe, to keep one probe attempt's cost constant regardless of what follows (iss-185's fix). Some probes retain an internal trailing \b of their own (e.g. net_lan_hostname's `\b` at the very end of its alternation) which normally requires a real non-word character (or true end of string) after the match. But when the probe is truncated to the window, "end of window" is treated by the regex engine exactly like "end of string" — so if the window happens to end immediately after what LOOKS like a complete hostname/token, the trailing \b is satisfied by the artificial window boundary rather than by real surrounding content, even though the FULL, untruncated line would not have matched there (the real next byte continues the token). Concrete repro: a line built as `"AKIA"+16*"Q"` (a confirmed match, establishing the probe's junction) + 506 filler bytes + ".local" + "zzz" — the window (512 bytes from the junction) ends exactly after "local", so net_lan_hostname's probe matches "b...local" (satisfied by end-of-window) even though the real line continues with "zzz" right after ".local", meaning the FULL line's own un-windowed net_lan_hostname pattern would NOT match there at all (no real word boundary follows in the actual text). Impact: a spurious net:lan_hostname finding (warn severity only, not hard_fail) causes Redact to needlessly rewrite up to 512 bytes of legitimate content as fingerprinted/starred output — not a security leak (over-redaction, not under-redaction) but a correctness/usability defect: legitimate file content gets mangled on a contrived but reachable input shape. Suggested fix (from the reviewer that found this): when a probe match's end lands exactly at the window's limit AND limit < len(line) (i.e. the window was actually truncated, not naturally at the line's end), re-run that one probe against the full, untruncated line[end:] before accepting the match — paying the larger cost only in this rare edge case rather than on every probe. Found during a merge-gate correctness review of iss-185's PR (bugfix/iss-185-scanner-adjacent-secret-boundary-bypass); non-blocking (contrived input, warn-severity-only impact), so not fixed inline — captured for its own verify-and-fix cycle.
- iss-190scanner adjacency recovery is capped by maxAdjacencyProbeWindow, so a recovered token longer than the window is truncated — and the truncation can break the recovery CHAIN, hiding a third abutting token entirely. probeAt (scanAllPatterns, internal/adapter/scanner/scanner.go) runs its anchored probe against line[at:at+maxAdjacencyProbeWindow] (512 bytes), so a recovered open-ended match longer than that is recorded with an artificial end at the window edge. Two manifestations. (a) Known and accepted since iss-185: the recovered token's far tail past the window stays raw in Redact's output; the token's prefix is still masked, so this is a partial-redaction trade, not a total miss. (b) NEW, found by two independent adversarial reviews of iss-188's fix: because the artificial end does not align with the token's real end, the next iteration's probeAt(m.end) and stolenJunctions both start from a byte offset that is inside the token rather than at its junction, so the chain that would otherwise unwind a run of three or more abutting tokens breaks — the third token becomes entirely invisible, not merely truncated. Repro: line := "ghp_" + strings.Repeat("a",36) + "ghp_" + strings.Repeat("m",600) + "ghp_" + strings.Repeat("z",36) yields exactly 2 token:github_pat findings where an unbounded search would find 3; the third token's 36 raw bytes survive Redact and the fail-closed residual re-scan reports the output clean. A sharper variant of (a) affects jwt_shaped specifically: its regex requires two literal '.' separators, so a JWT-shaped token whose header and payload together exceed the window has NEITHER separator inside the probe's slice and the anchored probe finds no match at all — the token is missed entirely rather than truncated, e.g. a fixed-length match immediately followed by a JWT whose first two segments total more than ~502 bytes. This is NOT a defect introduced by iss-188's backward search; it is the same pre-existing maxAdjacencyProbeWindow trade-off from iss-185, now reachable through a second code path because the backward search feeds more candidates into probeAt. Fixing it properly needs a different mechanism (a growing or adaptive window, or re-probing chained from a recovered match's real end) that must not reintroduce the unbounded per-match cost the window exists to prevent — the exact risk iss-188's own ledger entry warned against. Deliberately not folded into iss-188's fix pass to keep that diff scoped to the confirmed junction-search defect.
- iss-191junctionProbe's compile fallback turns stolenJunctions from a bounded candidate walk into a per-byte one, a latent cost cliff. junctionProbe (internal/adapter/scanner/scanner.go) builds one combined alternation over every pattern's boundary-free body; if that alternation fails to compile it falls back to regexp.MustCompile(`(?s).`), which matches at EVERY byte offset. The fallback was chosen so the candidate generator can over-produce but never under-produce — correct for detection, but it changes stolenJunctions' cost class: instead of one wholeMatch validation per real candidate junction in the backtrack window, wholeMatch runs once per byte offset in the window, and each of those validations is itself proportional to the match's own length (it re-runs the anchored probe over line[m.start:cut]). Cost per match goes from O(window) validations to O(window x match length) work. A reviewer measured roughly a 500x slowdown substituting the fallback directly — 4.21s against 8.25ms on one 200KB match. Not reachable with the current bundled pattern set: every bundled body alternates cleanly, and triggering the compile failure needs a pathological custom .abcd/config/pii.json override whose added pattern makes the joined alternation invalid (the per-pattern regexes are each compiled and validated on merge, so this is hard but not provably impossible to reach). Latent rather than urgent. Options if it is ever worth closing: cap the fallback's candidate count the way the window caps the search, drop patterns from the alternation one at a time until it compiles rather than abandoning the whole set, or mark the scanner unavailable (fail-closed) when the combined probe cannot be built — the last is consistent with how the package already treats a config fault.
- iss-192Brief surface chapters lag the shipped surface: the v0.4.2 release-gate crosscheck (full tier, 22 checkers) found 26 discrepancies across 01-ahoy, 04-launch, 05-intent, 07-memory, 15-prepare-this-repo, 16-audit and 05-internals/08-skills — banlist missing from the fourteen-command roster, hooks/bootstrap.sh absent from every hook enumeration, the shipped citation-baseline dry-run gate undocumented, ahoy's envelope/render enumerations missing banlist/guard-detail/citations fields, intent §6 attributing unshipped acceptance-criteria/bundle/supersession checks to the record lint, prepare-this-repo's stale commands/abcd/ layout and undocumented identity phase, audit's privacy-hygiene row understating network-identifier scanning, and memory's bare-render/schema/spec-range drift. Full finding list with evidence: the iss35-brief-surface-crosscheck receipt for the v0.4.2 content commit under .abcd/work/reviews/. Same residue class as iss-152 (v0.4.1).
- iss-193A managed repo commits under whatever identity git happens to resolve, and when
- iss-194Release retention is documented in the present tense but has never run: the newest-per-line policy in brief/04-surfaces/04-launch.md:134 and the release glossary entry describe pruning as operating behaviour, and internal/core/launch/retention.go:30 implements it exactly, but nothing executes it. internal/core/launch/ship.go:41 stops before the network ('the real GitHub Release + SLSA + tag push + retention prune are a later phase'), and .github/workflows/release.yml — which publishes every release this project has actually cut — carries no retention step at all. The brief's own phase note schedules the prune as itd-70, unshipped. Same implemented-but-never-run class as iss-183, and found the same way: by reading the record against the live surface. Live evidence, 2026-08-07: six releases exist; the real preview keeps v0.1.0, v0.2.0, v0.3.0, v0.4.2 and would prune v0.4.0 and v0.4.1, so the repository's own release list contradicts the prose. Scope here is the doc-currency half only — state that the policy is computed and previewable but not yet enforced, on the channel-truthful pattern iss-183 established; wiring the prune is itd-70 and is not assumed by this item. Maintainer disposition (2026-08-07): v0.4.0 and v0.4.1 are deliberately left in place rather than pruned by hand, so itd-70 has a live fixture to exercise on arrival — the first real prune should be the shipped mechanism's, not a manual one. Related observation, possibly separable: internal/core/launch/dryrun.go:126 discards the error from GitExistingTags, so a shallow or tagless checkout yields an empty existing set and the retention preview reports nothing to prune — indistinguishable from a genuine nothing-to-prune. Reproduced in a shallow clone during this investigation before tags were fetched.
- iss-195The scanner's rigid/open-ended heuristic sends every IPv4 and IPv6 match through stolenJunctions' backward search, a measurable cost regression on ordinary log content. stolenJunctions (internal/adapter/scanner/scanner.go) skips its bounded backward search only for patterns whose match cannot be one byte shorter; net_ipv4 and net_ipv6 (internal/adapter/scanner/network.go) are variable-length, so every address they match in ordinary content enters the search — no custom config, no compile-failure fallback needed (that latter, narrower mechanism remains iss-191's scope and still does not trigger on the bundled set, whose combined alternation compiles cleanly). Measured on identical content, current main (bddb6fa) vs the tree immediately before the iss-188 machinery (eb61acd), 100-line ~12KB documents, all identifiers reserved documentation values (RFC 3849/5737/7042): neutral content 1.0x; one MAC per line 3.6x slower (net_mac itself classifies rigid, but ipv6Re also matches MAC-shaped colon-hex and that overlapping match is open-ended); one compressed IPv6 per line 1.9x; one MD5-style SSH fingerprint per line 23x; one dense colon-hex known_hosts-style line 27x. Because Skip/SkipAt reserved-range filtering runs AFTER scanAllPatterns, reserved addresses that are never reported still pay the full search cost. The iss-188 review also demonstrated a correctness angle on this same path: duplicate hard_fail findings manufactured for a single compressed IPv6, reproduced on this repo's own tracked fixtures (internal/core/memory/memory_test.go, internal/urlguard/urlguard_test.go). Candidate directions: exempt network-class patterns from the backward search where a stolen-junction leak is not plausible for them, or short-circuit when the only patterns whose bodies can match in the backtrack window are network-class; whether the residual cost is then a documented trade-off is a maintainer call. Split out of iss-191 per maintainer ruling (2026-08-07); benchmark method and full table recorded here because the scratch artefacts under .abcd/.work.local/ are ephemeral.
- iss-200guard's env wrapper table listed -S/--split-string as a value-owning flag for the SEPARATE-TOKEN spelling only ('env -S git push --force origin main'), but GNU env -S/--split-string also accepts the value glued to the flag ('env -Sgit push --force origin main', 'env --split-string=git push --force origin main'), which re-splits identically and executes identically; a fix attempted in bug-hunt loop round 9 (bugfix/env-split-string-guard-bypass) closed only the separate-token form and was BLOCKed at pre-PR review by both an independent correctness reviewer and an independent security reviewer, who each independently reproduced that the glued forms remain a complete, silent bypass of every guard blocker on the live PreToolUse path; suggested remediation (from both reviewers, converging independently): in commandOf/skipWrapperArgs, treat -S/--split-string as a value-owning env flag in all three spellings — the exact separate-token form (-S as its own token, value in the following token), the glued form (-S<value>, len>2), and the --split-string=<value> form (value non-empty) — and in every case read the first word of <value> as command position, rather than either treating the whole glued token as a consumed wrapper flag or skipping the following token outright in the separate-token case — no nested re-tokenizing required, contained to the same two functions
- iss-201abcd guard hook reads its PreToolUse stdin payload via a bare LimitReader with no overflow check, so a payload padded past the 1 MiB cap (e.g. a blocked command with a trailing shell comment full of junk) is silently truncated, breaks JSON parsing, and routes to the fail-open-loud path (exit 1, command runs) with a diagnostic that misleadingly blames the host ('not readable JSON') instead of reporting the actual cap overflow; the sibling check verb's guardCandidate already reads cap+1 specifically to detect and refuse this. Independently verified: threshold is sharp and deterministic (cap-1 blocks, cap+1 fails open), always a loud (not silent) fail-open, exploitation cost bounded by needing >1 MiB of attacker-influenced content inside one tool_input
- iss-202scanner.New reads the per-repo .abcd/config/pii.json override with a bare os.ReadFile — no O_NOFOLLOW, no size cap, no regular-file check — unlike every sibling trust-boundary config reader in this codebase (guard.Load, rules.Load, banlist private store) which goes through fsutil.ReadGuarded; a FIFO planted at that path hangs the read forever and a symlink to a device file (git-committable, mode 120000, no local write access needed) grows the read unbounded toward OOM; reachable automatically via the SessionEnd hook's history capture, which also holds an unbounded history.repoLock flock across the hang, permanently wedging transcript capture for that repo; this is the same bug class already fixed once for ahoy.Detect under iss-97. Independently verified: FIFO hangs past 3s deadline (control: no-config-file case returns in 0.01s), /dev/zero symlink accumulates ~137 MiB/s, causal fix test (swap to fsutil.ReadGuarded) confirmed both cases resolve
- iss-203audit's privacy-hygiene rule guards on 'if sc, err := scanner.New(ctx.RepoRoot); err == nil' expecting a fallback to the built-in pattern set on error, but scanner.New never returns a non-nil error — every degradation path (unreadable/unparseable/uncompilable pii.json override) returns unavailable=true with a nil error instead — so the guard is always true, the documented fallback branch is dead code, and the rule never calls sc.Unavailable(); a broken per-repo severity override (malformed JSON, a directory at the config path, or an uncompilable override regex) silently drops the repo's raised severities and downgrades the audit exit code from 2 to 1 with zero finding or diagnostic explaining why, unlike history.Capture and the CLI identity path which both check Unavailable() explicitly on the same scanner. Independently verified via two-fixture test (valid override raises severity to error/exit-2; broken override silently drops to warn/exit-1 with no diagnostic) for all three degradation branches (malformed JSON, directory at path, uncompilable regex)
- iss-204hooks/hooks.json puts bootstrap.sh and the two binary-backed SessionStart hooks in ONE event group and relies on list order, but the harness runs all matching hooks in PARALLEL — the Claude Code hooks reference states verbatim 'All matching hooks run in parallel.' spc-21 asserts the opposite: 'Ordering within one event's hook list is preserved by the harness, so the binary-backed session hooks run after the bootstrap in the same event.' That warrant is false, and it is load-bearing. On a fresh install the two gated hooks evaluate [ -f "$CLAUDE_PLUGIN_ROOT/abcd" ] while bootstrap.sh is still downloading the ~10.7MB release binary (timeout 240), lose the race, and both print 'the plugin binary is not installed'. Observed on the first manual marketplace install (2026-08-10): both errors printed BEFORE bootstrap's own success notice, which is direct evidence of parallel execution. Consequence is not only noise — 'hook prompt-router-reset' and 'hook session-start' genuinely do not run for that session, and itd-105 AC#1 ('every hook executes successfully — no No such file or directory, no unguarded-shell warning') fails on every fresh install AND every plugin update, since each update lands in a fresh commit-stamped cache directory with no binary. Fix direction: collapse the three entries into ONE SessionStart command that runs bootstrap.sh and then the two binary calls in a single shell, so the sequencing is owned here rather than assumed of the harness.blocks iss-208
- iss-205Every one of the 17 files under commands/ resolves the binary as bare 'abcd' on PATH, with a documented fallback to 'go run ./cmd/abcd'. None of them mentions ${CLAUDE_PLUGIN_ROOT} — grep confirms zero occurrences across commands/. But itd-105 decided 'PATH: deferred to ahoy', so a by-the-book marketplace install provisions the binary ONLY into the plugin root and leaves nothing on PATH. The two halves therefore still do not meet: bootstrap installs a checksum-verified binary that no command can see. Observed on the first manual install (2026-08-10): 'which abcd' reports not found, and bare /abcd fell through to the source-build path — 54s, requiring a Go toolchain, and succeeding only because the marketplace clone happened to be on disk. On a clean machine without Go the entire plugin command surface is non-functional despite a healthy binary sitting in the plugin root. This directly contradicts itd-105's own premise: 'Nobody clones the repo to use abcd: the binary is all a user needs.' The fix is supported and cheap — the plugins reference confirms ${CLAUDE_PLUGIN_ROOT} substitutes in 'Skill and agent content: anywhere the placeholder appears'. Put "${CLAUDE_PLUGIN_ROOT}/abcd" first in the resolution order in all 17 command files, PATH second, 'go run' last.related itd-108
- iss-206The version-skew notice promised by itd-105 ('Given an installed surface newer than the newest published binary, when a session starts, then the skew is surfaced') can never fire, and fails silently. itd-105's warrant says the harness names each plugin cache directory for the commit it was cloned from; that holds only as a 12-character SHORT sha. Observed .binary-meta from the first manual install (2026-08-10): plugin_root_basename=872f0a1e6aab, which is exactly 'git rev-parse --short=12 HEAD', and plugin_sha=unknown. hooks/bootstrap.sh gates plugin_sha on exactly 40 hex chars, and internal/surface/cli/skew.go resolvedSHA() requires 40 again, so plugin_sha is permanently 'unknown' and binarySkewNotice() returns "" forever on every machine. This is precisely the failure the comment at hooks/bootstrap.sh anticipated and armed a diagnostic for — recording the raw ungated plugin_root_basename beside the gated field so that 'why has the skew notice never fired' has an answer in the file rather than only in a comment. The diagnostic worked exactly as designed; the gate is what is wrong. Fix direction: accept 7-40 hex in both places and compare on the shorter value's prefix length, since one side is a short sha and the other a full one.related itd-108
- iss-207The one instruction that resolves the no-binary-on-PATH state cannot be run in that state. hooks/bootstrap.sh's success notice ends 'For the abcd command in your own terminal, run `abcd ahoy install` once.' and README.md repeats it: 'run `abcd ahoy install` once to put the plugin-root binary on your PATH.' But abcd is not on PATH — that is exactly the condition the sentence addresses — so the command as written fails with 'command not found'. Observed consequence on the first manual install (2026-08-10): the agent, unable to run the printed command, invented 'cd ~/.claude/plugins/marketplaces/abcd-marketplace && go run ./cmd/abcd ahoy install' and told the user to run that instead — a source-build instruction reaching into the harness's plugin cache, which is not the documented install path and requires a Go toolchain. Fix direction: print the absolute plugin-root path in the notice (the script already holds it as $binary) and give README the same concrete form, so the sentence is copy-pasteable in the state it describes. Related to iss-205, which is the same root confusion on the command surface.
- iss-208A successful bootstrap install is rendered to the user as a third 'SessionStart:startup hook error', indistinguishable from the two genuine failures above it. hooks/bootstrap.sh's notice() exits 2 deliberately, and its comment gives the sound reason: a SessionStart hook's stdout becomes model context, while only a non-zero exit puts stderr in front of the human. But the harness renders ANY non-zero SessionStart exit as a '<hook name> hook error' notice — the docs confirm exit 2 'renders in the transcript as a <hook name> hook error notice, the same way a non-blocking error does'. So there is no 'notice' channel distinct from 'error', and the checksum-verified happy path is labelled a fault. Observed on the first manual install (2026-08-10): three consecutive hook-error lines, of which the third was the install SUCCEEDING. Fix direction: fold this into the single chained SessionStart entry proposed in iss-204 and lead the visible first line with the success, since the transcript shows only the first line of stderr; the honest-failure posture for the genuinely-no-binary window is unaffected.blocked by iss-204
- iss-209Every dependabot PR that bumps a pinned action in .github/workflows/release.yml or auto-release.yml fails TestSelfScaffoldParity and can never go green on its own. Observed on PR #211 (actions/attest 4.2.0 -> 4.2.2): 'release.yml: abcd rendering is not byte-identical to the committed workflow', failing check on BOTH platforms while gitleaks, record-lint, smoke and zizmor all pass. Root cause: the committed workflow is a GENERATED artefact. internal/core/launch/scaffold/templates/release.yml.tmpl:270 and .github/workflows/release.yml:248 both pin actions/attest@f7c74d28b9d84cb8768d0b8ca14a4bac6ef463e6 (v4.2.0), and TestSelfScaffoldParity asserts the two are byte-identical so that abcd's own release dogfoods the machinery a managed repo receives. Dependabot edits only the derived file, so parity breaks by construction on every such bump — this is recurring and structural, not a one-off. The obvious fix (bring the scaffold template into dependabot's scope) is NOT AVAILABLE: the github-actions ecosystem discovers only .github/workflows/*.yml and composite action.yml manifests under the configured directory, and no package-ecosystem scans an arbitrary .tmpl under internal/. .github/dependabot.yml today declares gomod and github-actions, both at directory /. Note also the wrong-direction trap: auto-rendering the scaffold on a dependabot PR would REVERT the bump, since render flows template -> workflow. Options, none adopted: (a) make the parity failure self-explaining — the message says 'not byte-identical' and prints the first diff but never names the template path or says 'an action bump must be applied to the template too', which is the cheapest change and matches the loud-staging principle; (b) propagate the bump backwards — a job on dependabot PRs that applies the changed pin to the template and commits to the bot branch, which is the durable fix but is custom automation writing to a bot branch; (c) drop these two workflows from dependabot's scope and manage their pins by hand from the template, trading automation for consistency. Secondary risk worth weighing: a permanently-red dependabot PR trains the maintainer to discount red CI on exactly the PRs where CI most needs to be trusted.related itd-2609301020001595
- iss-210A lone token that a user plausibly expects to be a subverb, but which is not one, is swallowed as free text and WRITES A RECORD on both mutating verb families — 'abcd intent status' files drafts/itd-N-status.md and 'abcd capture status' files issues/open/iss-N-status.md, each exit 0. Verified 2026-08-11 by building HEAD into a scratch repo and running both. This is a residual hole in the unrecognized-input-never-writes rule (iss-29) that iss-104's fix does not cover: suspectedTypoedSubcommand (internal/surface/cli/cli.go:2000) fires only on a NEAR-MISS of a real subverb, bestDist initialised to 3 so only edit distances 1 and 2 refuse. It is deliberately high-precision so a genuine multi-word prose title whose first word resembles a verb still files — the controls confirm that half works: 'capture resovle iss-1 note' and 'intent paln itd-1' both exit 2 with a did-you-mean and write nothing. But 'status' is edit distance >=4 from every real subverb in either family (intent: new/plan/ready/link/review/ingest; capture: list/resolve/wontfix), so the guard never engages and the word becomes the record title. The class is any plausible-but-nonexistent subverb far from every real one; 'abcd intent list' happens to be caught only by the accident that levenshtein(list,link)=2. NOT an intent-vs-capture asymmetry: the two behave identically, so a fix must land on the shared guard, not on the intent path alone. Fix direction: edit distance is the wrong discriminator for this class. A LONE single token with no other args is never a useful issue or intent title, so treat it as an unrecognized subcommand regardless of distance — refuse, exit 2, write nothing, name the real subverbs, and say how to force prose (quote it, or add words) so the terse-free-text escape hatch stays open. Detector: extend intent_surface_test.go and the capture surface test with a lone-token case per mutating verb family asserting exit 2 and zero records written, watched fail before the change; the existing near-miss cases must keep passing, and a multi-word prose title must still file. Impact on resolve is 'fix' at best and arguably 'breaking' — an unattended script or loop that shells 'abcd capture <one-word>' expecting a file would start failing — so it is NOT additive-class. Standing risk this closes: any autonomous loop that shells a bare word into either verb silently grows the ledger with junk records that a human must later triage.
- iss-211Multi-project adoption raises the priority of itd-91 (AI-attribution preference) and itd-92 (branch-protection verification) from 'good hygiene' to 'the product claim'. What abcd-cli has today is its OWN answer hard-coded: scripts/check-attribution.sh names specific banned footers and a fixed required trailer, and .github/workflows/attribution.yml is a hand-written file in one repo. Neither is portable, which is exactly the gap itd-91 already states — a project adopting abcd inherits abcd's preference by reading its docs but has no first-class way to declare its own (Co-Authored-By, none at all, or house style). The durable home is a rule in internal/core/lint beside deliverystate, indexdrift and citations: reachable from CLI and plugin, run in any managed repo, reading a declared per-repo preference rather than a constant. Two further observations from the 2026-08-11 session. (1) SCAFFOLD IS THE DELIVERY MECHANISM. internal/core/launch/scaffold renders exactly three artefacts into a managed repo today (release.yml, auto-release.yml, the runbook); an attribution workflow becomes the fourth, so every managed repo inherits the gate from one template instead of someone copying a file. It would automatically gain the self-scaffold parity property — and with it the dependabot pin problem of iss-209, which the sync tool merged in PR #215 already handles. The work just landed is the delivery rail for making this portable. (2) ITD-92 GATES EVERYTHING ELSE. A scaffolded gate that no repo adds to its required status checks is decoration; across N repos the required-check wiring and the enforce_admins policy stop being settings a maintainer clicks and become policy abcd asserts and verifies. That makes itd-92 arguably the higher-leverage of the pair: it is what converts every abcd-scaffolded check, present and future, from advisory into binding. itd-92's own capture note already says this in miniature — 'captured 2026-07-17, the day abcd-cli's own main was protected by hand — work the tool should carry for every repo it manages'. Both intents are still ungrilled drafts.
- iss-212The attribution gate merged in PR #217 is dead scaffolding until it is added to the branch's required status checks, and it is not there. Verified 2026-08-11 after the merge: main's required contexts are still check (macos-latest), check (ubuntu-latest), gitleaks, record-lint, smoke, zizmor — no "attribution" — and enforce_admins is false. The workflow runs and reports green on every pull request, so the repo now LOOKS gated while nothing is actually blocked; that is the false green the loud-staging principle refuses, and it fails the "wired or it isn't done" boundary the same way (no dead scaffolding). The gate was built precisely because the maintainer said it must be certain they do not have to check for attribution drift by hand; in its current state that certainty does not exist, and the appearance of it is worse than the previous honest absence.
- iss-213Several agents sharing ONE git worktree silently invalidated a verification result and came close to losing committed work. Observed repeatedly during the 2026-08-11 install-test round, in a repo that is about to run more agents, not fewer.related itd-148
- iss-214The attribution gate refuses a legitimate, exact model identifier: TRAILER_RE ('^Assisted-by: [A-Za-z][A-Za-z0-9._-]*:[A-Za-z0-9._-]+$', scripts/check-attribution.sh) has no bracket in its character class, so 'Assisted-by: Claude:claude-opus-5[1m]' FAILS while 'Assisted-by: Claude:claude-opus-5' passes. Verified 2026-08-11 by running the script's own body check over seven trailer variants. The bracketed form is not a typo — it is the exact identifier of the 1M-context Opus variant, and 'git log' shows 33 commits in this repo's own history already using it (claude-opus-5[1m] x33, claude-opus-4-8[1m] x5). The convention AGENTS.md:132 and CONTRIBUTING.md:31 state is to name the model VERSION, so an agent that reports its precise identifier is following the prose and failing the gate. Consequence is a PR blocked mid-run for correct disclosure, and the obvious workaround — silently truncating the suffix — degrades the very disclosure the trailer exists to provide, since [1m] distinguishes a materially different model configuration. This will bite an autonomous multi-agent run, where the failure surfaces as a red gate on a PR nobody is watching. Fix direction: widen the version half of TRAILER_RE to admit a bracketed context suffix (e.g. allow a trailing '\[[A-Za-z0-9._-]+\]'), rather than asking contributors to drop it; and add the two historical forms to the script's own test corpus so the regex is proven against identifiers actually in use rather than only against the happy path. NOT a defect, recorded here so it is not re-raised: the gate's rejection of a bare 'Assisted-by: Claude' with no version (9 commits in history) is CORRECT — the convention requires a model version, and those nine commits are non-conformant record rather than gate error. History is not re-checked; the gate runs on pull requests only.
- iss-215The attribution gate is provider-asymmetric: its POSITIVE check is vendor-agnostic while its NEGATIVE check and the prose it enforces are Claude-specific, so the gate stops the failure it was built for only as long as the assisting model is Claude. Verified 2026-08-11 against scripts/check-attribution.sh: TRAILER_RE accepts any '<Vendor>:<version>' pair, so 'Assisted-by: OpenAI:gpt-5' and 'Assisted-by: Google:gemini-3' both PASS — correct and desirable. But GENERATED_RE bans only 'Generated with [', the robot-emoji 'Generated with', and 'Co-authored-by: Claude' / 'Co-Authored-By: Claude', so a body carrying 'Co-authored-by: ChatGPT <bot@openai.com>' alongside a valid trailer PASSES. That is precisely the failure mode the workflow header says it exists to stop — itd-91 records a reconciliation sweep across 78 pull requests after PR bodies picked up a tool's default footer — merely wearing a different vendor's name. The AI-co-authorship objection AGENTS.md:132 states is about authorship the tool does not hold and contributor-graph inflation, neither of which is Claude-specific. Second half of the same asymmetry: the documented convention hardcodes one vendor in the template — CONTRIBUTING.md:31 writes 'Assisted-by: Claude:<model-version>' and AGENTS.md:132 gives 'Assisted-by: Claude:claude-opus-4-8' — so prose names a vendor the gate does not require, leaving a contributor using another provider without a stated correct form even though the gate would accept one. Fix direction is itd-91's, whose scope is a per-repo declared attribution preference every surface reads; .github/workflows/attribution.yml calls itself a stopgap until that lands, and iss-211 already raises itd-91's priority on multi-project adoption. Two things this record asks of that work specifically: make the co-authorship ban match on the TRAILER KEY rather than on a vendor name, so 'Co-authored-by:' naming any AI is refused; and state the convention as '<Vendor>:<model-version>' with Claude as an example rather than as the literal.
- iss-216Install instructions need a getting-started page once more than one harness is supported, and the version floor needs a home in it. Raised at the itd-108 grill (2026-08-11) while ruling that no migration is owed to existing users, because there are none yet.
- iss-217add a cross-agent session-capture source as an optional plugin
- iss-218commitment records (issue ledger, .abcd/work/decisions/, intents) must not name an external tool before its adoption is decided; names live in the dated research note. Convention exists only as maintainer guidance + docs-lint harness rules scoped to docs/ and README; the working record has no principle file or record-lint rule enforcing it
- iss-219ahoy dev-install tests read the host PATH: a stale installed abcd (e.g. the July dev shim in ~/.local/bin) makes the four install-mode tests fail with an unexpected '(shadowed on PATH)' suffix, so make preflight blocks pushes from any machine with abcd installed. The tests should run against an isolated PATH.
- iss-220simple deterministic CI failures have no compose-time prevention or self-repair path: the attribution gate detects a missing PR-body Assisted-by trailer post-hoc (PR 230), but nothing composes or verifies the body at creation time and no loop is authorised to apply the mechanical fix. PR-body composition is facilitator-owned manual work and therefore automation backlog: abcd should compose/verify the PR surfaces it requires for managed repos, and an allowlisted class of deterministic check failures (trailer append, formatting) should be self-repairing
- iss-221ahoy install's re-founding lineage prompt is a one-shot: under --yes/non-TTY it prints and silently takes the [y/N] default No, registers the root as new, and a second run reports already_up_to_date without re-asking — no verb links lineage after the fact, leaving two active index entries for the same project (old epoch 85573f…, new 488a0aa… after the attribution rewrite). Non-TTY identity prompts should refuse rather than default, and lineage should be linkable post-registration
- iss-222ahoy install --dev against an existing unowned track-latest wrapper at the target path performs no bin write, reports no symlink/shadow gap, and leaves install_mode empty — a silent no-op where loud staging requires either adopting the equivalent wrapper, refusing with a named gap, or reporting the skip on the result
- iss-223the managed .gitignore visibility table has no mode for a public repo that commits its record: on abcd-cli (public, single-repo-curated-release, .abcd/** deliberately in-tree) ahoy install applied the public policy and fenced /.abcd/ and /memory/, contradicting the repo's own boundary that the record is present in every checkout. The visibility table needs a committed-record declaration (config or marker) that suppresses the fencerelated itd-159
- iss-224ahoy install --yes returns status=partial with remaining symlink.missing but emits no note explaining the refusal (unwritable /usr/local/bin); declined_categories is null and notes are absent, so the user cannot tell why the symlink was skipped or what to do next
- iss-225ahoy skill doc says the PATH entry defaults to ~/.local/bin (created when absent), but the install engine targeted /usr/local/bin/abcd and stopped when it was unwritable instead of falling back; either the doc or the engine's bin-dir resolution has drifted
- iss-226ahoy skill doc documents a --bin-dir flag for ahoy install/uninstall, but the binary rejects it (unknown flag); the documented escape hatch for an unwritable default bin dir does not exist
- iss-227installDevShim silently swallows failures: the os.Remove, MkdirAll, and WriteFileAtomic error paths are bare returns (internal/core/ahoy/apply.go, installDevShim), so a failed shim write yields status=partial or clean with no note explaining what was not done or why; only the success path calls a.note
- iss-228The plugin-root binary (repo-root abcd -> bin/abcd-darwin-arm64) sat a month stale after iss-171 merged, so the ahoy skill's first resolution rung reported pre-iss-171 gaps (wrong target, missing --bin-dir) with no staleness signal; the skill and detection have no guard that warns when the plugin-root binary predates the source tip in a source checkout
- iss-229implement the galloping/exponential-doubling probe (trueMatchEnd) that replaces the fixed 512-byte adjacency window in scanAllPatterns/probeAt: the window grows only while a match keeps running into its edge and stops the moment the match ends short of the edge or reaches the real end of line, so a match end is never a truncation artifact. This is the structural fix designed in the 2026-08-08 decision [dcn-2608080000000001](../../decisions/dcn-2608080000000001-iss-189-iss-190-shared-root-cause.md) after bug-hunt rounds 6-8 each BLOCKed on local patches for the same root cause (a truncated window-edge view driving a discard/skip decision reaching further than the ambiguity). It dissolves iss-189 (trailing boundary satisfied by the artificial window edge, spurious over-redaction) and iss-190 (window-capped recovery truncating a token and breaking the recovery chain) outright, without reintroducing the round-6 cost regression: the window grows only for matches genuinely still growing, at the amortized cost class the top-level unbounded match already pays. iss-189 and iss-190 (both superseded by this capture) are its acceptance corpus: their repro shapes must pass without a boundary classifier or a clipped-so-skip special case.related itd-155
- iss-230offer a one-tap micro-prompt channel (survey pattern) for maintainer decisions: when abcd needs a single small human ruling (a yes/no, a pick from two or three options), it renders one micro-prompt the facilitator can answer in one tap instead of a full interview session. Lifted out of itd-111's open questions during the 2026-08-15 forward-plans grill so the staleness intent keeps a clean scope; strike the open question from itd-111 when it goes through intent plan. Facilitator-touch item, homed in the facilitator-experience plan.
- iss-231guard warn tier is silent on the live PreToolUse hook: internal/surface/cli/guard.go maps VerdictWarn to Fprintln(stderr, message) + return nil = exit 0, but the failOpen path's own comment (same function) documents that a pre-tool-use hook exiting 0 has its stderr DISCARDED — which is exactly why failOpen uses exit 1 to be loud. So every warn-tier entry (e.g. git-reset-hard) writes a message nobody ever sees and the command runs as if allowed. The warn tier is effectively invisible. Fix direction: map VerdictWarn to exit 1 (the same non-blocking-but-loud status failOpen already relies on), so a warn both runs and surfaces its message. Load-bearing for iss-200's Option-D design, whose 'warn the middle with context' model is impossible while warn is silent; also a standalone correctness bug independent of iss-200.
- iss-232itd-111 latent coupling: the ahoy install staleness refusal keys on the binary's vcs.revision (via vintage current-from-BuildInfo). Release binaries are VCS-stamped today (release.yml runs make build VERSION=<tag> from a git checkout, -buildvcs=auto default), so pinned users have a determinable vintage and proceed. But if a future release build ever sets -buildvcs=false or builds from a .git-less source archive, Known flips false for every pinned user and ahoy install begins REFUSING until they pass --allow-stale-binary. Add a guard/test on the release build config asserting the shipped binary carries vcs.revision, so this coupling cannot silently break. Non-blocking; surfaced by the independent ruthless review of feat/itd-111-staleness. NOTE: captured in the iss-200 design worktree to avoid an allocator collision (iss-231 taken there); it is an itd-111/release-build follow-up, not iss-200 work.
- iss-233ci.yml runs the full check matrix twice per PR push — push and pull_request triggers overlap
- iss-234docs-only PRs pay the full two-OS build+test matrix — add a fail-closed inert-path skip gate
- iss-235The review lenses are scattered as separate agent TYPES (abcd:ruthless-reviewer, abcd:security-reviewer, and the persona-lens as an ad-hoc prompt) rather than a single surface. Consider consolidating them under one verb: bare /abcd:review lists the available lenses; /abcd:review --ruthless / --security / --persona (and future lenses) runs a named one. A single verb is easier to discover, keeps the lens set in one registry, gives cloud routines a stable fallback (the verb hand-loads the lens prompt when the plugin's agent types are unavailable — the 2026-08-16 canary found the abcd:* agent types do not resolve in a routine session), and matches how the other surfaces are shaped as verbs. Half-formed (maintainer thought): naming and whether lenses stay agent-backed under the hood are open.
- iss-236launch --dry-run hard-fails on a local_username false positive: the scan matches the maintainer's short username against the documented '--dev' CLI flag text, so the release preview reports 5 hard fails on a clean tree. The matcher needs a word-boundary/flag-context exemption.
- iss-237Brief drift: 05-internals/04-universal-patterns.md and 01-product/03-mental-model.md describe internal/core/docfidelity, the spc-74/75 marker grammar, and a .abcd/validation_disciplines/ registry as current state; none exists in the Go tree and those spc ids belong to the pre-adr-21 spec space (live specs are spc-1..spc-22).
- iss-238brief/05-internals/01-agents.md still reserves /abcd:audit for 'compliance / hash-chain' (itd-16's umbrella), contradicting the shipped repo-conformance audit surface documented in 04-surfaces/16-audit.md (itd-85 lineage).
- iss-239Dangling pre-rebuild spec ids in the draft corpus: itd-44 (spc-56), itd-51 (spc-33/37), itd-57 (spc-48/60/62), itd-61 (spc-75) cite specs from the numbering adr-21/adr-26 reset (live store is spc-1..spc-22). Worse, intents/README.md and itd-34 assert the itd-44 lineage 'landed as itd-44 (spc-56 thin adoption)' — no such spec or decision-verdict code exists, so the record claims a delivery the tree cannot back.
- iss-240itd-85 (read-only repo-conformance audit) is fully delivered — internal/core/audit, cli/audit.go, commands/audit.md, surfaces/16-audit.md, resolved issues against it — yet the intent still sits in drafts/. Under the delivery-state doctrine the capability is only half-recorded until the maintainer runs the ship move.
- iss-241research/prompting/agents/ holds prompt baselines for chat-distiller and embark-scaffolder, neither of which exists under agents/ any more — the baseline corpus has drifted from the shipped agent set.
- iss-242abcd intent --json reports bucket counts and spec links only — no per-intent listing. A planning sweep over drafts/ (which intents are plannable vs seeded-placeholder AC, filed when) required shell-grepping 55 files and git history. The verb wants a list mode with per-intent id, title, bucket, ac_state (seeded|real), and filing date; the seeded placeholder is a stable string, so ac_state is cheap.
- iss-243sota-per-intent's template slot and intent_sota lint were never built: only 9 of 107 intents carry a '## SOTA' section, and 5 of 7 freshly-prepped drafts lack one. The principle's promotion path names the lint; until the detector exists the convention silently under-enforces (fix-the-detector).
- iss-244The intents README lifecycle diagram documents four things the binary does not have: an /abcd:intent ship verb, an /abcd:intent reclassify verb, an intent_lifecycle_hook, and the bundle-member and discipline paths of intent plan. abcd intent plan takes exactly one id and silently defaults kind to standalone with no classifier, no kind confirmation and no plan-review; the shipped verb set is intent create, intent plan, intent ready, intent link, intent review, intent review ingest and spec close. The diagram also frames the lifecycle as 'mostly automatic, with deliberate manual steps' when it is mostly manual with three transition verbs, and its step 1 claims intent create refuses without acceptance criteria when the refusal actually lives in intent plan. A committed record describing an unbuilt future as present reality is the inverse of change-narration and misleads every session that reads it.
- iss-245The capture store's schema models resolution provenance it has no verb to write. ResolvedBy{Intent,Spec,Commit} (capture.go:72) is parsed on read (validate.go:275) but Resolve (workflow.go:162) writes only resolution and impact and exposes no flag to supply it, so a resolved issue can assert it was fixed in prose but cannot point at the intent, spec or commit that fixed it. PromotedTo (capture.go:92) is validated against ^itd-[0-9]+$ (validate.go:121) and documented in the issues README as 'the itd-N this issue graduated into', yet no verb writes it and no issue in the ledger carries it — so the capture-to-intent promotion the schema anticipates is unreachable, which is why the 'Which ledger?' note in commands/intent.md forces the intent-vs-issue call at the moment of lowest information with no way to revise it. Contrast the intent side, where the fidelity review binds its verdict to a sha256 receipt over the acceptance criteria: one record store, two very different evidence standards.
- iss-246`surface_coverage` is blind inside a row, so `shipped` means "the top-level verb exists" and every unbuilt sub-verb hides behind it.
- iss-247The attribution gate cannot pass a human-only commit, so the maintainer cannot hand-edit a file through the web UI or any non-AI path. check-attribution.sh demands an 'Assisted-by:' trailer on every non-bot commit; the only exemption in .github/workflows/attribution.yml is for bot-authored pull requests. A manual one-line ADR status change (commit 5456f6022975, 'manual: Change status from proposed to accepted') failed the gate for having no trailer. The gate's own error text names the contradiction — 'If this artefact had no AI assistance, say so in the PR and this gate can be revisited; the convention is disclosure, and a human-only change has nothing to disclose. Today the gate asks for the trailer on every non-bot contribution.' Disclosure of AI assistance is the purpose, so demanding the disclosure where there was no assistance either forces a false trailer or blocks the commit. Today it blocks the maintainer; it will block the first outside human contribution the same way, and the DCO Signed-off-by deferred to the public flip does not resolve it. Needs a human-only path that is honest: an explicit no-assistance marker, or narrowing the gate to commits that claim assistance.
- iss-248references_sync lint rung: cross-check references.csl.json keys/DOIs/URLs against the ACKNOWLEDGEMENTS.md References & sources section, so a store entry without a prose entry (or vice versa) is a finding; today the sync is the documented protocol in research/_references.md
- iss-249ahoy install-mode tests inherit the real PATH: with an installed ~/.local/bin/abcd present, TestDevInstallWritesShimAndSurfacesMode, TestNormalInstallRegressionPin, TestInstallPinnedToDevTransition and TestInstallDevToPinnedTransition fail with 'shadowed on PATH' because the developer's live install shadows the test's; the tests pass when ~/.local/bin is removed from PATH, so the suite is red on any machine that has abcd installed the documented way
- iss-250Brief-surface drift found by the v0.5.0 release gate: the full-tier crosscheck (22 checkers, both directions) returned 28 unique discrepancies between the brief's surface prose and the shipped binary — 14 false-claim, 8 undocumented-surface, 2 criterion-violation, 2 stale-count, 2 fictional-layout. Dominant clusters: the vintage/staleness surfaces (bare 'abcd version' three-line render, version --json four fields, version --check, --allow-stale-binary, uninstall --bin-dir) landed without their brief rows; the citation-baseline dry-run gate and render line are undocumented in 04-launch.md; 01-ahoy.md's envelope shape omits the banlist key and guard.detail; 05-intent.md:335 claims gap_audit is deferred (shipped) and an MG004 check ships (does not exist); 07-memory.md's spec-count claim is stale (spc-2..spc-27 exist); the agents/ plugin surface has no registry row and surface_coverage does not check it; skills/-era phrasing survives in 02-constraints/04-naming.md, 06-delivery/01-build-sequence.md and 02-verification-matrix.md. Full list with file:line, claim, reality and class: the iss35-brief-surface-crosscheck receipt for content commit d1afd2c under .abcd/work/reviews/. Not release-blocking (design-record drift, no user-facing doc affected) — same class and disposition as iss-192 at v0.4.2.
- iss-251Two lint engines under one vocabulary: internal/core/repolint (post-itd-6 rename; Rule/Evaluate/tri-state exit) and internal/core/lint (RuleConfig/Finding stream) are separate engines with separate rule models and config schemas, already entangled (repolint's rule_docs.go wraps docs-lint as a conformance rule). Every new rule author must pick an engine. Consolidating the rule models is a deliberate future intent - deliberately kept out of the itd-123-era rename sweep after adversarial review of merge-now vs rename-only.
- iss-252TestEmitRefuses/an_added_record_carries_no_impact flakes on CI teardown: t.TempDir RemoveAll fails with 'unlinkat .../001/.git/objects: directory not empty' — the subtest's assertions pass, but a background git process spawned in the scratch repo (auto-gc/maintenance or fsmonitor) is still writing objects when cleanup runs. First observed on the v0.5.0 release verify job (run 31960563726), where it fail-closed the whole release after the tag was pushed; a rerun recovered it. Fix direction: the gittest scratch-repo helper should disable background maintenance (gc.auto=0, maintenance.auto=false, core.fsmonitor=false) at init so no child process outlives the test. Detector: the release verify Test step; acceptance: the suite survives teardown on CI without rerun.
- iss-253The Cut A §4 manual gate FAILED on assertions 3 and 4 (transcript: .abcd/.work.local/scratch/2026-08-16-s4-transcript.txt, machine: a no-Go Mac with a fresh harness install). After /plugin marketplace add + /plugin install, NO bootstrap line ever appeared at any of three session starts, the plugin root (…/plugins/cache/abcd-marketplace/abcd/<sha>/) contained a full source checkout but no provisioned binary, and every UserPromptSubmit and PreToolUse hook errored 'No such file or directory' for the entire evening — the exact failure family the gate checks for zero of. The command surface functioned only via rung two (the PATH binary the separate one-liner installed), so the no-Go promise is unproven; ahoy install itself reports plugin.root_missing as resolvable:false. Assertions 1, 2 and 5 passed (checksum-verified one-liner with no sudo, abcd v0.5.0; transcript captured; non-interactive install with a clean, path-scrubbed receipt — including a correct abort in a non-repo directory). Per the gate's own rule this BLOCKS Cut B. Environment notes for reproduction: the harness never visibly ran the plugin's SessionStart chain after install (bootstrap.sh emitted nothing — neither success nor refusal, despite loud-staging), and the machine's home dirs are cloud-synced (anomalous stat results, 65535 link counts, multi-minute tree walks in the clone). Detector: the §4 checklist; acceptance: a fresh-machine plugin install yields one bootstrap success line, a provisioned plugin-root binary, and /abcd answering in about a second with no Go.related itd-154
- iss-254The hook surface has a single point of provisioning and an unactionable failure mode: only the SessionStart chain runs bootstrap.sh, so when that one hook does not fire (or runs without CLAUDE_PLUGIN_ROOT — its guard then exits 0 silently), no other hook ever attempts provisioning and the session is permanently degraded; meanwhile every UserPromptSubmit/PreToolUse/SessionEnd invocation fails as a raw '/bin/sh: .../abcd: No such file or directory' — noisy on every tool call, actionable on none. Observed live in the iss-253 gate failure: hours of hook errors, zero provisioning attempts outside session start, zero SessionEnd transcript captures. Fix direction: each binary-invoking hook guards on the plugin root, attempts a rate-limited silent bootstrap salvage when the binary is absent (bootstrap already has the concurrency lock, bounded curl timeouts, and a one-stat fast path), and on continued absence emits one plain actionable line instead of the exec error. Detector: a hooks-shape test asserting the salvage-and-fallback pattern on every binary-invoking hook, plus an executed-shell fixture test; acceptance: with an empty plugin root and a working bootstrap fixture, the prompt-router hook provisions and runs; with a failing bootstrap it prints one actionable line and exits non-blocking.
- iss-255ahoy install writes a .gitignore managed block that ignores /.abcd/ (and /memory/) wholesale — on any repo that commits the durable tiers, including abcd-cli itself, this hides every new record file from git status and makes git add refuse them, silently breaking the record workflow for every session in the clone. Observed live: install on abcd-cli appended the block; new intents/issues stopped appearing as untracked; the write was reverted by hand. Adjacent to iss-176 (config in an ignored path reported NOT ENFORCEABLE) but broader: the block contradicts the three-tier layout the installer itself scaffolds. Detector: ahoy install on a repo whose .abcd/development is tracked must not write an ignore rule covering it; acceptance: install on abcd-cli leaves git status of a new .abcd/work/issues file visible.
- iss-256Post-cutover, a hand-written CHANGELOG Unreleased entry blocks every derived cut: ingest refuses a non-empty Unreleased section by design, but nothing stops the entry landing in the first place — the contributor habit predates the derived flow, and the first collision happened the day after the cutover (a merged PR added an Unreleased entry for work that had no resolved record, wedging the next cut until the entry was converted into a record by hand). Detector: a record-lint or CI rule that blocks a PR adding lines under '## [Unreleased]'; acceptance: such a PR fails its record gate with a message naming the record-first flow.
- iss-257abcd is citable and its sources are recorded: a root CITATION.cff (CFF 1.2.0) powers the forge's cite-this-repository box; the References & sources section of ACKNOWLEDGEMENTS.md records the academic literature the design record draws on as a curated, alphabetically ordered list of primary sources; canonical CSL-JSON metadata lives in .abcd/development/research/references.csl.json with a documented on-demand render path. Filed retroactively: the capability shipped with a hand-written Unreleased entry and no record, which the derived release flow refuses — this record is the entry's citable home.
- iss-258capture promote's post-mint stamp-failure remedy is attached unconditionally, so a promote that loses a race against a concurrent promote of the same issue emits advice that will refuse: B mints itd-Y, fails the under-lock re-check because A stamped itd-X, and B's error still says 'complete the link with capture promote iss-N --intent itd-Y' — running that hits the already-promoted refusal, and the duplicate draft itd-Y must be deleted by hand. The wrapped error does carry the true itd-X fact. Accepted residue class in spc-24 (no cross-store lock); a smarter remedy would special-case the already-promoted stamp error and say 'delete the duplicate draft' instead.
- iss-259intent-store paths render to the terminal unsanitised in several intent verbs: intent plan prints res.Intent.Path and intent create prints the minted path without termsafe.Sanitize, and a hostile clone can commit a drafts/itd-N-<slug>.md whose filename tail carries control bytes (intentFileRe admits anything but a newline after the id), reaching the owner's terminal as escape sequences. The promote render sanitises its two paths as of spc-24; close the class once by sweeping the sibling intent renders through termsafe.Sanitize.
- iss-260findRecordFile treats any os.ReadDir failure as an empty bucket, so an unreadable (not absent) intent/spec bucket — mode 000, or a symlinked bucket dir — makes capture promote --intent and capture resolve --intent/--spec report 'not found in the store' instead of the actual I/O error; the old intent.Load path in promote link mode reported the read error and refused symlinked buckets. Still fail-closed (nothing written), but the diagnostic lies about the cause.
- iss-261commands/abcd.md claims 'status is a positional alias for the same bare render' and its argument-hint reads [status], but the binary's root command is Args: cobra.NoArgs — abcd status errors 'unknown command' with exit 2. Either wire the alias or drop the claim; found while building the abcd <id> root positional (spc-26), which gates its positional on the record-id shape and leaves other positionals on the unknown-command path.
- iss-262check-attribution.sh's GENERATED_RE misses the italic footer form a hosted agent platform actually appends: `_Generated by [Claude Code](...)_` starts with an underscore, and the regex anchors '^[[:space:]]*(robot)?[Gg]enerated (with|by) [' — so the exact footer shape that motivated the gate sails through the body check when wrapped in markdown italics. Admit an optional leading '_' or '*' (and matching trailing) in the shape. Found live: both walkability PRs carried the italic footer and the body check did not flag it; the failing leg was commit identity.
- iss-263describeIssue discards ListResult.Skipped, so an issue file that exists but is unparseable (broken frontmatter) makes abcd iss-N report 'not found in the issue ledger' — a diagnostic that misleads about a record physically present in a status dir. Surface the skip roster in the fault: 'iss-N present but unreadable at <path>: <parse error>'.
- iss-264cmd/record-lint prints Finding.File and Finding.Message raw — no termsafe.Sanitize and no path scrub on the findings path (its scrubPaths covers only the two error exits), so any rule echoing repo content lets a hostile clone inject terminal escapes into CI logs, and any finding message embedding an os error can leak absolute paths. The abcd CLI surface sanitizes at its findings renderer; the standalone binary does not. Found by the spc-27 security review, which also caught (and the change fixed) the one in-diff instance.
- iss-26502-constraints/04-naming.md's task_classes enum row claims 'Machine-readable source of truth: the Go binary's task_classes schema (internal/core/...) — a cross-check test fails if this table and the schema diverge', but no task_classes schema or cross-check test exists anywhere in the Go tree (grep confirms zero Go references). spc-28's step 3 instructed updating that test in the same commit as the intent_review→intent_audit token flip; nothing existed to update. Either build the cross-check the row promises or reword the row to name the real source of truth (agent frontmatter + this table).
- iss-266cobra parents with no RunE are not Runnable, so cobra prints help and exits 0 WITHOUT validating args: an unknown sub-verb reads as success to a script. Confirmed on 'abcd docs nonsense' and 'abcd guard nonsense' (both exit 0); 'abcd memory nonsense' and 'abcd history nonsense' exit 1 because those parents have a RunE. spc-30 fixed the disembark parent (a retired sub-verb spelling must refuse, not silently succeed) by giving it a RunE that prints help, so cobra.NoArgs then refuses a stray token at exit 2. The same one-line fix is owed to every other RunE-less parent — sweep them so no unknown sub-verb anywhere exits 0.
- iss-267Hook sub-verb names are now a compatibility contract, not a cushion. iss-266 makes every parent runnable, so an unknown sub-verb exits 2 instead of printing help at exit 0. On the Claude Code hook plane exit 2 is the BLOCKING status: exit 2 on UserPromptSubmit blocks the prompt, and exit 2 from 'guard hook' on PreToolUse blocks every Bash tool call -- and the PreToolUse wrapper in hooks/hooks.json treats 2 as a recognised code, so its 'FAILED TO RUN ... UNGUARDED' safety net does not fire. hooks.json ships with the plugin git clone while the binary is fetched from the latest release by hooks/bootstrap.sh, so the two can skew. No live instance today (every sub-verb hooks.json names exists at v0.5.1), and the fail-closed direction is intended. But a future rename of 'guard hook' or any 'hook <sub-verb>' must now carry an alias rather than rely on the old silent exit-0 cushion: against a skewed hooks.json/binary pair it would brick a session where it previously degraded silently. Found by the security review of the iss-266 fix.
- iss-268The attribution gate cannot be written about in a fenced code block. GENERATED_RE is anchored to line start, so any line inside a markdown code fence that begins with the banned footer shape is refused exactly as a real footer would be -- and a fence is the natural way to document a shape. Pre-existing, not introduced by iss-262: the plain `Generated with [tool](url)` form was already refused inside a fence; iss-262 extends that to the emphasised forms. Hit live on the iss-262 PR itself, whose first body quoted the footer in a fence and failed the gate it tightens. The current convention is to quote the shape mid-sentence instead, which the corpus pins with two accept cases, but that makes the one document most likely to show the shape -- the change that tightens the rule -- the one least able to show it. Options: (a) keep the convention and document it in AGENTS.md so the next author does not rediscover it through a red CI leg; (b) teach the gate fence state, which costs real complexity in a bash security check and opens an evasion route, since a footer wrapped in a fence would go unflagged while still rendering as visible text; (c) accept as-is. Needs a deliberate ruling rather than a same-PR patch.
- iss-269The hook plane's fail-open fix covers sub-verbs only, not flags or leaf positionals. iss-267 routes the guard and hook PARENTS through failOpenNoArgs so an unknown sub-verb refuses at exit 1 rather than the host's blocking status 2. Three neighbouring paths still exit 2: an unknown TOP-LEVEL token hits the root's Args validator (root's exit-2 contract is pinned by 04-surfaces/08-abcd.md, lint_surface_test.go and root_dispatch_test.go, so inverting it is a larger change), a stray positional on a leaf such as 'guard hook' exits 2, and ANY unknown flag exits 2 via FlagErrorFunc which failOpenNoArgs does not touch. None is reachable from today's hooks.json, but each becomes reachable the moment the manifest changes shape: if a future hooks.json adds a flag (e.g. 'abcd guard hook --strict') and skews against an older binary, iss-267 returns verbatim -- same brick, same wrapper blind spot -- and TestHooksManifestNamesLiveSubverbs would not catch it, because its regex stops at the first non-subverb token and never inspects flags. Also worth deciding: whether a top-level rename of 'guard' itself (this release already renames audit to lint) should be covered, since a skewed pair would then block every Bash call through the root validator. Options: extend failOpenNoArgs to the leaf and to FlagErrorFunc on the hook plane; extend the manifest test to pin flags too; or rely solely on the manifest-freeze doctrine and document it. Found by the security and ruthless reviews of the iss-267 fix.
- iss-270The attribution gate's fence handling reads a fence's indent in ABSOLUTE columns, but CommonMark measures the three-space opener limit relative to the enclosing container. That diverges in BOTH directions inside a list item, and the dangerous direction is the one this record originally stated backwards.
- iss-271Three clauses of the attribution gate's fence matcher are not pinned by the corpus. Found by the ruthless review of iss-268, which ran a 31-mutant battery: (1) the marker-character TYPE restriction in fenceparse -- substituting 'if (c == "") return 0' keeps termination and leaves the corpus green, but --- *** ___ === runs then become fence delimiters, which is a real bypass direction; (2) the tab exclusion in sub(/^ +/, "", t) -- the comment asserts a tab-led line is not a fence, but allowing [ \t] leaves the corpus green; (3) blank()'s \t\r character set -- narrowing it to a plain space leaves the corpus green. All three are CORRECT as written; only the coverage is missing, and only the first has a bypass direction. Two smaller gaps from the same battery: the iss-270 list-item residual is pinned for '- ' items but not for '1. ' items (content column 3, also under the absolute limit, same class and same reproduction shape), and no case places a checkable line immediately after a fence closer, so a one-line over-strip at the boundary would pass the whole corpus. Note when adding cases for (1): deleting the marker-character line outright HANGS awk rather than failing a case, because on an empty line the character is the empty string and substr past the end also returns it, so the run counter never terminates -- a mode a pass/fail corpus cannot express, and the reason that line carries a termination comment.
- iss-272The guard's WRAPPER set has the same incomplete-enumeration shape gh-297 fixed for interpreters. gh-297 made the execute-a-string INTERPRETER family one shared predicate (sh, bash, dash, zsh, ksh, mksh, ash). The wrappers map in internal/core/guard/match.go is a separate list of commands that merely exec another, and it omits several that are equally ordinary: nice (and 'nice -n 5'), setsid, flock, stdbuf, ionice, unshare, chroot, and busybox sh -c / busybox ash -c. Each is a silent allow today for every bundled blocker -- and equally so before gh-297 with plain sh, so none is introduced by that change. Also absent from BOTH sets: su -c '<hazard>', runuser -c '<hazard>' and script -c '<hazard>' /dev/null, which are execute-a-string interpreters in exactly the sense gh-297's rationale describes (each runs its -c operand with the grammar the tokenizer already parses) but are not shells, so they belong in neither list as currently shaped. The realistic ones are nice, setsid, busybox sh and su -c. Out of scope by contrast: ssh host '<cmd>' and docker run img sh -c '<cmd>' execute on a different host or namespace. Note for whoever takes this: gh-297's comment now says explicitly that 'nowhere left to widen' covers the interpreter set only, not the wrapper set, so the claim and this gap do not contradict each other. Found by the security review of gh-297.
- iss-273Consolidate the build-provenance step onto actions/attest and drop the wrapper. Upstream states that as of version 4, actions/attest-build-provenance is simply a wrapper on top of actions/attest, and that new implementations should use actions/attest instead. This repo ALREADY invokes actions/attest directly at .github/workflows/release.yml:248, in the same job that uses the wrapper at :296 -- so it currently runs attest 4.2.2 directly and, after the gh-316 bump, 4.2.1 transitively through the wrapper. Consolidating would remove a trust layer, eliminate that version skew, and halve the dependabot churn that keeps tripping iss-209 (every pinned-action bump edits the generated workflow only, breaking template parity and reddening CI until a human runs make scaffold-sync). actions/attest generates SLSA provenance natively in src/provenance.ts, so the migration looks feasible; the work is to map the wrapper's inputs onto the underlying action's and confirm the emitted attestation predicate is unchanged. Found by the security review of the actions/attest-build-provenance 4.1.1 to 4.2.2 bump, which approved that bump on its merits.
- iss-274abcd lint exits 2 on a clean main checkout: four privacy-hygiene errors flag illustrative example paths (internal/core/ahoy/fsutil.go:40+42, internal/core/ahoy/store.go:170, internal/surface/cli/staleness_test.go:14 — comment prose and a test fixture like /home/alice/.local/bin/abcd), and no CI job runs the full conformance verb, so the repo's own lint sits red between releases. Either the lines take the sanctioned abcd-lint:allow marker (they are deliberately illustrative) or the rule learns the persona convention; and whether abcd lint belongs in CI is a separate maintainer call.
- iss-275TestGuardShimFailsOpenLoud's runShim inherits the host PATH, so on a machine with a real abcd installed the guard hook's PATH-fallback rung (shipped with the hook resolution ladder) finds it: the binary-absent case genuinely guards the session via the PATH binary, no UNGUARDED warning prints, and the test fails — environmentally, exactly the machines that dogfood the install. CI is unaffected (no abcd on PATH). Same class as iss-249, in the cli shim harness; the hooks_selfprovision_test hookRun helper already pins PATH for this reason and is the pattern to copy. Detector: the test itself on an affected machine; acceptance: go test ./internal/surface/cli/ -run TestGuardShim passes unmodified with an abcd on PATH — including a new case asserting the PATH rung guards the session when the plugin root is empty.
- iss-276The capture source enum lacks a value for external-contribution intake: validSources in internal/core/capture/capture.go names nine sources, none fitting a finding that arrives from an outside PR's triage; the intake pipeline (.abcd/work/intake.md) will need one
- iss-277Ruleset drift check is unbuilt: the applied branch rulesets are mirrored under .abcd/work/rulesets/ but nothing diffs the live rulesets against the committed JSON, so drift is invisible until a human re-reads the console; itd-92 owns the verb
- iss-278Five agent prompts read attacker-influenceable input without the itd-5 contract (ruthless-reviewer, security-reviewer, docs-currency-reviewer, intent-auditor, sota-researcher) and agents/ sits outside both lint roots, so no detector exists for the class; the PQ linter (agents/README.md) is the missing detectorrelated itd-151
- iss-279docs-lint roots are docs/ and README.md only, so .abcd/** — the largest public surface — is scanned by no name gate; retire-the-name's banned_tokens cannot reach CONTRIBUTING.md, AGENTS.md, or scripts/ either
- iss-280main's own commit messages are ungated: Makefile's check-attribution runs origin/main..HEAD, whose base is main itself, so a commit that lands on main (squash, web merge) is never checked by any local or CI run afterwards
- iss-281Externally submitted PRs and issues must be reviewed by at least two invited collaborators (hard rule, maintainer decision 2026-08-19). PR half: enforceable as a required status check counting approvals from collaborators with role triage or above, running on pull_request_target so a fork cannot neuter it. Issues half: GitHub issues carry no native review gate — ledger captures land via PRs and inherit the PR rule; tracker issues rely on intake S1 process until a mechanism exists
- iss-282The retention prune has no executor: ComputeRetention renders the newest-per-line plan on every cut (brief section 3) and ship.go names GitHub Release + retention prune as a later phase, so superseded patches (v0.5.0, v0.4.0 today) stay published until someone deletes them by hand from the plan. First rung: a documented manual prune after each publish (gh release delete, tags kept for record); the executor belongs in the release workflow after that proves outrelated itd-70
- iss-283The real_name suppression breaks on an org-owned remote: newIdentityMatchers suppresses real_name only when git user.name equals the username parsed from remote.origin.url, so transferring the repo to an organisation (remote owner Partnermedia, user.name set to the product thinker's login) turns the caller's public GitHub handle into 13 hard_fail findings and blocks the launch. The noreply email (id+login@users.noreply.github.com) carries the caller's login locally and is the right second source for the suppression
- iss-284The adr-40 vocabulary renames narrow the public surface for v0.6.0: abcd audit is abcd lint, abcd disembark oracle is abcd disembark review, and abcd intent review / intent review ingest are abcd intent audit / intent audit ingest. Four command paths leave the surface; each successor refuses the old spelling by naming the new one. Deliberate breaks, documented in the CHANGELOG Breaking section (itd-123, itd-124, itd-125)
- iss-285Quoted YAML nulls split capture and record-lint verdicts: capture unquotes before IsNull, record-lint reads the raw value
- iss-286Release derivation diagnoses a null impact as malformed while record-lint calls it missing
- iss-287Uppercase YAML null spellings unrecognised by the null predicates (reported as GitHub #290)
- iss-288The adversarial-review principle has no armed detector: adversarial-review-scales-with-blast-radius requires two independent reviews before an intent moves drafts/ to planned/ (and one before an ADR is accepted), but nothing refuses the move without them. The enforceable rung: intent ready (and the record checks) refuse the transition unless review receipts exist in the .abcd/work/reviews/ VSA shape for the draft at its reviewed content hash
- iss-289The release workflow builds on an unpinned Go minor: scaffold substitutions set GoVersion 1.25, which resolved to 1.25.12 on runners today — the toolchain with four stdlib vulnerabilities fixed in 1.25.13 that govulncheck flagged in ci. ci.yml was pinned to 1.25.13 the same day but release.yml renders from the template, so shipped binaries build on whatever 1.25.x the runner resolves. The v0.6.0 tag predates any fix and cannot be retro-patched (anti-tag-move); the pin lands for the next cut
- iss-290CODE_OF_CONDUCT.md is deliberately deferred: it is not in the stray_root_docs allowlist, and allowlisting it in the same change that adds it would put the evaluator inside the loop; adding it is a two-change dance (allowlist first, file second) for whenever the contributor base warrants one
- iss-291abcd guard silently allows a blocker whose exec-string verb carries a value-taking short-flag cluster before the payload flag (script -Tc out.txt -c '<blocker>'): clusteredPayload accepts the cluster without consulting the verb's value flags, mis-reads -Tc as -T -c, resolves a bogus payload and switches the Tier-2 fail-safe off for the segment
- iss-292abcd guard's wrapper-probe test (wrappers_test.go runsCommand) runs wrapper binaries with no cmd.Dir, inheriting the package source directory as cwd; flock opens its probe values (0 1 PATH root) as lock files, so go test writes four zero-byte files into the tracked tree — and they are already committed under internal/core/guard/
- iss-293launch.ParseSemver discards strconv.Atoi's range error (major,_ := ...), and semverRe's numID is unbounded, so a >int64 version component clamps to MaxInt64: distinct oversized versions collide to one String() and the next Patch++ wraps negative — reachable via GitExistingTags (git tag list) and changelog.DeriveNext; the identical defect was already guarded in spec/spec.go
- iss-294The 'abcd version --check' flag help calls it 'the only command that touches the network', but the same generated reference page also calls 'docs cite refresh' the only network verb and 'memory ingest <url>' does its own HTTP GET — three real fetch paths, contradicting adr-38's own two-verb model
- iss-295README.md's 'It starts with the brief' section claims in present tense that abcd 'has a skill that ingests that material and produces a plain-language draft of your project's brief' and that you sharpen it with 'a Socratic interview the framework provides' — but abcd ships zero skills (surface is commands-only) and the grill/Socratic interview is an unshipped planned intent (itd-27), an unmarked not-yet-real claim the README's own honesty rule forbids
- iss-296The hand-maintained ADR index table (.abcd/development/decisions/adrs/README.md) ends at adr-42 and omits committed records adr-43 and adr-44; the record-lint index_drift rule registers four indexes but not the ADR index, so this largest hand index is ungated. Same file: .abcd/work/rulesets/README.md says 'seven required status checks' where main-protection.json now lists eight (external-review added)
- iss-297adr-40's v0.6.0 verb renames (intent review -> intent audit, disembark oracle -> disembark review) left stale residue in durable present-tense docs: roadmap/phases/{README.md,phase-0-substrate.md,phase-6-lifeboat.md} still say 'intent review', and brief/05-internals/08-skills.md plus brief/04-surfaces/README.md still list 'oracle' as a disembark sub-verb the binary now refuses
- iss-298The brief carries broken and stale intra-record cross-references invisible to links_resolve (which strips the #fragment before resolving): six deep links name headings that were renamed or renumbered (04-launch.md, 04-universal-patterns.md, 01-ahoy.md, 05-intent.md sections 5/6/7), ten anchors mis-encode an em dash, 00-meta.md cites a deleted disembark section-3 budget rule, and three live README lines cite the pre-split monolithic brief by section number
- iss-299brief/README.md's 05-internals directory-tree comment enumerates ten chapters including a nonexistent 'in-session dispatch' (that is planned intent itd-2, not a chapter); the directory holds nine files and its own index has nine rows
- iss-300The persona glossary (brief/glossary/core/persona.md) and brief/01-product/05-personas.md say the persona picker 'chooses at random', contradicting personas.json and itd-79 whose rule is 'selection is by role, never by name'; the glossary's worked examples also assign off-role names (Carol as product lead, Alice as developer)
- iss-301external-review.yml computes its approver tally with 'gh api .../reviews --paginate --jq' where --jq runs per API page (not across the full set; --slurp is incompatible with --jq), and no per_page is set so pages are 30 — so the 'latest state per reviewer wins' reduction the comment promises fails once reviews span a page: a stale page-1 APPROVED survives a later page-2 CHANGES_REQUESTED, and a straddling double-approval is counted twice. Fail-open on a required security gate. Not fixed autonomously: required-check workflow that cannot be validated without running Actions
- iss-302external-review.yml's role_of() folds every 'gh api collaborators/<u>/permission' non-zero exit into the string 'none' via '2>/dev/null || echo none', indistinguishable from a legitimate no-role answer, so a transient/permission failure silently misclassifies authors and drops approvals; the job grants only contents:read + pull-requests:read while that endpoint needs push access (or an App members permission), so it likely 403s for every lookup and wedges the gate red for all human PRs with no diagnostic. Not fixed autonomously: required-check workflow, and the permission behaviour needs a real Actions run to confirm
- iss-303links_resolve (internal/core/lint/lint.go checkLinks) strips the #fragment before resolving and skips same-file # links, so no gate validates heading anchors even though both record-lint and docs-lint declare the rule blocking and the Makefile advertises it as catching a broken relative link; ~18 broken anchors sit on a green tree. Proposed: extend the rule to slug the target file's ATX headings and validate the fragment, landing warn-first
- iss-304Confirmed nitpicks deferred from bughunt round 1 (recorded not fixed): (a-4) memory ingest --source reads its operand with os.Stat-then-unbounded os.ReadFile, a size TOCTOU the URL branch's io.LimitReader avoids; (b-4) the generated CLI reference claims to list every user-facing command but omits Cobra's completion/help commands; (d-12) the CI job id 'record-lint' actually runs scripts/check-reviews.sh (reviews-charter), a misleading required-check name whose safe rename needs a coordinated live-ruleset edit
- iss-305abcd lint privacy-hygiene hard-fails on ordinary committed content because hasAbsHomePath lacks the leading-boundary predicate its scanner twin has
- iss-306scanner githubRemoteRe is case-sensitive on the github.com host, disabling the github_username detector on a mixed-case remote and spuriously hard-failing when name==handle
- iss-307scanner network ipv4Re and macRe rely on a trailing ASCII word boundary, silently missing a hard_fail address whose only sin is an adjacent word char
- iss-308repolint absPathRe Windows arm is case-sensitive so a lowercase c-users path escapes the privacy rule
- iss-309launch ParseSemver discards strconv.Atoi range error so an over-int64 version component clamps to MaxInt64 and can wrap negative in DeriveNext
- iss-310memory ingest materialFromLocal reads a user-typed operand with Stat-then-ReadFile leaving a swap window and an uncapped-growth read
- iss-311cmd record-lint and scaffold-sync resolve the repo root with an unscrubbed git rev-parse so an inherited GIT_WORK_TREE redirects the lint or release gate
- iss-312guard wrapper-probe tests write flock lock files into the tracked package source tree and four zero-byte artefacts are committed
- iss-313check-attribution-cases.sh scratch repos are not hermetic so an inherited GIT_DIR makes the corpus report green while rewriting the ambient repository history
- iss-314Makefile PHONY list omits check-attribution scaffold-sync and scaffold-sync-check so a same-named root file silently no-ops the target
- iss-315guard CHANGELOG code comment and test claim python -c and perl -e already get a loud warn but the shipped behaviour is a silent allow and the pinning test is vacuous
- iss-316README process section asserts two unshipped capabilities a brief-drafting skill and a Socratic interview the framework provides
- iss-317development README conventions sentence says issues graduate rather than a ledger contradicting accepted adr-32 and the live work-tier ledger
- iss-318AGENTS.md and the ci.yml header enumerate CI separate jobs as a closed list that omits dependency-review and govulncheck
- iss-319development README record-map table omits specs release and release-gate and carries a stale personas-json migration promise
- iss-320brief and intent record cross-references carry dangling section anchors including five that misdirect a reader to the wrong section
- iss-321persona pronoun discipline itd-79 is violated by gendered pronouns in seven intent records including a shipped intent
- iss-322lifeboat gvIDNum discards Atoi range error so an over-int64 record id from a foreign repo sorts to the extreme of the graveyard readout
- iss-323hook salvage entries invoke bootstrap.sh with no timeout budget below its 180s curl worst case so a slow-link provision is killed and suppressed for ten minutes
- iss-324scanner isPathSegmentByte includes the slash so a third partys home path inside a file URL escapes stage-one redaction
- iss-325no pre-tag CI lane cross-compiles the full release matrix so a darwin-amd64 or linux-arm64 interaction break first surfaces post-tag behind the release approval gate
- iss-326The v0.6.0 tag is permanently unpublishable: its roll branch carried no receipts commit, the receipt gate fail-closed at release time, and the re-release path builds only from the tagged commit whose frozen tree can never contain receipts naming its own content commit. The tag stays as a record (anti-tag-move); v0.6.1 is the recovery
- iss-327The ship flow permits an unreleasable cut: launch ship writes the dated heading with no check that the receipts protocol can complete, so the receipt gate fires at tag time — the most expensive possible moment, unrecoverable once tagged. Folded into itd-93 by maintainer decision: the emit prints the receipts protocol as a checklist, the ingest refuses a cut it cannot prove releasable, and a launch receipts sub-verb runs the release job's exact check locally before the mergerelated itd-93
- iss-328The brief's surface chapters drifted 37 findings from the shipped reality (v0.6.1 release-gate crosscheck, full tier): 14 false claims, 12 undocumented surfaces, 10 stale counts, 1 fictional layout — including a pre-rename 'intent review ingest' spelling in 05-intent.md, the ahoy dry-run envelope missing its banlist key, an undocumented --allow-stale-binary install flag, and the launch dry-run's citation gate absent from its gate roster. The full where/claim/reality list lives in the iss35 receipt committed beside the v0.6.1 cut under .abcd/work/reviews/; a sweep should fix them chapter by chapter, citing the receipt
- iss-329Go 1.25 has left the support window: go.dev lists 1.27.0 and 1.26.7 as the stable lines, so 1.25 receives no further security patches and the pinned 1.25.13 is the line's end. The toolchain (go.mod go directive, ci and release pins, scaffold substitutions) should move to the older supported line, 1.26.x, as its own change with the parity test in lockstep
- iss-330Parallel-mint id collision observed live: the maintainer's bughunt session and the release session each minted iss-291..293 concurrently; the collision surfaced only at the merge-queue's record-lint on the second branch, costing a full release re-cut. Direct field evidence for itd-114 (collision-proof record ids) — the ledger's next-free-integer mint is unsafe under exactly the parallel-agent workflows the repo now runs daily
- iss-331commands/lint.md presents the abcd-lint:allow line waiver as applying to any finding, but only the privacy-hygiene rule consumes it; a user waiving a docs-currency/three-tier-layout/etc finding gets a silent no-op and a stray committed token, colliding with docs-currency's own differently-spelled escape
- iss-332.abcd/development/README.md conventions line says issues graduate into intents/ or principles/ rather than a ledger, but the repo runs on a committed issue ledger at .abcd/work/issues/ (adr-32); the map of the durable record denies the store it governs, in the file iss-42 ruled must be current
- iss-333brief/05-internals/03-configuration.md's Plugin-internal development namespace tree draws the pre-adr-30 layout: roadmap/intents/{drafts,planned,shipped}, research/adr/, research/phase/, and specs/ under .abcd/ — the record's only map of its own namespace routes a reader to four paths that do not exist; the blocker moved-intents-path rule is defeated only by the ASCII art splitting the string
- iss-334intents/README.md teaches the v0.6.0-retired intent review verb and the intent-fidelity-reviewer agent (retired to intent audit / intent-auditor by adr-40); the intents store front door documents an invocation that exits non-zero and an agent absent from the tree, and its template block is copied into new intents while contradicting create.go
- iss-335.abcd/work/issues/README.md self-declares the store contract with strict validation but omits the impact field (mandatory in resolved/, gated by the issue_impact_valid blocker) and the agent-observation source value (accepted by capture and used by live records) — a reader hand-authoring a resolved record per the contract fails preflight
- iss-336checkGateLockstep returns clean when its runbook or workflow config path is blank while enabled:true, before the rule's own fail-closed guards — a defence-in-depth asymmetry against the rule's stated posture; functionally equivalent to enabled:false (no external arming path), so recorded not fixed
- iss-337probe.go's inner directory descent (dirRoot.OpenRoot(name)) is guarded only by the parent ReadDir's IsDir, so a directory swapped for a FIFO in that window blocks — same TOCTOU shape as readLifeboatFile but race-only and unfixable via the nonBlock const (os.Root.OpenRoot takes no flags); needs a raw openat restructure, recorded not fixed
- iss-338Seven registry personas are given he/she/his/her pronouns across intents/drafts (itd-92,97,98,108,126,128) and intents/shipped (itd-100), violating the they/them persona discipline (itd-79); review-enforced convention with no mechanical gate, concentrated in one 2026-08 authoring batch — a cosmetics-batch cleanup
- iss-339githubRemoteRe matches the remote host case-sensitively, so a mixed-case github.com remote (git@GitHub.com:...) leaves GitRemoteUsername empty and the github_username redaction kind is never compiled — the caller's handle survives history capture redaction and the PII scan
- iss-340abcd history show writes the stored transcript body to the terminal with no termsafe sanitisation (cli.go human render branch) — a transcript that ingested hostile content (fetched pages, target-repo files) replays ESC/CSI/C1/bidi sequences raw; the termsafe sweep missed the history surface
- iss-341readLifeboatFile keeps an Lstat then root.Open window over an untrusted lifeboat (embark), bypassing fsutil.ReadGuardedInRoot — a vetted regular file swapped for a FIFO blocks the open forever, or an in-root symlink is read/hashed in place of the vetted file
- iss-342SourceContext.ListDir opens directory entries with root.Open (no O_NONBLOCK), so a statically-planted FIFO named at a path a probe adapter lists (e.g. docs) hangs abcd disembark probe/plan/pack forever over an untrusted target repo — no race required, breaking the package's stated no-hang-on-FIFO invariant
- iss-343commands/prepare-this-repo.md locates the record at commands/abcd/prepare-this-repo.md and says the repo root is three levels up, but the file lives flat at commands/prepare-this-repo.md (two levels up) since the iss-161 flattening — an agent following it resolves $ABCD one dir above the repo and every Phase 0/1 read misses, under a no-search-fallback directive
- iss-344Parallel hunts capture the same defect twice: iss-306 (hunt A round 1, landed late) and iss-339 (hunt B round 2) record the identical githubRemoteRe case-sensitivity bug, minted independently on unmerged branches invisible to each other. Collision-proof ids (itd-114) do not solve this class — it is the semantic sibling of the id collision, sharing the root cause that parallel minters cannot see each other's unmerged mints. Candidate rungs: a capture-time similarity check (itd-84's validator rung), hunt briefings that read open PRs' ledgers, or a shared mint registry as a side effect of itd-114's forge-backed option
- iss-345ahoy symlink heal never fires for the entry a plugin update strands: classifyBinTarget owns a symlink only when its dest equals the current plugin root binary, so a PATH entry pointing into the deleted previous plugin cache dir classifies foreign+dangling — no symlink.dangling gap, stepSymlink refuses, and the user is told to resolve manually a link abcd itself wrote. The heal only covers same-root-binary-deleted, a state no real plugin update produces.
- iss-346guard check's also-matched line assumes Matches[0] is the winner, so a synthetic block over registry warns silently drops the matched warn entry and echoes the winner twice
- iss-347readTranscript opens the hook-supplied transcript path without O_NOFOLLOW or an over-cap probe, the one guarded read left off fsutil.ReadGuarded, so a symlinked transcript_path is followed and an over-cap file is stored silently truncated
- iss-348the root command's Use and help omit the shipped record-id dispatch, so the generated CLI reference states Usage: abcd with no positional and abcd --help never mentions that abcd iss-N describes a record
- iss-349terminology.md lists the pre-tool-use shell-hazard guard among deterministic fail-closed gates, asserting the opposite safety property from adr-42's fail-open-loud mistake filter on the one page written for an evaluator
- iss-350README promises abcd ahoy reports the local-bin-not-on-PATH state as a named gap after the copy one-liner install, but detectBinDirOnPath is suppressed for a copy install: no plugin root yields no PATH gap at all and a resolvable root yields symlink.foreign with resolve-manually
- iss-351the three-disciplines roster itd-1 itd-5 itd-37 is hand-enumerated at six sites while intents/disciplines/ holds six active disciplines, dropping itd-79 itd-81 itd-84 from the mental model, scope, roadmap dashboard and phase-0 acceptance
- iss-352three current-state records cite ADRs at development/research/adr/, a path that does not exist and a layout adr-30 explicitly rejected; all three are backticked code spans links_resolve never checks
- iss-353research/notes/README.md prescribes topic-kind note naming while adr-30 and development/README.md ratify date-prefixed naming and the record-lint successor plus ideate both emit dated notes; the notes README is the outlier and 29 of 41 notes are dated
- iss-354ci.yml's three go-version pins are coupled to nothing: TestSelfScaffoldParity gates release.yml and auto-release.yml against scaffold substitutions but no test reads ci.yml, so the d594511 drift where CI scanned green on a newer toolchain than the release build recurs silently on the next bump
- iss-355a batched merge-queue push makes github.sha the batch tip, so auto-release tags the wrong commit and release.yml's HEAD-caret-2-caret receipt derivation resolves an unrelated PR's commit whenever the release roll is not the last entry in its queue batch; the ancestry guard passes and the run wedges after the immutable tag, the iss-326 outcome by a route itd-93's pre-merge check cannot close because batch composition is decided by the queue
- iss-356round-2 fixed nitpick batch: guard check help omits the disclosed backtick limit; urlguard misses CGNAT 100.64/10 and other RFC 6890 ranges; readHookInput misreports an over-cap payload as malformed (iss-201's class at the shared helper); repolint privacy-hygiene silently skips textual files over the 4 MiB cap; capture reCommitSha refuses 64-hex commits; launch Short hides that --dry-run is required; release.yml verify-tag comment overstates what gh verifies; release.yml header says dispatch runs only the rehearsal job; dependabot covers no pip ecosystem for docs; brief pointer lines enumerate five of nine internals chapters; phase-6 and 06-lint carry change-narration blocks; 05-internals cites a ledger entry that does not exist; 03-evidence names the retired activity record nitpick documentation
- iss-357memory ingest records a redirect-controlled FinalURL verbatim into stored material origins — the iss-359 class one door over; the cite fix neither touched nor recorded the sibling site
- iss-358scanner lanHostRe and deviceHostRe keep the trailing ASCII word boundary the iss-307 sweep dropped from ipv4Re and macRe, so a LAN or device hostname abutting an underscore or alnum suffix is silently missed
- iss-359cite fetch records a redirect-controlled FinalURL verbatim, so C1, bidi and zero-width runes in a hostile Location query reach abcd docs lint --json and the committed citations baseline raw; the termsafe doc claim that encoding/json escapes control characters is false for those classes
- iss-360adr-7 carries no YAML frontmatter (uses a prose Status line) while the ADR format contract requires machine-readable frontmatter on every ADR; it is the sole outlier of 36 and passes record-lint ungated
- iss-361The lifeboat coverage renderer prints untrusted cross-repo status and tiers_present fields to the terminal without termsafe, so a crafted probe report injects raw ESC/OSC-8/C1/bidi sequences; only the repo name is sanitised
- iss-362abcd banlist --json omits the reach sentence its command file instructs an agent to relay verbatim; reach lives only in the text renderer, forcing the paraphrase the doc forbids, while abcd ahoy --json carries banlist.reach correctly
- iss-363commands/lint.md and prepare-this-repo.md enumerate the conventions abcd lint checks as five, presented as exhaustive, but DefaultRules ships six including identity-positioning; prepare-this-repo.md itself arms that rule
- iss-364capture validates related_specs against the retired fn-N namespace (reFnID) instead of the live spc-N; adr-11 renamed fn to spec, fn- is a record-lint blocker, and 0 of 340 records populate the field, so it is unusable for its documented purpose
- iss-365The govulncheck CI job pins @v1.1.4 whose bundled x/tools caps its type-checker at go1.24 while go.mod declares go 1.25.6, so package loading fails and the job exits before any scan; non-gating masks it as advisory, so no vuln analysis has run since it landed
- iss-366termsafe.Sanitize masks four zero-width runes (U+200B/200C/200D/FEFF) but not U+2060 WORD JOINER (the modern successor to the deprecated FEFF-as-joiner it does mask), nor U+2061-2064/U+00AD/Hangul fillers, so those default-ignorable characters pass through and two byte strings render identically
- iss-367commands/launch.md documents a top-level files count in launch --dry-run --json, but DryRunReport has no such key; the file list is bundle.files, an array; the bullet violates the file's own dotted-path convention
- iss-368The core/disembark glossary term links its counterpart to interview/embark (the grill-session opening, a different bounded context) rather than the /abcd:embark unpack surface, misdirecting the reader
- iss-369readTranscript opens the hook-supplied transcript path with O_RDONLY|O_NONBLOCK but no O_NOFOLLOW, the last bespoke external-input read in the CLI not routed through fsutil.ReadGuarded; defence-in-depth consolidation (no reachable exploit: the path is harness-supplied and no path policy exists)
- iss-370Agent worktrees commit without the private name-guard: .abcd/.work.local/ is per-worktree, so every isolated-worktree agent commit runs with the banlist layer absent — loudly warned, per design, but the isolated-agent pattern now systematically bypasses a protection the main checkout has. Candidate remedies: the worktree-creation path seeds a pointer to the primary checkout's store, or the hook falls back to reading the primary worktree's local tierrelated itd-150
- iss-371The persona_registry lint checks names, not roles: itd-114 shipped 'Bob, a maintainer' (Bob is registered staff engineer; the maintainer role is Kira's) and itd-115 has 'Carol, a facilitator' (Nia's role) — both passed lint. The selection-by-role rule (personas.json, itd-79) has no detector for role-name agreement
- iss-372The CHANGELOG Unreleased section and DECISIONS.md tail are structural merge-conflict magnets under parallel PRs: every concurrent branch appends to the same two files, and the maintainer hand-resolved conflicts across the 2026-08-20 merge sweep with bughunt round 3 DIRTY on exactly these files as the third occurrence. The derived-cut model points at the fix: entries could live in the records themselves (per-record files never conflict) and compose at cut time, retiring the shared Unreleased append entirely — itd-93's surface should weigh it
- iss-373Three ADRs end with leaked agent tool-call closing tags committed into the durable record: a literal </content> line then </invoke>
- iss-374The hand-maintained ADR index lists adr-44 as proposed but the record frontmatter is accepted; the index drifted after status was flipped without updating the index
- iss-377Demote hooks/bootstrap.sh to a cold-start trampoline once abcd update ships (itd-130 follow-on rung). Trigger: itd-130 shipped. When any abcd binary is resolvable, the hook delegates provisioning to the Go core (abcd update); the raw curl fetch survives only for the no-binary-anywhere cold start — the one state a Go updater cannot serve. Seam hardening carried from itd-130's Decisions: delegate only to a binary passing an ownership check, keep the raw fetch as the fallback when delegation fails, and freeze the release-asset layout as a contract so an old PATH binary provisioning a new plugin root keeps working across cuts. Goal: one canonical downloader instead of three (bootstrap.sh, the README one-liner, the Go verb).related itd-2609292106557115
- iss-378Windows cold-start shim for the binary: a PowerShell twin of hooks/bootstrap.sh for the no-binary cold start on Windows. Trigger: Windows target work begins (abcd ships Windows binaries one day). itd-130's abcd update core is the compiled updater that runs on Windows once a binary exists — it already uses minio/selfupdate's rename-dance for the running-exe swap — but the hook ladder in hooks.json and bootstrap.sh are POSIX shell and do not run on Windows. This seed is the cold-start shim only; the steady-state updater is itd-130.
- iss-379In-process build-provenance (SLSA attestation) verification in abcd update. Trigger: the trust gap the README concedes is worth closing (e.g. after the public flip). itd-130 ships at the same-origin checksums bar (itd-105); the release workflow already attests binaries and checksums.txt, so abcd update could verify the attestation before the swap for a stronger root of trust than same-origin checksums — at the cost of a heavy dependency (sigstore-go). Twin of itd-108's deferred offline signing key (minisign): both close the 'the forge is the identity root' gap that an attestation alone does not.
- iss-380Homebrew tap for abcd (a personal tap, brew install <personal account>/tap/abcd). Trigger conditions are now MET: the repo is public and abcd update exists (its install-channel refusal already prints brew upgrade abcd on a Cellar-resolved path). Recorded and parked in [dcn-2608200000000006](../../decisions/dcn-2608200000000006-homebrew-distribution-recorded-and.md); this ledger entry makes it queryable rather than prose. abcd's release pipeline is bespoke (semantic-gate attestations, no goreleaser), so the tap push is a hand-rolled release-workflow step, not goreleaser's homebrew_casks pipe. Ready for triage rather than deferral.
- iss-381The delivery pipeline abcd runs on itself is hand-orchestrated and should be deterministic. This session hand-ran the full sequence: SOTA research -> itd-84 decomposition -> draft intent -> TWO independent adversarial reviews (design/feasibility + record-discipline) -> planning interview -> plan+spec -> test-first implementation -> TWO more adversarial reviews of the diff (ruthless + security) -> apply/refute findings -> gates (preflight, record-lint) -> atomic commits + PR -> resolve the ledger issue with provenance -> seed the deferred items back into the ledger. Every hand-off, gate, and review-pair was driven by judgement, not a deterministic harness. The individual stages already have records — itd-83 (the review bar fires itself), itd-84 (decompose before filing), itd-82 (ledger drain), itd-78 (intent-dependency graph) — but ALL are drafts/staged and NONE composes the others into one orchestrated pipeline. Honest constraint (loud-staging): the pipeline cannot be MORE automated than its stages, so full automation waits on those disciplines shipping; but the deterministic SCAFFOLD — the fixed stage order, the mandatory review-pair gate before plan and before merge, the hand-offs to the host for the human-in-the-loop steps, the ledger-seed-the-deferrals close-out — can be built now as a workflow/routine (itd-107 versioned-routine-template is the nearest delivery vehicle). Routing note: this is a big, cross-record idea, not a decomposed intent — it likely needs /abcd:ideate then itd-84 decomposition before it becomes filable, and it may reshape rather than duplicate itd-83/82/78.
- iss-382disembark plan's RenderManifest prints planned file paths unsanitised, so a hostile source-repo filename injects raw C1/bidi terminal escapes into the plan render and its --json twin
- iss-383the history transcript store's read path is unguarded — listRecords and Read use raw os.ReadFile, so a planted FIFO wedges history list and history capture while the store flock is held, and a symlinked record is followed
- iss-384Baseline.validate sanitises final_url alone while echoing the entry key, url and quoted fields raw, so a committed citations-baseline entry writes ESC/bidi/zero-width to the terminal through the blocking docs-lint gate
- iss-385commands/version.md's network enumeration is still false after two rewrites — it names version --check and update as the only fetch verbs while docs cite refresh and memory ingest <url> also reach the network
- iss-386launch scaffold derives a floating Go minor for adopter repos — goModVersionRe strips the go.mod patch, goVersionRe rejects supplying one, the toolchain directive is ignored, and a hand-pinned release.yml is refused then overwritten — the adopter-side residue of iss-289
- iss-387the release-gate manifest pins 17 briefDocs while four shipped surface chapters (guard, ideate, identity, banlist) are outside the pin, so every full-tier crosscheck attests coverage it never ran
- iss-388roadmap phases README states itd-88 is in planned/ and unscheduled, but the intent has shipped — a false bucket claim in present-tense current-state prose
- iss-389the examples-use-reserved-identifiers principle still says a fixture-identifier lint would make it a discipline — the allowlist-inversion lint shipped (iss-154) and cites the principle by name, so the Promotion paragraph misdirects an agent to build an existing rule
- iss-390the pre-decided promotion of examples-use-reserved-identifiers to a discipline-kind intent never happened — the iss-154 lint shipped, the principles README contract says a mechanical gate promotes the principle, and no discipline intent exists
- iss-391research notes README routes phase-scoped research to research/phase/N/ and names research/adr/ as a sibling — both layouts adr-30 rejected and the gated research-children index denies — and its Related display texts sit one level short of their hrefs
- iss-392bughunt round-3 confirmed nitpick batch — zero-padded record-id filenames evade the id-uniqueness lint in all three families; the go-version lockstep test skips .yaml workflows; scripts/*.sh lack the eol=lf pin the repo's own policy states; agents/CHANGELOG announces lifeboat-reviewer 0.1.1 while the prompt carries 0.1.0; five live records still route to the pre-flattening commands/abcd/ and retired docs/reference pages
- iss-2608210737260468The intent (itd) and spec (spc) families still mint via the legacy max+1 refs-union allocator; adr-45 ruling 3 schedules their adoption of the timestamp-numeric mint seam as configuration — a swap of the allocation call in the intent and spec stores onto the shared recordid seam, retiring their MaxAcrossRefs scans and mint warnings — after the captures family has run the scheme for a release cycle (itd-114 ac-6's Given clause). This is the tracker so the rollout's second family is not forgotten once that cycle completes
- iss-2608210737264758The optional forge-backed allocator (itd-114 ac-5) is deferred by recorded ruling — spc-33 names it a later adapter behind the same mint seam, adr-45 ruling 4 fixes its posture (allocates and never stores per itd-129's ledger-canonical line; offline falls back to native loudly) — but no open work item holds the seat, so nothing tracks building it. The fidelity verdict on itd-114 carries the criterion as NOT_MET/deferred-by-ruling; this capture is the deferred work's ledger seat, builds on itd-129's adapter seam when that lands
- iss-2608210737265820intent audit ingest appends the INGESTED verdict block at end-of-file, so when a shipped intent carries link-reference definitions after its Audit Notes heading (itd-114: the iss-80 link ref) the block lands below them — rendering fine but visually detached from the Audit Notes section it belongs to. The writer should insert under the Audit Notes heading (or above trailing link-ref definitions) rather than appending at EOF
- iss-2608210737265933Two accepted mint residuals recorded so future hunts do not rediscover them as findings (spc-33 bounds-and-residuals section; surfaced by the pre-PR security review of the itd-114 delivery): (1) recordid's fileID rebuilds an id from the parsed integer, so a timestamp stamp with a leading zero — reachable only from a host clock in 2000-2009 or from 2100 onward — resolves to a different id than its filename claims (the year-2100 horizon the spec accepts); (2) the mint's rejection-sampling loop is uncapped, safe today because entropy is crypto/rand or an injected test reader that EOFs, but if Minter.Entropy ever becomes configurable from env/config/flags the loop needs an iteration cap. Neither has an attack path under the current wiring
- iss-2608210738363966The attribution gate (scripts/check-attribution.sh) is CI-only: no local hook mirrors it, so a commit whose git AUTHOR/COMMITTER is an AI identity (Claude <noreply@anthropic.com>) is only caught in CI, where it presents as an unmergeable-looking PR (a failing required check), not a merge conflict. The pre-commit hook runs only the name-guard; make preflight / the pre-push hook run record-lint + docs-lint + reviews-charter but NOT check-attribution. This cost a full diagnosis on #391 (AI-authored cloud-routine commits) and a reauthor+new-branch repair (#402), because force-push to fix in place is refused by policy. Fix: mirror check-attribution into the pre-push gate (as make preflight already mirrors record-lint), so an AI author identity or a forbidden Generated-by/Co-Authored-By footer fails locally before the round-trip. See memory cloud-routine-git-identity; relates itd-91.
- iss-2608210738367948New-repo / ahoy setup does not establish the git identity autonomous routines commit under. ahoy DETECTS a mismatch between the working git user.name/user.email and the committed identity pin (.abcd/config/identity.json, iss-62) but never SETS the identity, and nothing configures the human identity for an autonomous cloud routine's environment — so a routine defaults to Claude <noreply@anthropic.com> and every commit it makes fails the attribution gate (see attribution-gate-has-no-local-mirror). The ahoy/onboarding gap for a repo that will run routines: scaffold or verify the routine-environment git identity (git config user.name/email, or GIT_AUTHOR_*/GIT_COMMITTER_* env) so routine commits are authored by the human of record from the start. Bridges iss-62 (identity pin), itd-91 (declared AI-attribution preference), and the cloud-routine-git-identity memory. Candidate ahoy-install sub-step or a new-repo setup check.
- iss-2608210738378295Local record gates validate the WORKING TREE, not the committed/pushed tree, so a partial commit passes them while the committed tree fails CI. Demonstrated live this session: git mv staged a rename (iss-370->377) but the follow-up sed edit to the frontmatter id was left unstaged; git commit captured only the rename, so the committed file had filename iss-377 with frontmatter iss-370 — a record_schema blocker. record-lint had passed at commit time because it reads the working tree (which held the sed edit), and the pre-push make preflight passes for the same reason (the unstaged edit is still present); only CI, checking out the commit, sees the divergence. Fix direction: run the push-time gate against the tree that will actually ship (e.g. a clean worktree of HEAD, or git stash --keep-index before linting), so a working-tree/index divergence cannot pass locally and fail CI. Sibling of iss-147 (guard-load reads guard.json from the working tree).
- iss-2608210923436594User-local agent memory is an unarmed, non-portable convention store: several working conventions (attribution footer handling, cloud-routine git identity, citation integrity) live only in one developer's per-project memory, so abcd works here partly because that memory compensates — and none of it travels to other users' managed repos. abcd already owns the portable homes (the bundled rules domains, .abcd/development/principles/, the per-project .abcd/memory/ substrate, validators); what is missing is the deliberate graduation loop: a convention that appears twice in local memory is a candidate for a rules-domain line, a principle, or a validator, and nothing currently prompts that promotion. Same shape as the itd-114 lesson — safety must live in the tool, not in every minter's prompt or any one user's memory
- iss-2608210923437502The bundled COMMITTING rules domain (the defaults every managed repo inherits from the binary) says Assisted-by-not-Co-Authored-By but omits the two attribution failures that keep recurring operationally and are currently patched by per-agent memory and per-routine prompt text: (1) the harness auto-appends a Generated-by footer plus session link to PR bodies and issue comments it creates — the domain should instruct the post-write read-back-and-strip (iss-178 remedy a, as an injected rule rather than every routine prompt re-carrying it); (2) autonomous runs default their git identity to the tool, which the attribution gate rejects (iss-193's class) — the domain should name the commit-as-the-human requirement. Prevention rung, complementing iss-178's detection remedy b; prompt-carried and memory-carried safety is the anti-pattern itd-114 just retired for minting
- iss-2608210923438110Citation-integrity conventions exist only in one user's local agent memory, not in the record or the cite/ingest surfaces — any other agent building a references baseline in a managed repo would repeat both corrected mistakes: (1) admitting entries with initial-only author names plus a to-be-checked caveat when the entry's own URL/DOI would resolve the full names in one fetch (caveats are for genuinely unreachable facts, not skipped lookups); (2) taking author names from anywhere but the publisher's CURRENT record — a published name that has changed must never be reverted to the former name (the maintainer flagged a live near-miss hard). Both belong in the product: a convention note for docs cite / ingest now, and a validator rung on the ingest metadata extraction later
- iss-2608210932052003abcd launches autonomous bug hunts (and other routines) for the user, opt-in — beyond handing the user a prompt to paste into a cloud routine. Today the bughunt is a Desktop prompt the user wires into an external cloud routine by hand; the direction is abcd owning the launch: the user opts in, and abcd assembles and starts the routine, applying the run contract it already governs (the human git identity per itd-131, the gates, the merge decision, the state issue). This is the realisation of the run seam — adr-27 (run is a pluggable seam, not a bespoke engine), itd-29 (the run operator surface: start/status/pause/resume/ship), itd-107 (routines assemble from one versioned template; the bughunt and a delivery-pipeline archetype), and the reframed iss-381 (the deterministic delivery pipeline survives as an itd-107 archetype, not an engine). When abcd launches the routine it sets the human git identity at launch, which is the clean mechanism the itd-131 identity gate points at for routine commits (vs today's prompt/env workaround). Big, cross-record capability — needs decomposition and likely ideate before it is filable; recorded so the direction is durable.
- iss-2608210934566220The six bundled OPINIONS rules each end with a pointer to a file under .abcd/development/principles/ that exists only in the abcd repo itself — a managed repo inherits the injected lines verbatim, so every prompt whose recall matches the domain hands its agent six dangling references (the principles corpus is not part of adoption). Either the bundled lines need self-contained phrasings with the pointer marked as abcd-repo-only, or adoption (prepare-this-repo / ahoy) should ship a distilled principles set the pointers can resolve against. Found while adding the memory-graduation rule, whose line was written self-contained for exactly this reason
- iss-2608210934566221Relocate the hook binary and .binary-meta from the plugin cache dir to the harness persistent data dir (CLAUDE_PLUGIN_DATA, ~/.claude/plugins/data/abcd-abcd-marketplace/). The harness re-clones every update into a fresh commit-stamped cache dir and its docs state extra files there are NOT preserved across updates, so the ~11MB binary is re-fetched on every plugin update by design. The data dir survives updates and is deleted only on full uninstall. Fixes in one move: the per-update re-download, the SessionEnd bootstrap-cancellation window, per-version binary disk copies (orphaned cache dirs are GC'd ~14 days after .orphaned_at), and the PATH-symlink rot captured separately. Reworks the itd-105/spc-21 bootstrap fast path and every pluginBinaryPath consumer.related itd-132
- iss-2608210934566222The pinned PATH symlink written by ahoy install targets pluginBinaryPath(pluginRoot) — a commit-stamped plugin cache directory. Every plugin update orphans that directory and the harness garbage-collects it ~14 days after .orphaned_at, so for a marketplace user the ~/.local/bin/abcd symlink silently dangles within two weeks of every update. The heal path (symlink.dangling gap + re-running ahoy install) exists but nothing triggers it automatically. Fix follows the persistent-data-dir relocation: point the pinned symlink at the data-dir binary, whose path is stable across updates.related itd-132
- iss-2608210934566223The SessionEnd hook attempts the blocking bootstrap download before falling back to a PATH binary. After a plugin update lands a fresh binary-less cache dir, an update-then-quit exits through SessionEnd, which starts the ~11MB download, gets cancelled by the harness during shutdown ('Hook cancelled'), and silently drops that session's transcript capture — observed 2026-08-21, session 8db3dbd6 lost. Exit is the one hook with no time budget: reorder to plugin-root binary, then PATH binary, then loud give-up, and never bootstrap at SessionEnd. The persistent-data-dir relocation shrinks the exposure to true first-install-then-quit, but the ordering fix stands on its own.
- iss-2608210934566224Session-end transcript capture is best-effort and its loss is silent: a cancelled or killed SessionEnd hook (update-then-quit, crash, SIGKILL) leaves no trace that a session was never captured into the history store. Add a recovery sweep — at session start or in ahoy doctor — that compares harness transcripts against the history store index and reports (or captures) the gap, turning silent loss into a caught-on-next-start notice. abcd history capture already ingests retroactively.
- iss-2608210934566225The harness statusline is a user-level setting no plugin can inject, but ahoy install could offer it as an owned transparent-confirm ConfigChange (same pattern as the PATH symlink): point statusLine at a new 'abcd statusline' verb consuming the harness stdin JSON and appending guard health, version skew, and update-available. Event-driven refresh (300ms debounce, min 1s interval) rules out live download progress; steady-state health only.
- iss-2608210934566226ADR to draft at itd-132 planning (SPLIT-routed trust rule): binary persistence must not weaken the spc-21 verification posture. Whatever shape itd-132 takes (relocate-execution or download-cache+copy), the fetch-time invariants carry over verbatim — same-origin checksums.txt, HTTPS pin with -q-first curl, proxy/CA env unset, no environment seam for origins — AND the at-rest window is addressed: under the cache model a tampered binary survived at most one update cycle; a persistent location extends that window unboundedly unless the recorded binary_sha256 is re-verified at adoption/refresh points. Companion brief invariant: SessionEnd performs no network work. Route: ADR + brief invariant, filed with the itd-132 spec.
- iss-2608210934566227Principle to draft at itd-132 planning (SPLIT-routed stance): store durable state where the platform documents it survives — never fight the host lifecycle inside a directory the host re-clones or garbage-collects. Surfaced by the 2026-08-21 plugin-update post-mortem (binary in the re-cloned cache dir). Candidate home: .abcd/development/principles/. File alongside the itd-132 spec.
- iss-2608210934566228spc-35 BLOCK (security review): the cache promotion 're-verify against recorded binary_sha256' is a corruption check, not a tamper check. The cached artefact and its binary-meta (holding the expected hash) both live in ${CLAUDE_PLUGIN_DATA}/cache, equally same-UID-writable. An attacker writing BOTH — payload plus a meta recording its hash and the current release_tag — passes the promotion gate and gets an unverified binary installed at the guard path and onto PATH, with the success notice asserting 'checksum-verified'. Demonstrated end-to-end vs live v0.6.1. This is exactly adr-46's central claim: on main a poisoned plugin-root binary healed at the next update (harness re-clones a fresh root -> bootstrap re-downloads+verifies from GitHub); here the poisoned cache is preferred over the network indefinitely and survives every update. adr-46, invariant 12, and the notice assert a protection the code does not provide. Fix: in cache mode (which already resolves the latest tag over the network) GET that release's checksums.txt and verify cached_sha against the PUBLISHED digest before use_cache=yes — restores tamper-evidence online, offline stays corruption-only (document honestly). Plus the missing test: TestBootstrapCorruptCacheRefusesLoudly rewrites only the artefact, never the meta, so it never exercises the case that succeeds.
- iss-2608210934566229spc-35 BLOCK (security review): the migration seed re-opens the mv-onto-directory hazard the main path already refuses. The seed fast-path test is '[ ! -f "$cache_binary" ] || exit 0', which is TRUE for a directory at that path. So 'mkdir -p .../cache/abcd-<os>-<arch>' (one same-UID command) makes the seed 'mv -f' the file INTO the directory (succeeds) and write a lying binary-meta -> every fresh plugin root then downloads ~11MB and hits refuse, so shell commands run UNGUARDED, every session, until a human removes the directory by hand — and this survives every plugin update. Demonstrated (exit 0, no message). Fix: the migration path needs the '[ -e "$cache_binary" ] && [ ! -f "$cache_binary" ] -> refuse' form already used at the main install site (bootstrap.sh:409).
- iss-2608210934566230spc-35 FIX-FIRST (ruthless review): replacing the PATH symlink with an owned regular-file copy severs the executable-ancestor route back to the plugin root, so every plugin-root-dependent verb no-ops when abcd is invoked BY NAME from a plain terminal — which is where bootstrap.sh itself tells the user to run 'ahoy install', and where 'abcd update' runs. Root cause: CLAUDE_PLUGIN_DATA is exported only to hook processes, not terminals (itd-132 records this). Two failures: (1) resolvePluginRoot() walks the copy's ancestors (~/.local/bin -> ~ -> /Users), none has hooks/, returns ('',false) -> Detect emits plugin.root_missing, Install/version/staleness no-op (store.go:96-108; store_symlink_test.go pins the OLD symlink mechanism and stays green only because it builds the symlink by hand, not via ahoy install). (2) path-entry lives in the data dir resolved solely from CLAUDE_PLUGIN_DATA (data_dir.go:12), so from a terminal isOwnedCopyFile is false -> uninstall leaves the binary ('not a symlink; left untouched'), abcd reports its OWN binary as symlink.foreign, and abcd update's RefreshPathEntryDigest no-ops so path-entry desyncs permanently. Contradicts AC 4 and the CHANGELOG. Fix (ruthless): record plugin_root= in the provenance and add it as a resolvePluginRoot candidate; write the provenance to a home-scoped abcd-owned location derivable from the installed copy, consulted when the var is absent; extend store_symlink_test.go with the copy layout; update commands/ahoy.md + docs/reference/cli/commands.md (still say 'symlink'). Note the recorded plugin_root is itself a GC'd cache dir, so the hook-side bootstrap must rewrite it on each provision.
- iss-2608211132061930lint.LoadConfig reads the docs-lint/record-lint config with a raw os.ReadFile — no O_NOFOLLOW, no regular-file check, no size cap — while its .abcd/*.json siblings guard.Load, rules.Load and positioning.LoadConfig all guard the read as a trust boundary. The read is hook-reachable (ahoy.Detect via hook session-start/end) and cross-repo-clonable, so a committed .abcd/docs-lint.json symlink to a FIFO wedges abcd docs lint / lint / ahoy / hook / cite refresh and the record-lint CI leg, a /dev/zero target OOMs the CLI, and an out-of-repo symlink target runs the entire ruleset from a file the repository does not own (gate substitution).
- iss-2608211134281912Four untrusted-operand stdin readers (readIdeatePayload, readLessonsPayload, readSynthesisPayload, readSource) read exactly cap bytes via a bare io.LimitReader(cap), so an over-cap '-' payload is silently truncated into a severed prefix instead of refused, while each reader's file transport (readGuardedOperand) refuses the same bytes with fsutil.ErrTooBig. Worst on the history capture path: history.Capture performs no parse and no cap check, so an over-cap stdin transcript is stored as an 8 MiB prefix, reported 'stored', under a sha256 idempotency key computed over the prefix — breaking spc-4's refuse-whole invariant. Also lets an over-cap ideate verdict past both the MaxPayloadBytes cap gate and the dec.More() trailing-data gate at a crafted boundary. Unswept siblings of resolved iss-201/iss-347; every site's doc comment claims stdin parity with the file cap.
- iss-2608211139076040The iss-392 canonRecordID fix canonicalised four record-id-uniqueness scan sites but missed the sibling sites sharing the same keyspace: deliverystate.go keyed the intent bucket map and its CHANGELOG citations on the raw id spelling (so a zero-padded intent filename or citation silently failed the drafts-citation delivery_state gate open), speclinks.go/KnownIntents and the superseded_by (lint.go) and spec intent-existence (lint.go validateSpec) lookups keyed/looked-up raw (false-blocking a padded twin), and spec_id_unique keyed on the raw frontmatter id (fail-open on a padded spc twin, the very hole iss-392 claimed to close for 'all three families'). The playbook's second spine: a pattern fixed at 4 of N sites leaves N-4 latent.
- iss-2608211140410761abcd <id> ADR dispatch (record.go describeADR) confirms the frontmatter id with a byte-exact 'fields["id"].Value != id' compare (frontmatter.Field.Value is TrimSpace-only, quotes not stripped), while record-lint schema.go compares parsed handles (a tested tolerance, TestRecordSchemaFilenameIDComparesNumerically) and the citation resolver rebuilds ids from the parsed integer. So an ADR written id: "adr-12" (quoted), adr-0012 (padded), or ADR-12 (cased) is lint-green and citation-resolvable but abcd adr-12 reports 'not found'. A live facet against the shipped corpus: abcd adr-0003 (padded, admitted by IDRe) routes to the file then refuses. Second site under iss-285's quote-normalisation-split principle.
- iss-2608211142142469The release-gate runbook describes the semantic-receipt gate as 'Dormant until the public flip' (README.md blockquote) and phrases arming as a future condition ('Once the fail-closed verify rule is armed, the tag is rejected'), but the repo is public and the gate is armed and fed receipts on every release — it has fail-closed two: v0.3.0 (iss-108, the self-reference defect) and v0.6.0 (iss-326, a missing receipts commit, leaving a permanently unpublishable tag). The runbook a maintainer follows at tag time thus tells them receipts are not yet required, which is iss-326's proximate cause. It also misstates the failure mode ('the tag is rejected' — the tag survives, anti-tag-move; the publication is refused) and self-contradicts at the adjacent parenthetical ('dormant... never exercised' vs iss-108's v0.3.0 firing). Inverts the enforcement-claims-are-facts principle (an under-claimed live gate).
- iss-2608211142146585The release-gate runbook (.abcd/development/release-gate/README.md) misdescribes release.yml's verify job in two present-tense claims a maintainer reads at tag time. (1) It says the verify job runs the nine gates 'on macOS + Linux', but release.yml's verify job is runs-on: ubuntu-latest with no matrix — Linux only; the macOS coverage is ci.yml's check job. The gate_lockstep record-lint rule mirrors only the verify STEP NAMES, never runs-on, so the platform claim is outside its reach. (2) 'The verify job gates the merge' is false: verify runs post-merge on the tag/workflow_call; ci.yml's required checks gate the merge. Doc-accuracy family of resolved iss-182.
- iss-2608211142496517cmd/scaffold-sync/main.go's package doc comment states the command is 'run by the scaffold-sync workflow on a dependabot branch', but no such workflow exists or ever existed: the string appears nowhere in .github/, and iss-209 records that a workflow_run automation was built and rejected in review (a GITHUB_TOKEN push raises no events, leaving the PR permanently pending; and it was unsound). Makefile:72-76 states the opposite outright ('Nothing in CI calls either target'). The false claim misdirects whoever debugs a red TestSelfScaffoldParity to wait for automation that will never run or re-attempt the dead end iss-209 exists to stop.
- iss-2608211143184945README.md's Go badge advertises 'Go 1.25' while go.mod declares go 1.26.7 and every CI/release pin is 1.26.7; CHANGELOG records the deliberate move to 1.26 for support-window reasons. The badge is the front page's only toolchain statement, and 1.25 is a version the project just retired for security. GOTOOLCHAIN=auto self-corrects a from-source build, so harm is bounded, but the front page contradicts a deliberate security decision. The go-version lockstep test walks .github/workflows only, so no gate covers the badge.
- iss-2608211143185943README.md described abcd capture as minting records 'with the next free id' — the proper name of the max+1 allocation protocol that adr-45/spc-33/itd-114 abolished after live collisions (one costing a release re-cut). 'Next free id' is the codebase's own name for the retired mechanism (recordid.MaxAcrossRefs, lint.go). The README is the only public document still describing it, setting the wrong mental model (small sequential successor-comparable ids) and legitimising the hand-add-at-max+1 path iss-74 identified as a collision source. Written 2026-08-17, pre-rollout.
- iss-2608211144265046commands/lint.md documented repolint JSON findings as carrying 'a file and line (line 0 means the finding is not tied to one line)', but repolint.go tags Line as json:line,omitempty so a zero line is omitted entirely, never emitted as 0. Line-less findings are the majority (only docs-currency/privacy-hygiene/identity-positioning set Line). An agent following the doc and testing line==0, or formatting file:line, produces file:undefined. The brief 16-lint.md carries the true contract but named only two line-carrying rules, omitting identity-positioning (rule_positioning.go also sets Line). commands/prepare-this-repo.md implied the same line sentinel.
- iss-2608211144555085The ADR index (.abcd/development/decisions/adrs/README.md) ends at the adr-44 row while adr-45 is accepted (2026-08-20) and cited as settled law by six live records (the invariants brief, itd-114, spc-33, .abcd/work/issues/README.md, two open issues, DECISIONS.md). 37 ADR files vs 36 index rows — exactly one missing. The index is the declared hand-maintained roll-call (adrs/README.md) and is not among index_drift's four registered indexes, so it is structurally ungated. Third recurrence of this class in the same table (after resolved iss-296 and iss-374), which iss-38's decision (hand-kept indexes must be deleted or gated) predicts.
- iss-2608211145448208adr-43 (accepted 2026-08-19) decided 'No CLA, and no DCO' and named as its own consequence 'the DCO deferral text retires from every surface that carried it', but the deferral survived in two live surfaces the ADR's landing commit did not touch: AGENTS.md (symlinked as CLAUDE.md/GEMINI.md, injected into every agent session) said 'A human-only Signed-off-by: (DCO) is deferred to the public flip or the first outside contribution', and scripts/check-attribution.sh carried it twice — a comment and the runtime error text shown to a contributor whose commit trips COAUTHOR_RE — stating the false premise that the repo defers DCO until it goes public (it is already public). CONTRIBUTING.md already says 'no CLA and no Signed-off-by requirement', so the surfaces contradicted each other.
- iss-2608211146222734The retired pre-adr-30 path literal 'roadmap/intents' — a record-lint blocker token (moved-intents-path: 'intents live at intents/') — survived in AGENTS.md and .abcd/README.md, the two canonical where-things-live maps, both outside record-lint's roots (.abcd/development) so the armed token is structurally blind to them. Read in context beside the real nested path decisions/adrs, the slash reads as a path separator, i.e. the banned pre-adr-30 layout. A 2026-07-06 review already adjudicated both sites stale (fix #6). CLAUDE.md is a symlink to AGENTS.md, so the line is injected into every agent session and risks an agent propagating the banned path into development/ where it is a live blocker. Live instance of open iss-279's detector gap (banned_tokens cannot reach AGENTS.md/CONTRIBUTING.md).
- iss-2608211146562243RD001 is documented as unconditional in both definition sites (.abcd/work/reviews/README.md and brief/05-internals/06-lint.md name only the root README as exempt), but scripts/check-reviews.sh exempts 40-hex sha-keyed semantic-gate receipt directories — 7 of the 10 live review directories. The exemption is principled and recorded elsewhere ([dcn-2607180000000001](../../decisions/dcn-2607180000000001-the-iss-35-semantic-release-gate-was.md), spc-14, itd-93 acceptance criterion), but a reader auditing the folder against either charter sees 7 apparent blockers, and 06-lint.md says the rule 'ports into internal/core/lint', so an implementer working from the record alone would port it without the exemption and turn the gate permanently red.
- iss-2608211147403129The ADR-RFC pairing contract disagreed across three surfaces. adrs/README.md declared RFCs carry 'related_adrs: [adr-N, ...]', but rfcs/README.md (the RFC frontmatter spec and its bidirectional table) defined no such field; and rfc-2 carried 'spawned_from: adr-43' — a field rfcs/README.md documented as itd-N only — while omitting spawned_intents/related_intents/authors/related_adrs, so adr-43's declared pair (related_rfcs: [rfc-2]) was one-sided. The RFC store is ungated (record_schema registers adr/itd/spc/iss only). rfc-2 was the sole outlier in the two-file store; landed with adr-43 (2026-08-19) with no recorded follow-up. Structurally identical to resolved iss-360 (adr-7 outlier).
- iss-2608211432254405launch scaffold deriveBranch assumes .git is a directory and reads HEAD/origin-HEAD with raw os.ReadFile, so in a linked worktree or submodule (where .git is a gitfile) both reads fail and it stamps the fallback branch main into the generated release workflows, leaving the release gate silently inert on a non-main-default repo
- iss-2608211432257954launch --dry-run leaks a cwd/home-rooted absolute path into lockstep.detail and would_refuse_on when a pinned manifest is unreadable, violating the no-absolute-paths-in-machine-output norm; the dry-run is a success envelope so scrubPaths never reaches it
- iss-2608211432258689launch --dry-run prints WouldRefuseOn with %v and no termsafe.Sanitize, so a committed repo filename carrying raw terminal escapes reaches the terminal and CI log (sibling of iss-259/iss-264 at an unrecorded site)
- iss-2608211432258975abcd lint maps a rule-engine fault to exit 1 which its documented Conftest tri-state reserves for warnings-only, so a CI gate keying on exit>=2 reads a lint that never ran as an advisory pass (fail-open)
- iss-2608211432384091README claims every non-SessionStart hook self-bootstraps, but the SessionEnd hook deliberately never downloads the binary (pinned by TestSessionEndNeverBootstraps); the universal is false for SessionEnd
- iss-2608211432384430history Capture/List reject an invalid rootSHA with a message naming only 40 chars though rootSHARe accepts 40 or 64 (SHA-256); the diagnostic contradicts the widened regex
- iss-2608211432389181readVerdictFile does Lstat-then-os.ReadFile with a comment claiming the swap window is not a symlink escape, but os.ReadFile follows a swapped-in symlink and ignores the size cap; it is the last CLI-operand reader not routed through fsutil.ReadGuarded
- iss-2608211432389477commands/memory.md writes the citation field as source.class (a nonexistent nested path) though the JSON key is the flat source_class
- iss-2608211432389791commands/ahoy.md enumerates install_mode as three values but detectInstallMode also appends a (shadowed on PATH) suffix, so the documented value list is incomplete
- iss-2608211432482363rfc-1 declares related_intents itd-26 but itd-26 has no reciprocal related_rfcs, a one-sided pair the RFC bidirectional convention expects (last unswept half after round-4 rfc-2/adr-43 fix)
- iss-2608211432483805the .abcd/work tier roster in AGENTS.md and .abcd/README.md names only CONTEXT.md and DECISIONS.md, omitting the committed issue ledger (adr-32), reviews, and rulesets that also live there
- iss-2608211432489288two backticked bare relative paths point at directories that do not exist (decisions/adrs/README roadmap/rfcs and intents/README decisions/adrs), invisible to links_resolve
- iss-2608211432489481seven markdown links across the record carry a backticked display path that does not resolve from the containing file while the href does, evading links_resolve (recurrence of iss-391)
- iss-2608211849461061frontmatter.Fields requires --- on line 0, so a comment-led record file bypasses the no_git_metadata blocker (13 glossary term files)
- iss-2608211849463840docs-lint/record-lint main walk lacks the root containment and guarded read its sibling citation collector applies to the same cfg.Roots, so a cloned repo reads and lints files outside the repository
- iss-2608211849466878citation DaysBetween reads local calendar date then restamps UTC, so citation staleness and the release-gate overdue blocker depend on the maintainer timezone
- iss-2608211849467013guard tokenizer does not recognise redirection operators, so gluing >file onto a token silently downgrades a Tier-1 block to allow
- iss-2608211849468791attribution gate trailer/None regexes are dollar-anchored over a class excluding CR, so a CRLF pull-request body false-reds the required attribution check
- iss-2608211849580624README provisioning section describes download-on-every-update, but spc-35 shipped a persistent CLAUDE_PLUGIN_DATA cache that provisions by verified copy; the .binary-meta deletion remedy is also a no-op on cache-provisioned roots
- iss-2608211849581263brief 05-personas.md says the persona picker chooses at random, contradicting personas.json and itd-79 (selection is by role, never by name); a live residual of resolved iss-300
- iss-2608211849582190CONTRIBUTING grants the fenced-quotation carve-out for commit messages and pull-request bodies alike, but the gate strips fences on the body arm only, so a fenced footer in a commit message still fails CI
- iss-2608211849583208the bundled INTENTS default rule (Personas are always Alice, Bob, Carol) reaches abcd own intent authors because .abcd/rules.json never overrides INTENTS, contradicting the armed 14-persona registry
- iss-2608211849583757brief 05-personas.md roster lists thirteen personas, omitting Nia; the registry has fourteen and Nia is in live use
- iss-2608211850070318abcd history list --json emits bare null on an empty store while the command doc promises an empty list
- iss-2608211850070541abcd identity init maps a structural fault to exit 1 (the rendered-refusal code) while its sibling verbs and the tree-wide usage-error contract use exit 2; init renders nothing on that path
- iss-2608211850074600lifeboat SourceContext.ReadFile sizes with fstat then reads exactly the cap, so a file that grows past the cap between check and read is silently truncated to a prefix rather than refused
- iss-2608211914592726residual config-derived os.ReadFile sites in internal/core/lint read cloned-repo-controlled paths without the containment/guarded-read stack the roots and glossary walks now use: persona.go registry, lint.go spec-doc and record-store reads, speclinks.go, contextcurrency.go, deliverystate.go changelog, indexdrift.go, subverbs.go snapshots. Triage each by attacker-controllability under a cloned repo and guard those in scope
- iss-2608220131352917guard tokenizer misses the ampersand redirection operators &> and &>> so a glued or spaced &>/dev/null splits the simple command and drops the dangerous flag out of command position, a silent allow on every blocker-tier entry
- iss-2608220134344680record-lint frontmatterOpen and frontmatter.Fields anchor on line 0 and TrimSpace does not strip a UTF-8 BOM, so a BOM-led or multi-line-comment-led record yields an empty field map and slips the no_git_metadata blocker and the record_schema id/supersession gates entirely
- iss-2608220136593438ahoy classify tests .git with isDir, so a linked worktree or submodule (where .git is a gitfile) is misread as unmanaged-folder, every gap detector is skipped, and ahoy install exits 0 aborted with a wrong not-a-git-repository reason; the last isDir(.git) holdout after iss-72
- iss-2608220136597127ahoy DetectionResult.Guard is a value field with a plain json tag but is only assigned for a managed repo, so an unmanaged folder serialises a never-computed all-false GuardHealth (a broken guard) beside plugin_root_status resolved; the Banlist sibling is already a pointer with omitempty for this reason
- iss-2608220142154022update.Plan dispatch switch has no default case, so an unrecognised UpdateTargetKind falls through the return nil permissive branch of a mutating refusal gate to fetch-and-swap, against unrecognized-input-never-writes; UpdateTargetFile is now an explicit case and any other kind a named refusal
- iss-2608220142158516abcd update and abcd history list/show/capture leak absolute home-rooted paths into their success/refusal envelopes (text and --json) because the CLI scrubPaths runs only on the error value; the update refusal detail fires on the documented plugin-session path and the plugin relays target_path into agent chat
- iss-2608220144233519repolint privacy scanner readTrackedFile reads io.LimitReader(f, maxScanBytes) with no cap+1 probe, so a tracked file that grows past the cap between fstat and read is scanned as a truncated prefix and reported clean, bypassing the not-scanned warn channel the same file over-cap at stat would take
- iss-2608220145356167abcd docs lint returns a bare engine error which cli.Run maps to exit 1, the same code as a blocker finding, while abcd lint and record-lint exit 2 for an engine fault; a consumer keying on exit >=2 reads a docs lint that never ran (a config containment refusal) as an ordinary findings-pass
- iss-2608220147106835abcd spec/intent/memory (and capture recent_open) emit bare null for empty --json collections instead of [], contradicting the class-wide invariant history list fixed; a consumer iterating the value (jq .[], an agent following the command doc) errors on null
- iss-2608220148289898record.describeADR routes ADR filenames by a fixed %04d- prefix, so an ADR file with non-four-digit padding (00099-, 77-) is lint-green and citation-resolvable but reported not-found by abcd adr-N; the filename-ordinal residue of iss-2608211140410761 which fixed the frontmatter-id half; spc-26 spec line amended to numeric-ordinal probe
- iss-2608220149008905external-review.yml suppresses zizmor dangerous-triggers on its pull_request_target trigger, so the safety invariant it states in prose (PR code never checked out) is unenforced; a later checkout added to that job passes every zizmor persona, a pwn request; add a Go test asserting no pull_request_target workflow checks out code
- iss-2608220150151397brief 01-product/03-mental-model.md claims the corpus has zero live bundles and points at retired-bundle history, but four planned intents (itd-20/24/63/69) declare bundle-member of spc-83-operator-surfaces and intents/README heads it Active bundles; residual of resolved iss-123 which fixed the README half only
- iss-2608220150152332AGENTS.md and CONTRIBUTING.md describe the CI check job as unconditional but since the inert-path classifier landed a docs/.abcd-only pull request stands the macOS leg, race lane, zizmor, govulncheck and smoke down; the merge-queue run still runs the full set so nothing ships under-verified
- iss-2608220150152535docs/requirements.txt line 1 claims pinned so every site build renders docs identically but only mkdocs-material is pinned; every transitive dependency floats from PyPI at build time so two builds of one commit can render differently and dependabots pip cooldown never sees the transitives
- iss-2608220150154972commands/version.md tells the agent to report install_mode from the JSON but the field is json omitempty and absent whenever no abcd-owned PATH entry is resolvable (fresh install, foreign/dangling entry, unresolved plugin root), so an agent following it reports a missing field or invents one
- iss-2608220150157497principles/sota-per-intent.md links `[adr-22](../decisions)` and `[adr-26](../decisions)` to the decisions directory instead of the ADR files; links_resolve passes because the directory exists; the only two ID-labelled links in the record whose target does not match the id
- iss-2608220150157498Eight typed cross-references point at targets absent from the tree — adr-22 supersedes adr-14, adr-15 and adr-17; adr-25 supersedes adr-8; adr-27 supersedes adr-16; adr-28 supersedes adr-18; adr-35 supersedes adr-4 (all retired under retire-the-name); itd-3 names spec_id spc-1 which has no file — and nothing checks supersedes targets today. The 2026-08-21 site investigation counted six; the in-session grep found eight. The planned site build arms the detector via the .abcd/site-baseline.json ratchet, seeded with what the build finds, and the tombstones-or-stubs question (itd-136/itd-137) decides how they renderrelated itd-160
- iss-2608220150157499The spec link is recorded from both ends (intent spec_id and spec implements, 30+ pairs) and 20 related_* pairs are listed in both files, so the record's 278 stored typed references are 226 distinct links. Harmless today, but every consumer that renders or counts links must collapse mirrored references or double-count; the site build is the first such consumer
- iss-2608220150157500Issues carry no typed cross-references at all — only body mentions — so any typed-link rendering (the site's by-links arrangement, but equally any future record tooling) shows the entire issue ledger as unlinked. If issue-to-record links are wanted, the capture and resolve verbs are where they would be recorded
- iss-2608220150157501One early commit carries the tool name in the git author field (pre-dating the Assisted-by policy) and two commits are dependabot; any contributors rendering from git history needs an explicit rule labelling bot and tool author rows separately from the humans who are authors of record, or the pre-policy commit silently appears as a human contributor
- iss-2608220150157502Cloudflare non-production branch builds run only the version command, so branch previews repeat the production build instead of building the branch — observed and recorded as comments in wrangler.jsonc. The adr-48 deploy design replaces these with a labelled preview deployed from Actions on push to main and turns Cloudflare's automatic production builds off
- iss-2608220150157503The docs toolchain is on a closing maintenance window: MkDocs 1.x has had no release since August 2024, Material for MkDocs announced maintenance mode in November 2025 (critical bug fixes and security updates for 12 months at least, no new features), and MkDocs 2.0 removes plugins entirely. An SSG decision (Zensical, Hugo/Hextra, or other) is due as an ADR before the window closes, around November 2026; adr-47 keeps generation outside the SSG so the migration touches only mkdocs.yml, overrides and the build command
- iss-2608220150157504Two external artefacts point at retired names and paths: the project workspace description names the repository under its pre-transfer owner, and the July landing-page asset links that owner and docs paths that no longer exist (docs/reference/commands.md, docs/reference/facilitator.md). Neither is in this tree, so no in-repo detector can arm; fixing them is a maintainer act in the external workspace
- iss-2608220150157505The brief's press release (brief/01-product/01-press-release.md) tells the lifeboat story while README tells the product-thinker story the landing page will render; the brief already records the divergence as an open question. The site follows docs/, so the question does not block the site work, but the two front doors describe different products until it is answered
- iss-2608220150157506A standardised README split (contributor page on the code host, product story on a rendered site) for every managed repo was proposed and adversarially reviewed the same day: four fatal hits against the imposed-standard framing, reframed to offered-never-imposed — a scaffold-time contributor-README template proposed as a human-adopted diff, structure held per-repo via registered positioning.json surfaces, and no convention language until abcd's own split has shipped and a second managed repo has adopted it (itd-140 rule 3). The review is the dated 2026-08-22 research note; graduation takes the full idea-admission gauntlet with abcd's shipped instance as first evidence
- iss-2608220150157507The machine-local private name-guard blocked a commit on the entry its hook reports as entry-14: the unanchored pattern matches inside an unrelated academic author's surname in rendered bibliography content (the site prototype), a false positive that keeps the behavioural spec out of the shared tree. The fix site is the generator, not the file: the pattern sits inside the generated abcd-sources block of the private-names store ("do not edit between markers" — a hand-anchored edit is overwritten by the next sources sync), so the sources-sync that emits the block must word-boundary-anchor every short name pattern it writes at emit time. Until that ships the prototype lives in the local scratch tier and the plan documents the detour (decision confirmed 2026-08-22: status quo, no guard weakening, no hand-edits to the generated block; the prototype is committed into research/abcdev-site/ in a follow-up once the anchoring lands). Fix the detector, not the findingblocks iss-2608221342509869
- iss-2608220150157508Local-only token-usage accounting in the history store: at history capture time, extract per-message usage (input, output, cache-read, cache-write) and the model id from the transcript's own usage fields, store the aggregate with a timestamp in the stored transcript's metadata, and offer a report summing per session and per repo. Pricing is a user-level table (~/.abcd), recorded on explicit ask only: when a report meets a model with no recorded pricing it offers an explicit refresh verb in the docs-cite-refresh mould — never an implicit fetch (adr-38). Estimates are labelled API-equivalent (subscription seats do not bill per token; cache tiers price differently). Local-only by construction: never committed, never rendered on any siterelated itd-2609292107351737
- iss-2608220150157509Auto-merge for docs PRs is armable only when the diff is prose-only, defined precisely: no YAML frontmatter changes AND no file adds, moves, or deletes under the record stores — because record state lives in both frontmatter (status flips) and directory position (lifecycle bucket moves). A state change is a gate crossing (adversarial-review-scales-with-blast-radius) and always waits for the human; prose fixes are below the review floor. Adopted as documented protocol now (applied by eye when arming); the mechanical rung — a CI check that refuses auto-merge arming when the diff touches frontmatter or record paths — is a later seed per script-first-mvp
- iss-2608220150157510CHANGELOG.md is the repo's most contended file (205 changes since July): every user-facing change appends an entry near the top, so any two in-flight branches conflict there — and it keeps biting on real merges. The SOTA fix is per-change fragments (the towncrier/changesets pattern, which is also the shape the ledger already uses): each change commits one fragment file with a collision-proof name, and the release cut — which already owns CHANGELOG writes via launch ship (adr-37) — assembles the dated section and deletes the fragments. Zero contention by construction; the changelog-driven release flow is unchanged, only its input format widens
- iss-2608220150157511Merge contention is structural in the shared registers, not the prose: append logs (.abcd/work/DECISIONS.md, 154 changes; the decomposition-calibration corpus, conflicted 2026-08-22) and the lint-gated indexes that index_drift forces every branch to co-edit (brief/06-delivery/03-out-of-scope.md drafts index, conflicted the same day; 04-surfaces/README.md; decisions/adrs/README.md; intents/README.md; release/surface.json). The fix shape for the indexes is already written down: the enumeration command in out-of-scope.md derives the list from the filesystem, so the committed copy could become generated-at-build and the lint compare against the derivation instead of a hand-edited region. Append logs tolerate union merges; the indexes do not
- iss-2608220150157512ADRs, intents and specs still mint sequential ids (adr-NNNN, itd-N, spc-N), so two parallel branches minting in the same family produce add/add collisions on the same id — the exact mechanism adr-45 removed for issue captures, whose timestamp-numeric ids produced zero conflicts across twelve same-day captures on 2026-08-22 while the sequential families carry the standing risk. adr-45 rollout note 3 already names the path: one allocator, per-family adoption as configuration. Extending timestamp minting to the remaining families closes the class
- iss-2608220750024263adr-47 decision 2 says the site build optimises rasters, but the stdlib-only generator copies rasters verbatim; optimisation needs either an image-codec dependency (sign-off gate) or pre-optimised committed assets
- iss-2608220750024303adr-47 decision 2's allowlist of generator-added words does not name image alt text, yet the migrated docs pages carry alt text the site inherits; the carve-out wants an explicit ADR amendment
- iss-2608220750025153the site generator hand-rolls a Markdown-subset renderer, a strict HTML tokenizer and a CSL formatter to stay dependency-free; adopting goldmark and x/net/html instead is a maintainer dependency decision
- iss-2608220750029985the OpenGraph 1200x630 crop of intro.png named by the migration map is not yet created or committed; the landing page ships without a social card until the asset lands
- iss-2608220750029986adrs/README.md index omits the accepted adr-47 and adr-48 rows (site-build session) — fourth recurrence of the unindexed-ADR class after adr-45 (iss-38 wants these indexes gated); rows added in the same change that records this
- iss-260822075002998700-meta.md § Brief vs lifeboat claims /abcd:ahoy copies an empty brief skeleton into a fresh repo; shipped ahoy scaffolds only .abcd/config.json + .abcd/rules.json (plus banlist artefacts), never the skeleton. Restate as a design target aligned with the interview-entry design — greenfield is the all-blank coverage state, not a copy-a-skeleton step.
- iss-2608220750029988glossary/core/brief.md's frontmatter definition says the brief defines the project before any implementation begins — contradicting adr-5 and the file's own body, which say the brief is the current state revised in place. Its When-to-use section also claims the brief lives at the root of the .abcd/ hierarchy; the path is .abcd/development/brief/.
- iss-2608220750029989The 03-evidence pages 01–03 carry leave-empty-until-disembark placeholder banners — during development, leave empty; populated post-build — contradicting adr-5's always-current doctrine. Open questions exist now and have no recordable home while the banner forbids entries. The resolution should also weigh where a hold-register-shaped record would live (see the hold-route triage seed).
- iss-2608220750029990The brief nowhere states its truth rule: everything in the brief is decided — the only variance a reader must resolve is shipped vs staged, and a staged claim says so. One paragraph in 00-meta.md citing adr-5.
- iss-2608220750029991capture's triage routes (defect fix / promote to intent / brief fix / wontfix) force frame-level unease into artefact-level fixes: there is no hold route for a finding whose real content is that the framing itself cannot yet be articulated. A hold-with-axes route is missing — non-articulation is data, holds carry axes and exit by articulation. Candidate RFC or intent; decompose before filing. Ties to the 03-evidence placeholder resolution (where would a hold-register-shaped record live?).
- iss-2608220750029992Two concurrent sessions shared one checkout (2026-08-22, itd-112 banner session vs filing session): a branch switch under a mid-commit peer unstaged its index and swapped the CHANGELOG state; both sessions' tree-wide lint gates failed on each other's work-in-progress. Recovered by coordination with no loss. Root principle: branches do not isolate the working tree, HEAD, or index — the checkout is the unit of isolation. Conventions land in AGENTS.md § Concurrent sessions in the same change.
- iss-2608220750029993Session-presence detection for shared checkouts: each live session leases a marker (session id, intended branch, started-at) in the checkout, and the pre-commit gate warns when another live session's lease is present — the armed-detector rung of the AGENTS.md concurrent-session conventions, which are vigilance-only until this ships. Lease home needs thought: the local tier is per-worktree by design, and the hazard is precisely two sessions in ONE worktree, so the lease belongs to the checkout, not the branch.related itd-2609091034175565 · related itd-2609091416295622 · related itd-2609151838312703
- iss-2608221126066379frontmatter.Fields trims a leading UTF-8 BOM (iss-2608220134344680) but the sibling parsers that promise byte-exact parity with it do not: intent's setFrontmatterFields (internal/core/intent/intent.go:129, whose comment claims it matches frontmatter.Fields's delimiter tolerance exactly) refuses a BOM-led record the reader accepts, so intent mutations on such a record fail-closed with 'no leading frontmatter block'; changelog's bodyStart (internal/core/changelog/source.go:60, 'so the two never disagree') returns 0 and leaks the whole frontmatter block into the derived changelog body; lint's recordTitle (internal/core/lint/schema.go:554) hand-rolls the comment skip with neither TrimBOM nor the multi-line-comment state. Sweep the siblings onto the shared tolerance or narrow the parity comments to the truth.
- iss-2608221126066631The guard tokenizer keeps process-substitution operands out of command position analysis, so a blocker-tier flag glued behind one escapes: 'git push >(cat) --force origin main' and 'git push >$(echo x) --force origin main' both return ALLOW while their plain-redirection spellings block (pre-existing on main; confirmed unchanged by the iss-2608220131352917 &> fix, same redirection family). Within the documented mistake-filter posture, but the &> precedent shows the family is worth sweeping: recognise >(...) / <(...) as redirection-shaped operands and keep the remaining argv in analysis.
- iss-2608221126066632Live recurrence, 2026-08-22: two concurrent sessions in two current checkouts each minted itd-144 and itd-145 in the same window — four records, two ids — resolved by hand-renumbering one side to itd-146/147. This is the second, undocumented path into the sequential-id collision recorded as iss-2608220150157512, which describes the stale-view path adr-45 already anticipated. Staleness was NOT the cause here: one session fast-forwarded 46 commits immediately before minting and still collided. The structural fact is that intents and specs mint max+1 (nextIntentID) while withIntentMintLock in internal/core/intent/create.go is advisory and scoped to a single checkout, so it cannot see a sibling worktree; two current checkouts therefore allocate the same id by construction. The durable fix is the timestamp mint adoption recorded as iss-2608210737260468. Recorded deliberately because capture has no add-evidence path and itd-87 (recurrence escalation) is unbuilt, so this evidence would otherwise exist only in two session transcripts.
- iss-2608221254560250docs/reference/terminology.md Memory row describes retrieval as 'recall-matched and budget-bracketed', but no retrieval engine exists: the recall: frontmatter field is parsed and round-tripped yet never consumed, and the budget brackets live only in itd-39 (draft). The row overstates shipped behaviour.
- iss-2608221254566264disembark.maxAgentTokens is documented in the brief (05-internals/03-configuration.md) as a per-agent context budget with stream+summarise overflow behaviour, but no code reads the key and it is absent from .abcd/config.json — brief-vs-binary drift.
- iss-2608221310142705New top-level verbs face no design-time test outside the assessment family, and the ideate verdict on the verb taxonomy left one unclaimed. adr-40 already imposes a design-time test, but only on assessment surfaces and only on one axis: what is compared to what, with a surface that would perform two acts split at design time rather than documented as a bundle. It says nothing about whether a proposed verb belongs at the top level at all, so a non-assessment verb faces no test. The 2026-08-22 ideate verdict (research/notes/2026-08-22-ideate-cli-verb-taxonomy-restructure.md) killed an open-ended 'restructure when confusable pairs appear' deferral because a condition with no detector is the phantom gate enforcement-claims-are-facts forbids. What it put in that place is a design-time question asked when a verb is proposed: does an existing record-owning verb already own this act? The question is answerable by the human designing the verb, which a trigger conditioned on future confusion is not. Five unbuilt verb names are already in play across three different statuses, so the test has live subjects: dredge, loot and audit sit in the reserved table of brief/02-constraints/04-naming.md; audit and reflect sit on its metaphor-exemptions list; and oracle is in neither, appearing only as a design-target sub-verb under a note recording that no oracle verb is registered. It currently exists only inside a research note, which is not where a design-time rule can be found by the person who needs it. Decide its home: a principle under development/principles/, a line in the naming register at brief/02-constraints/04-naming.md beside the existing metaphor-vs-exempt criterion and the bare-command-as-render discipline, or an explicit decision to leave it in the verdict record. itd-146 carries the same question as an open question; this capture exists so the test survives that intent not shipping.
- iss-2608221328552172abcd intent and abcd capture both swallow an unrecognised sub-verb as content and mint a record at exit 0, violating unrecognised-input-never-writes on the two highest-traffic mutating verbs. Verified on 45afe46 against a freshly built binary: 'abcd intent nosuchthing' prints 'created itd-148 (drafts)' and exits 0; 'abcd capture nosuchthing' prints 'captured iss-... (open)' and exits 0. Both records were durable files on disk, removed by hand afterwards. The principle at development/principles/unrecognized-input-never-writes.md states the rule -- a verb that mutates state fails closed, anything not exactly recognised is an error, never a fallback interpretation -- and cites this precise scenario as its founding evidence: a misspelled capture subcommand swallowed as capture text, filing an issue when the user asked to resolve one. The principle is therefore documented and unenforced, and the failure it was written about is still live on both verbs. The cause is structural rather than accidental: both verbs take free text as their canonical create path, so an unknown token is indistinguishable from intended content. That makes a bare token ambiguous by construction, which is the design question a fix must answer -- candidates include requiring quoting or an explicit create flag for the text path, refusing a single bare token that matches no sub-verb and resembles one, or accepting text only from stdin. A typo costs a spurious durable record, a burnt id under the max+1 intent allocator, and a record-lint index_drift blocker until the stray is noticed. Related: adr-45 on id allocation.
- iss-2608221342502032site.tar.gz is attested but absent from checksums.txt, so the release manifest no longer covers every asset; wants a deliberate decision rather than a silent gap
- iss-2608221342502263itd-102, itd-103 and itd-104 shipped carrying the identical minted press-release placeholder; the landing page's featured-quote derivation now skips the two placeholder templates mechanically, and the three intents want their narratives written
- iss-2608221342503802the references page overflows at 360 and 390 px (scrollWidth 484): long unbroken link tokens escape their column; found by the screenshot audit's first run while the static mobile gate reports ok on the same tree — the complementary-gates argument made concrete
- iss-2608221342506032docs/requirements.txt pins mkdocs-material by version only; the deploy render job runs pip without hash-pinning, so a --require-hashes freeze is the remaining supply-chain hardening
- iss-2608221342506046abcd site build reuses a non-empty output directory without purging, so files from an earlier build survive into the new tree; a purge needs a build-marker guard so it can never remove a directory the build did not write
- iss-2608221342508040seven check-config JSON files sit flat in the abcd directory; the maintainer suggests a config sub-tree, which needs one convention decision covering all of them plus an adr-47 amendment for the site pair
- iss-2608221342508878several issue captures write a bare --- directly after a paragraph, which CommonMark renders as a setext heading; surfaced by the record explorer rendering full bodies — the second-detector effect the site intents predicted
- iss-2608221342509701the screenshot audit installs playwright by pinned version through npx with no lockfile; a committed lockfile would harden it but changes wrangler-action's package-manager inference and needs the dependency gate
- iss-2608221342509869the private name-guard blocks every commit touching ACKNOWLEDGEMENTS.md because a pre-existing citation in HEAD matches an unanchored pattern; two credits (the layout algorithm, the screenshot tooling) are held as local patches until the anchoring fix landsblocked by iss-2608220150157507
- iss-2608221456462677checkInlinableSVG accepts an SVG XML prolog, comment and CDATA section (whitelisting the xml declaration, no case for comments/CDATA) but the emitted-page reader htmlscan refuses all three, so a normal exporter SVG makes abcd site build succeed and abcd site check refuse the page with a message naming no asset.
- iss-2608221456463223The guard tokenizer does not recognise bash ANSI-C quoting or locale quoting, so \$'--force' tokenises to \$--force and a Tier-1 blocker (git push --force, rm -rf, --no-verify) is silently allowed while bash hands the child byte-identical argv, contradicting the doc.go invariant that quoting affects tokenisation not argument semantics.
- iss-2608221456466438LoadRepoMeta reads .claude-plugin/plugin.json repository into an href on every emitted page with no executableScheme check, unlike its two sibling href sources, so a javascript: address (or a scheme-less typo) passes every gate and ships on every page.
- iss-2608221456469558A site page that fails to parse is dropped from c.pages, so the page-walking gates (hero, banned-tokens, snippets, mobile, figure-labels) never examine it yet print ok, masking a genuine finding on that page behind the provenance parse fault.
- iss-2608221456469938The hard_fail local_username redaction matcher (m.localBare) is built without the (?i) its home-path sibling carries, so on a case-folding filesystem a case variant of the caller login (EVE/Eve) is neither redacted nor caught by the blocking residual scan, leaking the login into the stored transcript.
- iss-2608221456593173CODEOWNERS omits site-src/ (including install.sh.tmpl, the byte source of the served /install.sh) and docs/requirements.txt, so a PR confined to those merges with zero required code-owner review while shipping the install script to users.
- iss-2608221456593814The writing-style guide Escapes section says any machine-enforced rule accepts a docs-lint: allow line, but only the banned-token families honour it; links_resolve, stray_root_docs and citation_* ignore it, so a contributor adds a no-op escape and still fails the gate. The Structure table also omits the shipped names/* blocker family.
- iss-2608221456597173The adopter release scaffold hardcodes a go test -race ./internal/... step outside the .Abcd guard, so a bare adopter module with no internal tree fails every release verify run with lstat ./internal/: no such file or directory, wedging the release.
- iss-2608221456599229capture list/status --json emit skipped[].error carrying a raw absolute path beside the deliberately-relativised skipped[].path, in an exit-0 success envelope the CLI error-path scrubber never sees.
- iss-2608221456599559scaffold classify: a symlinked target leaf fails ReadGuarded with ELOOP (not ErrNotRegular), so the symlink case named first in the function contract falls through to the generic branch and embeds a raw absolute developer-identity path in the dry-run report and its --json success envelope.
- iss-2608221457122761abcd site check shipped (brief 22-site.md marks it shipped) but 04-surfaces/README.md and 05-internals/10-site.md still call the check gates design targets, and the release-gate manifest never pinned 22-site.md so Direction A never reads the site chapter.
- iss-2608221457123924Round-7 confirmed nitpick batch: site principle-id collision silently overwrites a typed record in record.json (loud refusal added); the isolatedGit history walk quoted non-ASCII paths so a record lost its dates (core.quotePath=false); docs Windows planned/dry-run --json/no-color colour and the 00-meta open-questions home clause.
- iss-2608221457125132commands/site.md and brief 04-surfaces/22-site.md claim the site build reads exactly a named set and nowhere else, but the set omits site-src/record.js, site-src/install.sh.tmpl, CONTRIBUTING.md (a build-aborting input) and ACKNOWLEDGEMENTS.md, and the output list omits install.sh and record.js.
- iss-2608221457127152brief 02-constraints/03-invariants.md carries a PLACEHOLDER/navigational-pointer banner over fourteen fully-stated invariants, two landed this week, and adr-50 names the file as where invariants live; the may-consolidate clause is the aspirational-maybe the same-day truth rule forbids.
- iss-2608221457128333brief/README.md index still calls the 03-evidence chapter placeholders populated by lifeboat extraction, three commits after that chapter was made live (commit closing iss-2608220750029989).
- iss-2608221457227161The guard tokenizer does not perform brace expansion, so a flag wrapped in a single-element brace group with an empty alternative (git push {--force,} origin main) expands in bash to byte-identical argv --force yet the guard reads the literal token {--force,} and allows it — a Tier-1 blocker miss of the same mutate-the-flag-token shape as the round-6 redirection fix. Distinct from the $'...' quoting gap (this is expansion, not quoting, and breaks no written invariant); recorded for a scoped follow-up because a correct bounded brace-expander is larger than this round's scope.related itd-156
- iss-2608221457227162a superseded Phase-0 pseudo-ADR sits in research/notes/ claiming ADR-01, outside every record gate
- iss-2608230617385431a quick-tunnel preview flow (cloudflared tunnel --url against a local site build) covers phone testing when the LAN route is blocked and multiple simultaneous testers during dev work; worth a documented protocol or make target if the need recurs — the URL is public while the tunnel runs, so the protocol must say what may be served through it
- iss-2608230639225979Recurring drift class: prose borrows a principle's authority for behaviour adjacent to but outside its letter. Three instances caught by fresh-context reviewers across the 2026-08-22/23 research notes: loud-staging cited for run-outcome reporting, loud-staging cited for runtime endpoint fallback, evaluator-outside-the-loop cited for reviewer freshness (its letter governs gate ownership). Only detector today is the SOTA-protocol's repo-fidelity review lens, which is genre-scoped; candidate detector is a standing principle-citation check in the reviewer agents' checklists (semantic, so a reviewer item rather than a deterministic lint).
- iss-2608230748418054Ideate leg-2 grill has a structural blind spot for id-less records: the 2026-08-23 abcd-research-verb run's grill failed to surface the same-day research note (2026-08-22-sota-research-protocol.md) that answers the submitted idea by name, because research notes carry no citable record id and the grill's output is id-cited hits. The nearest-citable-record note-field rule exists but nothing prompts a sweep of research/notes/ or DECISIONS.md, so a standing verdict recorded outside the id-bearing record families is invisible to the leg that exists to prevent re-litigation. The leg-3 evaluator caught it only by doing its own sweep.
- iss-2608230751270193Record health panel entries wrap mid-phrase and the summary line '8 / 8 · 148' is three unlabelled numbers. Restructure to two lines per entry (fact, then explanation) and label the summary (report 3a).
- iss-2608230751276906Site dashboard/contributors stat tiles render unevenly: .panel+.panel{margin-top} leaks into the .dash grid (every panel but the first is pushed down 14px) and .dash align-items:start lets each panel take content height, so row-mates never equalise. Seen on /record/, /contributors/, and at phone widths (reports 1, 4, 10, 14a of the 2026-08-23 manual test pass).
- iss-2608230751279689Header and footer external links print the repo handle (owner/repo) where users expect the forge name (GitHub). Label must come from a ui.json interface string with the handle as generic-side fallback, never hardcoded in Go (reports 2, 17).
- iss-2608230751433117References page citations shatter: .refs li{display:grid} turns every inline child (em, a, text runs) into alternating grid items, so journal names and DOI links land in the 40px marker column and wrap one character per line. Core content illegible on desktop; the overflow audit cannot see it because nothing overflows (report 6). Sweep for sibling li{display:grid} patterns.
- iss-2608230751434661Explorer pages print a grey dateline (date · version · commit) under every page title, duplicating the header pill and footer stamp. Remove the gen line from the explorer shell (report 5).
- iss-2608230751437480Site-wide ' · ' dot separators (header pill, datelines, panel summaries) read poorly; a deliberate separator/typography design pass is PLANNED per maintainer ruling 2026-08-23 (report 3b).
- iss-2608230752040334The site build's SVG inliner strips width/height attributes from svg image elements: docs/assets/img/process-loop.svg embeds cast portraits at width=42 height=42, but the inlined landing-page copy has no size attributes, so the WebP figures render at intrinsic size and the r=21 circle clips catch only slivers (report 8). Root-cause the optimiser and sweep every inlined SVG carrying image elements.
- iss-2608230752040735Landing-page a/b/c/d chapters lost the colour-gradient connecting rail from the signed-off mock: .chapter::before/::after rules were never lifted from the prototype into site.css (report 7). Port the rail CSS.
- iss-2608230752049112Install tab panel takes the height of the active tab, so switching to a thin tab (Windows) collapses the layout; on iPhone the tab strip wraps into three broken rows (Plugin / CLI+OS / orphaned Build). Stack panels in one grid cell so the tallest wins; give the strip a deliberate narrow-width layout per the existing <=700px nav pattern (reports 9, 14b).
- iss-2608230752151670Roles comparison table column labels (th spans beside the portraits) render badly on iPhone; visually hide them on the composed landing surface, keeping them screen-reader-accessible (report 13).
- iss-2608230752154346Maintainer re-rule 2026-08-23 amends spc-38's 'every visual has a table twin': a table twin is dropped wherever the visual already presents the same labels and numbers as text. Drop the twins on the dashboard seg bars, Assisted-by trailers, and the Genealogy release-cadence list; the cadence chart absorbs its dates; the relationship chart's Browse-as-a-list twin stays (spc-39 AC 4 keyboard path). Spec amendment to be recorded with the change (reports 11, 15, 20).
- iss-2608230752158970Record pages print badly: no @media print stylesheet, so interactive chrome prints, collapsed details lose their content on paper, Foundations page 1 is blank (panel refuses to split), cards slice across page boundaries, and footers orphan onto empty pages (report 18, three PDFs).
- iss-2608230752354909Record explorer IA restructure seed (intent-sized, maintainer-proposed 2026-08-23): sub-nav becomes Dashboard (Genealogy graph docked collapsed) / Foundations / Development (intents, specs, issues rendered like Foundations) / Relationships / Health (new page aggregating every deterministic inconsistency: unresolved cross-refs, author-identity duplicate candidates with suggested .mailmap lines, baseline ratchet), with Contributors and References as right-aligned text glyphs (ruled: glyphs, not image assets). Release-cadence panel replaced by a commits-per-release-window ridgeline, designed within this intent. Draft via the itd-84 decomposition gate before filing (reports 3c, 12, 15-amendment, 19-addendum).
- iss-2608230752354925Contributor author rows should link to forge profiles, derived deterministically (no API per adr-47) from the forge noreply email pattern, graceful absence otherwise. Includes the repo-side .mailmap fix: the old-format noreply <login>@users.noreply.github.com (39 commits) is not folded into the product thinker's canonical name; maintainer authorised the one-line unification 2026-08-23 (report 19).
- iss-2608230752354926ADR-23: Transport Agnostic Core (probe)related itd-161
- iss-2608230752354927relative links under .abcd/work/ are checked by no lint root
- iss-2608230752354928the history store's validKinds drops the source harness of an imported transcript
- iss-2608230817034768`hook session-end` redacts the whole transcript in-line before it writes, at
- iss-2608230838592910site check refuses every mkdocs-built docs page: the scanner faults on HTML comments (mkdocs-material templates and the FontAwesome icon licence header emit them), so docs/** never parsed — before de19186 those pages silently dropped out of every gate (the ship-day green was a false green over docs), and after it every page-walking gate is loudly denied. The deploy chain's site-check step will fail the next release. Candidate fix: scope the no-comment parse fault to generator-authored pages (the rule's own rationale is 'the generator emits none'), so docs pages parse with comments tolerated and the other gates regain coverage of them.
- iss-2608230847432285Per-agent worktrees do not isolate a session whose shell cwd reverts to the shared checkout, so the mitigation iss-213 recommended has a hole. This refines iss-213, which recorded several agents sharing one git worktree silently invalidating a verification result, and whose recommended direction was to give each agent its own worktree so the whole class disappears. That direction is now in force via the AGENTS.md Concurrent sessions section, and on 2026-08-23 three concurrent sessions demonstrated it does not hold. A session's shell cwd can be silently reset from its worktree back to the primary working directory, and the notice arrives on the tool result AFTER the command that caused it, so the contamination lands on the NEXT command. It fails toward the shared tree, which is the wrong direction: two sessions wrote into the main checkout while believing they were in their own worktree. One appended to two Go test files, the other filed a capture and edited three record files, and both discovered it only when a third session read git status in the main checkout and asked who owned the diffs. Nobody lost work, because the convention that a diff you did not make is a peer's work held and the owners were asked rather than the files committed. The isolation property did not hold; the coordination convention compensated for it. Two details generalise beyond this instance. First, the failure is silent in BOTH directions: nothing warns the writer, and nothing would have warned a committer using git add -A, because the misplaced files are indistinguishable from that session's own in git status. What stood between this and a bad commit was one session committing with explicit paths and another happening to run git status for an unrelated reason. Detection was not mechanical in any of the three cases. Second, this is the write-side twin of iss-213 rather than a restatement of it: iss-213's dangerous member was a verification result that described no tree in particular, on the read side, while this is work landing in a tree whose HEAD another session is preparing to move. Same root cause, that the checkout is the unit of isolation and nothing enforces which checkout a session is in, on opposite sides of the read/write boundary. The mechanical mitigation is to address the tree explicitly on every git invocation, git -C <abs-path>, and to use absolute paths for file writes, rather than relying on a persisted cd: a cd is a session-global mutation with no scope and no expiry, which is the wrong shape for the mechanism that is supposed to provide isolation. AGENTS.md states that the checkout is the unit of isolation without saying what makes a session stay in its checkout, and that gap is what let three sessions make the same mistake in one day. Decide the routing: an AGENTS.md line under Concurrent sessions is the cheapest rung and matches how the sequential-id caveat was handled, while the durable form is whatever makes a session's tree unambiguous rather than remembered.related itd-148
- iss-2608230847432286a gate that validates a proxy for a claim switches off the vigilance an absent gate would have preserved
- iss-2608230847432287the adversarial-review floor assumes below-the-line artefacts are covered by their gates, and today they were not
- iss-2608230943088357The plugin-root binary predates the verbs its own command surface documents, and the failure is an unknown-command error rather than a named refusal. Verified 2026-08-23: the commands/update.md page instructs the reader to run the plugin-root binary first, and that binary on this machine is v0.6.1, whose help lists no update verb at all. Running it as documented gives 'abcd: unknown flag: --yes', and running the bare verb gives 'abcd: unknown command "update" for "abcd"'. The page's own resolution ladder recovers the situation, since a source checkout falls through to go run ./cmd/abcd, but only for a reader who knows to keep going: the first rung produces an error that looks like a malformed invocation rather than a stale install. This refines iss-228, which records the same root cause with a different consequence -- a plugin-root binary sitting a month stale so ahoy's first resolution rung reported pre-iss-171 gaps with no staleness signal. That entry is about wrong gap reporting; this is about a documented command surface pointing at a binary that cannot serve it. The general shape is that the plugin surface and the plugin binary ship from one release but a repository checkout can be arbitrarily far ahead of the installed plugin, so every commands/*.md page documenting a verb newer than the reader's plugin has this failure mode, and update is merely the first to be noticed. Two directions, neither adopted: have the command pages degrade legibly when the resolved binary lacks the verb, by checking for it before invoking; or have the binary answer an unknown verb by naming its own version and vintage, so the error says stale rather than wrong. Worth deciding whether this is inherent to plugin-versus-checkout skew and therefore only a documentation problem, or whether the unknown-command path should carry install context.
- iss-2608230943260391abcd version reports 'dev' and abcd update calls the same PATH entry 'foreign', and both are correct, which is the problem. Verified 2026-08-23 against ~/.local/bin/abcd, a symlink into a source checkout's bin/abcd-darwin-arm64. abcd version prints 'abcd dev, vintage 5d864c42bad9, up to date'. abcd update on the same entry refuses with shape foreign and the detail that the entry is not something abcd owns. Neither is wrong. The words describe unrelated properties that happen to collide. Version's 'dev' is the build-time version string, internal/core/core.go var Version = "dev", overridden by ldflags at release, so any make-build or go-run binary reports it. Update's classification is about the PATH entry's provenance: internal/core/ahoy/update_target.go resolves the occupant, isDevShimFile in store.go recognises a dev shim only by a byte prefix on the file itself, and an entry that is neither a shim, nor an owned symlink, nor a regular file falls to UpdateTargetForeign. A symlink to a hand-built binary is therefore foreign by construction and correctly so. The legibility failure is that commands/update.md lists dev-shim as its own named refusal shape with its own remedy, abcd ahoy install, so a reader who has just seen 'abcd dev' has every reason to predict that shape and gets a different one with a different remedy. The two surfaces never appear together, so nothing forces the collision into view. This is a vocabulary collision rather than a classification defect, which is why the fix is not to change the classifier. Directions, none adopted: have version name the install mode alongside the version string, so the two properties are visible in one place; or rename the build-time 'dev' to something the install-mode vocabulary does not use; or have the foreign refusal say what it examined, since a reader told an entry is not owned cannot tell whether the objection is the symlink, the target, or the absence of recorded provenance.
- iss-2608230943533581itd-33's revisit triggers have fired and the coordination question owes a SOTA sweep that no record currently asks for. On 2026-08-23 several sessions ran in parallel in this repo and spent real effort coordinating rather than working: three of them landed writes in the wrong checkout when a shell cwd silently reverted from a per-agent worktree to the shared tree, and what stood between that and a bad commit was the AGENTS.md convention that a diff you did not make is a peer's work, not any mechanical property of the setup. That is itd-33's fifth revisit trigger — two consecutive successful multi-agent runs, after which the absence of coordination becomes the next bottleneck — and the intent asks in terms for exactly this texture to be recorded in the ledger so its design proceeds against real evidence rather than guesses. The accumulated evidence is now iss-213 (2026-08-11, a shared worktree and a false-green preflight spanning branch switches), iss-2608220750029992 (two sessions in one checkout, a branch switch unstaging a peer's index), iss-2608220750029993 (the session-presence lease, the armed-detector rung of the AGENTS.md conventions), iss-2608230847432285 (per-agent worktrees do not isolate a session whose cwd reverts), and the parallel-mint collisions iss-2608220150157512 and iss-2608221126066632. The gap this capture exists to close is the research one. .abcd/development/research/notes/ holds sixteen SOTA notes and not one covers multi-agent orchestration or coordination; itd-15 audits agent prompts against their research baselines, which is a different question. itd-33's own narrowing pass dropped LangGraph, CrewAI and AutoGen from its References when it cut file-level claims and substrate selection — right for that scope, but it leaves no record anywhere that a state-of-the-art sweep is owed on the topic at all, so without this entry the ask exists only in one session's transcript. The sweep should run under the protocol in .abcd/development/research/notes/2026-08-22-sota-research-protocol.md and cover at minimum what coordination substrates the field actually uses for same-machine multi-agent work on one repository, whether a claim-and-yield contract of itd-33's shape is state of the art or a local invention, how other systems make a session's tree unambiguous rather than remembered, and what the evidence says about coordination overhead against parallel throughput — the cost today's sessions paid in full. Promoting itd-33 out of drafts/ is a maintainer decision and is deliberately not taken here.
- iss-2608230957104179the scan-before-mutating rule enumerates four git operations and misses shared artefacts outside git
- iss-2608231000561060The repo-conformance lint runs in no gate while the record says it gates CI, and it is not currently gate-ready, which are two problems needing separate decisions. Verified 2026-08-23 on origin/main. brief/04-surfaces/README.md row 16 describes /abcd:lint as checking the three-tier layout, AGENTS.md router, durable decisions, docs currency, privacy hygiene and identity positioning, and states it 'backs prepare-this-repo and gates CI (itd-85)'. It does not gate CI. The Makefile's preflight target is lint-reviews record-lint docs-lint plus build, vet, test and race, with no abcd lint, and the Makefile has no abcd lint or repolint target at all. Searching .github/workflows for an invocation of the repo-conformance lint, excluding the unrelated 'abcd docs lint', returns nothing in ci.yml or release.yml, whose only lint steps are go run ./cmd/record-lint and go run ./cmd/abcd docs lint. The surface runs only when a human types it. The second problem is why simply wiring it up does not work. On current main the lint emits 19 privacy-hygiene findings, 17 at blocker severity, and the sampled ones are not leaks. Nine of the 19 are in the scanner's own source or in ledger entries about the scanner, where the patterns appear as subject matter. Three sampled outside that set are documentation examples: a Linuxbrew prefix in a spec table and again in [dcn-2608200000000006](../../decisions/dcn-2608200000000006-homebrew-distribution-recorded-and.md), and a CHANGELOG entry recording that certain path shapes stopped being read as usernames. So gating it today would fail every build on content that is correct. iss-305, resolved, records the mechanism -- hasAbsHomePath lacks the leading-boundary predicate its scanner twin has -- and iss-307, iss-308 and iss-324 are adjacent boundary defects in the same family. A waiver marker exists, abcd-lint:allow with the legacy spelling abcd-audit:allow, and the rule's own source uses it on two lines, so the mechanism is available but is not applied across the corpus. What makes this worth deciding rather than filing and forgetting: the rule is right about the case that actually bit. An absolute home path written into a ledger issue body is exactly what its pattern catches, and on 2026-08-23 two sessions independently wrote one. Neither was caught by an instrument. record-lint did not see them because its roots are ['.abcd/development'] and the ledger is in .abcd/work; the lint that would have seen them does not run. Note the two are not interchangeable, since record-lint is scoped to the durable record while privacy-hygiene scans every tracked file, so widening record-lint's roots is a different fix from running the lint. Decide in order: whether the record's gates-CI claim is corrected or made true, and if made true, whether the false-positive rate is addressed by waivers, by the iss-305 boundary fix, or by narrowing what blocks. Leaving the claim standing while the surface runs nowhere is the shape enforcement-claims-are-facts names, and iss-2608230847432286 records the class.
- iss-2608231001035445A dedicated print layout for the record, and a downloadable PDF report of the whole Record section (future intent seed). The 2026-08-23 print pass is a stylesheet that stops the worst faults — blank sheets, sliced cards, printed chrome — and it stops there: a closed disclosure still prints as its summary alone outside Chromium, the relationship chart's list is deliberately left collapsed, and nothing composes a document a reader would want to keep. This intent is the designed thing: a print/PDF surface for /record/** with its own page furniture (running heads, page numbers, a contents page, record ids as cross-references rather than links), and a single 'download the record' artefact a visitor can take away. Generic-side under itd-140 — inputs stay the record format, git history and CHANGELOG.md — and adr-47's single-source rule applies unchanged: the document selects spans, it never writes prose. Open questions for the interview: is the PDF built at site-build time (deterministic, attestable, adds a renderer dependency) or printed by the reader's browser from a print stylesheet (no dependency, no attestation, engine-dependent); and does it cover the record only or the whole site.
- iss-2608231003136455The relationship chart prints squashed: .bstage is sized height:min(72vh,720px) with width:100%, and the canvas bitmap record.js drew for a wide viewport is then stretched into the narrower print page box, distorting the aspect. The expanded Browse-as-a-list content is also cut mid-row at the panel boundary rather than paginating. Found printing /record/graph/ from a browser with the list open (report A of the 2026-08-23 second pass).
- iss-2608231003138797The references page's two panels (References & sources, Inspirations) read as two odd parallel columns of very different length. Maintainer's model is the relationship page's Browse-as-a-list disclosure: stack the two as full-width boxes one under the other, both COLLAPSED by default, so the page opens as two closed headings a reader chooses between. This supersedes the reading-grid exemption added earlier the same day, which only stopped the shorter column stretching to match the taller one (report B of the 2026-08-23 second pass).
- iss-2608231005025233The dashboard's stat tiles are inert: a reader who sees '27 principles' or '525 issues' has no way through to what the number counts. Each tile should be a link to where that store is read — principles and disciplines to the foundations page, issues/intents/specs/decisions to their listing, releases to the release history — with a hover frame so the affordance is visible before the click. Generic-side under itd-140: the destination is derived from the record's own store, and a store with no page of its own renders an unlinked tile rather than a dead link (report C of the 2026-08-23 second pass).
- iss-2608231008315498Contributors page rethink: keep only the two things that matter — Authors of record, and Assisted-by trailers — stacked one under the other as expandable panels; drop the three stat tiles, with 'commits disclose AI assistance' moving to the Health page (depends on that page landing with the IA intent seed iss-2608230752354909). Also a real data inconsistency: the Assisted-by panel's note reads 1035 (a.Assisted) while its bars sum to 1036, because the tally includes the 'None' row — the positive human-only declaration — which a.Assisted deliberately excludes (contributors.go counts DeclaredNone and continues before incrementing Assisted). A chart whose total is 'assisted' must not carry a row that is by definition not assistance: either split None out as its own labelled figure or relabel the panel to the declarations it actually counts, and make the note equal what the bars sum to (report D of the 2026-08-23 second pass).
- iss-2608231013186887Authorship.Assisted counts trailer OCCURRENCES but every surface renders it as a count of COMMITS. contributors.go increments a.Assisted once per Assisted-by value inside the per-commit loop, and 8 commits in this history carry more than one trailer, so the contributors tile reads '1037 / 1454 commits disclose AI assistance' when the true commit figure is 1029 (1030 commits carry at least one trailer, one of which declares None). The displayed 71% is right only by rounding coincidence. The same conflation makes the panel note (1037) disagree with its own bars (1038, including None). Separate the two quantities and name each for what it is: commits that disclose (a commit-level count) against trailer occurrences per model (an occurrence-level tally, where one commit may appear twice), and publish the undeclared count (424) which the struct already computes and no page renders. Found while redesigning the contributors page (report D follow-up, 2026-08-23).
- iss-2608231014306394The contributors page's headline disclosure figure is wrong in a way that understates compliance badly: it publishes '71% commits disclose AI assistance (1037/1454)' when the honest figure is about 95%. Three compounding faults. (1) The numerator counts Assisted-by trailer occurrences, not commits: 8 commits carry two trailers. (2) The denominator counts all 1454 commits including 410 MERGE commits, which the forge creates and no human authors, so no trailer is expected of them: 375 of the 424 undeclared commits are merges. (3) The residue is then presented as a disclosure gap. Measured on 2026-08-23: 1043 authored (non-merge) commits, of which 48 carry no trailer (4.6%), 1 declares None, the rest disclose. The denominator for any disclosure rate is authored commits; merges belong in neither numerator nor denominator, and the split must be visible rather than assumed.
- iss-2608231021254712The relationship between the CLI command tree and the plugin command surface is an open decision with no record that says so, so it is invisible to anyone scanning open work. The 2026-08-22 verb-taxonomy hand-run routed five parts and filed four. The fifth was HELD: whether the CLI tree is an engine API that the flat plugin surface merely calls, so the two need not carry the same spellings. It was not filed because an ADR records a ratified choice and the maintainer had not ruled, which was the right call at the time and is now the problem: nothing prompts the ruling. Its only durable homes are prose. research/notes/2026-08-15-decomposition-calibration.md names it in one HELD line inside a graded entry, and research/notes/2026-08-22-ideate-cli-verb-taxonomy-restructure.md discusses decoupling only as part of the idea it killed, so a reader of the verdict would reasonably conclude the question died with the restructure. It did not. The killed proposal was a noun-verb hierarchy with invented category nouns; the surviving question is narrower and independent of it. What makes it live rather than academic: the two surfaces are ALREADY not one to one, in both directions and by explicit config. Three commands are host-delegated markdown with no Go verb, and changelog, spec and rules are Go verbs with no markdown surface. So decoupling as a principle is precedented and partially in force, and what has never been decided is whether that is a deliberate architecture or an accumulation of exceptions. The verdict's leg 2 and leg 3 supply the evidence either way: iss-161 records that the harness structurally refuses a nested markdown surface, so the plugin side cannot mirror a nested CLI even if wanted; and the strongest recorded objection is that decoupling deletes the three-way name join, on which the surface_coverage sub-verb pass depends, against roughly 109 fenced binary invocations and 18 argument-hint lines under commands/. Deciding it settles whether a future CLI-side change may diverge from the plugin spelling at all, which is a precondition for any grouping, nesting or rename proposal that touches only one side. Not urgent, and deliberately carrying no proposal: this capture exists so the question is answerable from the ledger rather than only from a research note a later reader has no reason to open.
- iss-2608231024022535The relationship page's record list is a scroll window (.nodelist max-height:520px, overflow:auto), so printing it captures only the first 520px and slices the entry at that boundary: 3 of 778 entries reach paper, the third cut mid-sentence. Lifting the cap in print prints all 778 and turns a 1-page document into 96 — precisely the outcome the stylesheet already rejects on the record. This is a design call, not a defect fix: cap the printed list at a stated number of entries, hide it in print and say so, or accept the length. Measured 2026-08-23.
- iss-2608231024027294The disclosure marker glyph is part of the accessible name on every folded panel: .panel.fold summary h3::before renders a triangle that screen readers announce as text, so the panel is read out as 'triangle References and sources 28'. aria-hidden cannot apply to a pseudo-element; the remedies are a background-image marker or content:\"triangle\" / \"\" alt-text syntax. Pre-existing pattern elsewhere in the stylesheet, newly multiplied by the folded panels.
- iss-2608231024029144The references page prints EMPTY as a consequence of the stacked-disclosure change (iss-2608231003138797): both bibliography panels are closed on load, CSS cannot force a details element open, and the ::details-content escape already used for .more is Chromium-only and not applied to .panel.fold. A reader printing /references/ from a fresh load gets one sheet carrying two headings and zero citations; before the change the panels were always-open blocks and the bibliography printed. Verified 2026-08-23: 1 page as loaded, 5 pages with both opened by hand.
- iss-2608231025198888abcd capture writes to the ledger without running the redaction scanner
- iss-2608231029040602`abcd history capture` read its operand through `maxOperandJSONBytes` (8 MiB)
- iss-2608231110263208Entering full screen on the relationship chart leaves the reader with no feedback during the relayout: the standby indicator exists (ui.standby, the .bstandby element in graphpage.go, styled at site.css) and is shown on first load, but the full-screen transition re-lays-out 772 nodes without re-showing it, so the chart appears frozen. The indicator must be raised for any relayout the reader waits on — entering and leaving full screen, and any arrange change — not only the first paint (report E of the 2026-08-23 second pass).
- iss-2608231120121681a lint-and-test-green write path can still be broken; nothing requires running the built binary
- iss-2608231226274000`commands/launch.md` documents the release cut as three steps over two Go entry
- iss-2608231226342272`abcd launch --dry-run` reports a `gates` array built in
- iss-2608231226347380`auto-release.yml` runs `detect` -> `tag` -> `release`, and the semantic
- iss-2608231237300997There is no way to change text in a file the private name-guard blocks
- iss-2608231322321751The site check's overlapping-bubbles gate measures the COIL arrangement only: the counter lives inside the coil packer and never sees the by-links layout, so a links arrangement can ship with overlapping bubbles while the gate reports zero. Widening it is not a one-line change — the published positions are normalised to the unit disk while the radii are quoted in reference pixels, so a correct check has to compare both in one space (an attempt that compared them across spaces reported 159,600 overlaps on a 400-node fixture). Found while diagnosing why the by-links arrangement never settles (iss-2608231243286557). The renderer-side half of that defect IS fixed: the collision resolver no longer adds padding the layout never promised.
- iss-2608231322329898The relationship chart's filter legend is unreadable: it mixes two different encodings in one flowing list, so 'closed' appears to belong to specs and 'disciplines' sits between two lifecycle words. Two encodings are in play — COLOUR means the record's store (decisions, intents, specs, issues, principles) and BORDER STYLE means its lifecycle (open/planned hollow, drafts dashed, shipped/resolved/closed filled, superseded/wontfix faded) — and the legend runs them together as one wrapping row. Split it into two labelled sections: the coloured store dots, then the border styles beneath, so each encoding is read on its own. Disciplines currently share the principles colour and need their own, as a discipline is a distinct store to a reader even though the record files it under intents. Reported 2026-08-23.
- iss-2608231339287073The genealogy chart is a draft and needs rethinking as a designed picture (future intent seed). Its five lanes over one axis carry real facts — releases, decisions, intents, specs, principles, and issues as a per-day histogram — but the drawing does not yet read: the supersession arcs and their dashed stubs cross the lanes and collide with each other and with the marks they point at (adr-4, adr-8 and adr-18 overprint), a crowded day collapses into a capsule whose count says nothing about what is inside it, the lanes are unlabelled beyond a store name and a total, and the first-commit marker cuts the whole picture without saying why. It reads as five separate strips sharing an axis rather than as one genealogy. The rethink is a design question, not a defect: what should this picture ANSWER, and what shape answers it. Docked folded at the top of the dashboard as of 2026-08-23.
- iss-2608231346137587A full-tier `iss35-brief-surface-crosscheck` at content commit `7a4ee00`
- iss-2608231350127745The by-links arrangement's non-settling has a LAYOUT half that is still open, and it is a redesign rather than a fix. The renderer half is fixed (the collision resolver no longer demands 1.5 units of padding the published positions never promised, iss-2608231243286557), but the layout itself still publishes overlapping positions, so the chart still never comes to rest on that arrangement — measured 2026-08-23: by date comes to rest, by links does not. Two causes found and NOT fixed, because fixing them changes the picture: the islands are settled by a spring layout with no collision pass at all, and the two rim rows map each record's arc-width onto a circle whose circumference is smaller than the sum of those widths, so the rows are overpacked by construction. Attempted fixes measured: relaxing the linked records alone left 600 overlaps (the rest are on the rim); adding a rim-row growth rule left 367 and pushed the outermost radius from 0.97 to 1.83, visibly changing the picture without settling it. Both reverted. A correct fix places every record — islands, pairs and rim — under one packing rule, which is a design of the arrangement, not a patch to it.related itd-157
- iss-2608231409595789`.abcd/development/release-gate/manifest.json` describes itself as "the
- iss-2608231607594913Cloudflare Git-integration branch builds run for pull request branches even though wrangler.jsonc records them as disabled, so an unmerged commit reaches a third-party build system before review. wrangler.jsonc carries 'automatic production builds: disabled' and 'automatic branch builds: disabled', kept in-tree because the dashboard setting has no other durable record. On 2026-08-23 a Cloudflare build ran for a pull request branch at 10:00 UTC and the integration bot posted a successful-deployment comment naming the build id. That build was not Actions: .github/workflows/site.yml triggers on workflow_call, workflow_dispatch and push to main only, and it did not run on that commit; the workflow header itself states that the main-push preview replaces the Cloudflare branch builds that ran only the version command. Two consequences. Operationally, every pull request commit is cloned by a third party before merge, and Cloudflare exposes no delete endpoint for a build record or its logs, so whatever reaches a build log cannot be withdrawn without a vendor support request. Durably, the in-tree record is wrong in the confident direction: a reader checking whether branch builds run gets a clear no. Suggested direction: reconcile the dashboard setting with wrangler.jsonc and decide which is authoritative. A maintainer decides; this record reports.
- iss-2608231912566984The v0.6.2 release published its binaries, then failed on its final job, and
- iss-2608240806090544planned/README.md categorically claims every intent carries a spec_id: spc-N link, but 20 of 43 planned intents have spec_id: null — a legal lint-enforced state (intent_lifecycle) per the surface contract, parent intents/README, and adr-34; the subheading silently reintroduces the over-narrow framing adr-34 already corrected in the parent README (resolved iss-3).
- iss-2608240815453131shipped-intents README names the retired intent-fidelity-reviewer agent (renamed to intent-auditor per spc-28); the sibling front-door the iss-334 sweep of the parent index missed
- iss-2608240815458212shipped-intents README front-door claims the directory is empty while it holds 18 shipped intents, contradicting the parent intents index which describes it as populated
- iss-2608241115201044SessionStart exit-2-as-advisory no longer reaches the user. abcd hook session-start returns exitError{Code: 2} whenever it has notices to print (internal/surface/cli/cli.go:1289), on the documented assumption that a non-zero SessionStart surfaces stderr without blocking. Claude Code v2.1.241 instead renders it as 'SessionStart:startup hook error' followed by a truncated echo of the hooks.json command string; the stderr notice itself never reaches the user. Every session-start notice is therefore an opaque error banner: transcript-capture gaps, staged-drain failures, the remaining-backlog count, binary skew, dogfood staleness, and the version transition. The data-loss-adjacent ones matter most - a user told that a session transcript was not captured now sees only a hook error, with no way to learn what it was.
- iss-2608241115259170A dev-recorded setup_version can never reconcile against a release binary. versionTransitionFrom (internal/core/ahoy/vintage.go:222) guards running == dev but not recorded == dev, so a repo whose .abcd/config.json meta.setup_version was stamped by a local dev build reports a version transition against every release binary, permanently. The recommended fix is a no-op or a flap in exactly the repo that ships the code: ahoy install stamps core.Version of whichever binary runs it (internal/core/ahoy/apply.go:1020 via store.go:21), so abcd ahoy install from a dev PATH entry re-stamps dev and leaves the notice standing, while the plugin binary's install stamps the release version into a tracked file that the next dev install rewrites back. detectVersion (internal/core/ahoy/detect.go:599) carries the same asymmetry and raises version.upgrade as a required gap on the same footing.
- iss-2608241347321757`abcd capture resolve` exists and works. Nothing anywhere can fail when it is
- iss-2608241347321758gvSupersededADRs unquotes superseded_by BEFORE frontmatter.IsNull, so a quoted null (`"NULL"`) reads as absent on the lifeboat path even though YAML semantics make it a string -- decide whether lifeboat supersession wants quote-insensitive sentinel semantics, document it as an explicit lifeboat heuristic if kept, or drop the pre-IsNull unquote; surfaced by external review of pr-294 takeover 2026-08-24
- iss-2608241347321759frontmatter.Fields trims the captured value but strips nothing after a comment marker, and IsNull compares exact strings, so superseded_by: NULL # no successor is read as the literal string 'NULL # no successor' rather than the null token -- a trailing-comment form valid YAML never resolves as null; follow-up to pr-294 per reviewer (frontmatter self-describes as a line scanner, so decide: trim unquoted trailing comments or document as unsupported) takeover 2026-08-24
- iss-2608241542245317capture has no way to record comments or updates on an existing issue -- issues are create-once records whose only later mutations are status transitions, so triage evidence, corrections and new reproductions accumulate in conversation or unsanctioned hand-edits instead of the ledger; add a capture followup verb appending timestamped redacted body sections under the ledger lock, and give the schema's unwritten related_issues field its writer via a --relates flag (same schema-grows-a-writer precedent as resolved_by); design sketch persisted at .abcd/.work.local/scratch/review-2026-08-24/design-capture-followup.md review 2026-08-24
- iss-2608241612007530the issue-resolution gate is triggered by the trailer, so a fix that lands without one is invisible to it. RS001 fires only on a commit carrying a Resolves trailer, and RS002/RS003 only on stamps that already exist, so a merged fix whose commit names no issue passes all three rules and leaves its record in open/ — the exact backlog iss-2608241347321757 was built to stop, reached from the other direction. Measured 2026-08-24: 1315 commits name an iss- id somewhere in the message and 3 carry the trailer. iss-202 is the standing instance: its fix merged on 2026-08-24 in a commit ending with a bare 'iss-202' line rather than the trailer form, and its record sits in open/ with the fix shipped. The missing detector is the inverse direction — a change touching code an open record describes, declaring no resolution.
- iss-2608241612087533the release derivation cannot tell a back-filled resolution from a fresh one, so a ledger hygiene sweep re-announces old work as this release's content. internal/core/release/emit.go and internal/core/changelog/shipped.go read only folder membership and the record's impact field; neither reads resolved_by. The cut therefore equates 'record entered resolved/ since the base tag' with 'shipped in this release'. That equation holds only because RS001 now lands resolution inside the fixing commit, and a bulk hygiene sweep is the legitimate exception. Live instance: the 2026-08-24 sweep (089c0d61) closed 33 already-fixed records, and the v0.6.4 cut renders 14 of them as changelog entries for work first tagged v0.4.0, v0.4.1, v0.4.2 and v0.6.2 — four of the 14 are already cited by id under the 0.6.2 heading. The four records deciding the additive impact class (iss-98, iss-99, iss-100, iss-158) all describe pre-v0.6.3 work, so the version and the receipt tier rest on them too. Candidate fix: exclude an added record whose resolved_by.commit is reachable from the base tag, which needs the stamp back-filled on the six swept records that carry none.
- iss-2608241659573856the org rename breaks the plugin bootstrap's tag resolution, so a fresh install refuses with a message blaming the network. hooks/bootstrap.sh pins repo_url and api_url to the old organisation. It resolves the latest release by reading (not following) the redirect from $releases_url/latest and parsing a tag out of it with sed 's|.*/releases/tag/...|'. After the rename that URL returns 301 to https://github.com/<new-org>/abcd/releases/latest — the org hop, NOT a tag URL — so the sed matches nothing and resolved_tag is empty. Verified live 2026-08-24: old org gives redirect_url=.../abcd/releases/latest (301), new org gives .../releases/tag/v0.6.3 (302). Consequences: with a cached binary the script takes use_cache=yes with cache_trust=offline and provisions from an unauthenticated cache while claiming offline, which is wrong about the cause but degrades loudly; with NO cache the download path hits its guard '[ -n "$resolved_tag" ] || refuse the latest release tag could not be resolved ... there may be no network' and refuses, so every fresh plugin install fails and the message misdirects to the network. bootstrap.sh ships from the repository tree rather than a release asset, so merging the corrected URLs to the default branch fixes installs without waiting for a release cut.
- iss-2608241740093740commands/launch.md presents the release-day site deploy as automatic when it never succeeds. The step table row 6 reads 'Deploy the website from the tag | automatic, after step 5' and the prose adds 'the site deploy is invoked by the release workflow, so approving step 5 releases step 6 with it'. release.yml's own comment records the opposite: a called workflow's job cannot resolve environment secrets, this repository holds no repository-scoped secrets, so the inherited set is empty and the deploy fails through the release chain (proven at v0.6.2 and v0.6.3) while succeeding through workflow_dispatch on site.yml. The always-taken path is demoted to a 'When it goes wrong' bullet, so an operator following steps 1-7 verbatim is told a step is automatic that has never worked. Same defect class as iss-2608231912566984, one surface away. Also in the same section: 'Three failures are worth recognising' is followed by four bullets, the site/deploy one added by b6602672 without updating the count.
- iss-2608241740100762docs/explanation/process.md promises collision impossibility where the code provides improbability. It calls the minted issue id 'collision-proof (iss-<yymmddHHMMSS><4 random digits>) that no parallel agent can duplicate'. recordid/mint.go:53 records the real property: Mint reads nothing, so two minters cannot converge by sharing a stale view, and 'only a same-second suffix coincidence remains, which is the armed uniqueness detectors' residue to assert (adr-45 ruling 5)'. There is no read-back and no retry, so two agents minting in the same UTC second collide with probability 1e-4. AGENTS.md already documents the sequential-id collision hazard for intents and specs; this page overclaims for the timestamp mint.
- iss-2608241828356533the disembark marker scan reads untracked and gitignored files, so a packed lifeboat can cite work the user kept out of git. convOpenQuestionsSource.probeLimited grounds evidence/open-questions from ctx.WalkFiles("."), which walks the working tree through an os.Root and skips only walkSkipDirs (.git, .tox, .venv, Pods, __pycache__, build, dist, generated, node_modules, target, vendor, venv). Neither probe.go nor sources_conventions.go reads the index, parses .gitignore, or invokes git at all. Demonstrated on a throwaway repo holding one committed, one never-added and one gitignored file: the probe cited all three by path:line. This repo's own .abcd/.work.local/ — the gitignored local tier holding scratch/ and logs/ — is not in walkSkipDirs, so a lifeboat packed here would carry path:line citations out of it. The blank-case wording is already accurate ('every regular file in the tree except <walkSkipDirs>'); the defect is the behaviour, not that string. Decide whether the scan should consult git, honour .gitignore, or extend walkSkipDirs, and note disembark is offered as read-only over a source repo including dead and archived ones, where untracked residue is likeliest.
- iss-2608241845109280abcd site build refuses a committed record, so the site render fails on main and nothing catches it before CI. .abcd/work/issues/resolved/iss-2608241347321757-...md:52 carries a four-space indented code block, and the renderer supports a fixed subset only: 'unsupported markdown construct: indented code block: fence code with backticks so it renders as a copyable command — the site renders a fixed subset and never passes text through unrendered'. The binary is behaving as designed; the record is non-conforming. It reached main because the site-screenshots workflow is path-filtered and the ci changes classifier stands jobs down for a pull request confined to .abcd/, so PR 489 never ran a site build, and the failure only surfaced on the first later PR touching a watched path (the v0.6.4 release PR 497). Two gaps, not one: the record's markdown is wrong, and record-lint does not check records against the renderer's supported subset even though every record under .abcd/work/issues/ is site-rendered. The second is the detector; the first is its acceptance corpus. Note screenshots is not a required status check, so this never blocked a merge.
- iss-2608241959573830the repository moved organisations and the module path, install commands and support links still name the old one. github.com/<old-org>/abcd appears 468 times across 40+ files: go.mod's module path and the 404 import lines in 226 Go files that follow it, README.md's two badge URLs and its marketplace-add and install one-liner, docs/how-to/install.md, CITATION.cff's repository-code, SECURITY.md's advisory link, and the Makefile ldflags that stamp the version symbol. The runtime surface is already corrected (iss-2608241659573856) because it was breaking fresh installs; this is the rest. TestInstallGuideDocumentsTheInstallAndUpdatePath derives the documented marketplace slug from go.mod's module path, so go.mod, README.md and docs/how-to/install.md must move in one change or the gate fails - which is the detector working. Renaming the module path is a breaking change for any Go importer, judged near-zero cost because abcd is a CLI rather than a library and is pre-1.0. Deliberately out of scope: CHANGELOG.md's entry for the EARLIER transfer to the old organisation, and the historical records under .abcd/, which state facts about the past that rewriting would falsify.
- iss-2608242043243131the preflight gate list is prose no test derives from the recipe, so it drifts every time the recipe changes. Makefile's preflight target names its prerequisites once; docs/how-to/install.md, CONTRIBUTING.md and the Makefile's own comment each restate that list by hand. The restatements have now drifted twice in two releases: v0.6.4 corrected three surfaces that said three gates after lint-issues made it four (2852c095 updated AGENTS.md alone), and v0.6.5 re-introduced the same defect by adding site-render as a fifth prerequisite and leaving those surfaces saying four. Both times only the host-run docs-currency reviewer noticed, and both times it refused a release cut over it. The class is a derived-value restatement with no deriving test: the same shape as the marketplace slug, which TestInstallGuideDocumentsTheInstallAndUpdatePath solved by reading go.mod and asserting the documented string contains it. The detector is the same move here — parse preflight's prerequisites out of the Makefile and assert each enumerating surface names exactly that set. Acceptance corpus: the two instances above, both of which the test must flag when replayed against their pre-fix trees.
- iss-2608250536214009the release chain runs with an empty secrets context, because auto-release.yml passes none to release.yml. A called workflow's secrets context is ONLY what its caller passes. A job inside one that declares environment: gets the environment APPLIED — GitHub creates a deployment record for it — and still resolves none of that environment's secrets unless inherit unlocked the context first. release.yml has carried 'secrets: inherit' on its call to site.yml since v0.6.3; auto-release.yml's call to release.yml carried no secrets line at all, so the chain ran empty from the top and the production deploy failed on a credential that was never conveyed, on v0.6.2, v0.6.3 and v0.6.5. NOT v0.6.4: that release's render failed on an unfenced code block in a record and its deploy was SKIPPED, so it never reached the credential at all (run 32765800591; the iss-2608241845109280 defect). Verified from the release runs rather than assumed — v0.6.2 run 32657507210, v0.6.3 run 32674659520 and v0.6.5 run 32777924919 each show render success and deploy failure. Measured on a canary environment secret through the same two-level shape: a top-level job declaring the environment saw it SET, nested twice with no secrets line EMPTY, nested twice with inherit at the outer call SET. This supersedes the reading recorded in iss-2608231912566984, which concluded that a called workflow's job cannot resolve environment secrets even when it declares the environment. That is false: it cannot resolve them without inherit at every level above it, which is a different defect with a one-line fix.
- iss-2608250743421381two slash-command argument-hints advertise sub-verbs the binary refuses, in the one string a user reads before invoking. commands/ahoy.md:4 offers '[status | install | uninstall | doctor | dry-run]': 'abcd ahoy status' exits 2 with unknown command — bare 'abcd ahoy' is the status render — and the real sub-verb identity-check is absent from the hint. commands/launch.md:4 offers '[dry-run | ship | scaffold]': dry-run is a FLAG, so 'abcd launch dry-run' exits 2 while 'abcd launch --dry-run' exits 0; the binary registers only scaffold and ship. Both files' own bodies get it right, so the drift is confined to the frontmatter hint, which is exactly the part no prose reader checks and the part the harness surfaces first. The brief does NOT get it right: 04-surfaces/01-ahoy.md's dispatch sentence carries the same phantom status token, which is brief-tier and tracked under iss-2608231346137587. A first attempt at this fix ALSO added identity-check to the ahoy hint, which is wrong in the other direction: that verb is deliberately CLI-only, the command page carries a scoping note saying it stays a bare-CLI entrypoint rather than a plugin sub-verb, and the page carries a flow section for every other hinted token and none for it. The plugin dispatch set is install, uninstall, doctor and dry-run. This is a shipped surface, not record drift: commands/ is carried in the release bundle, so the adr-28 disposition that covers brief-tier findings does not apply. Found by the iss-35 crosscheck's plugin-command-surface probe at the v0.6.6 gate; the docs-currency pass had not flagged it across three runs, because its scope reads command prose rather than frontmatter.
- iss-2608250844259345a record's resolution frontmatter is user-reachable and nothing checks it against the record body it sits on. The resolution field is emitted verbatim by 'abcd capture list --resolved --json', which commands/capture.md dispatches, so it is a shipped surface rather than an internal note — but the rendered site pages carry the record BODY, so a resolution that contradicts its own body is invisible on the site and visible on the CLI. Demonstrated in the v0.6.6 cut: iss-2608250743421381's body was corrected to say identity-check is deliberately NOT added to the ahoy hint, while its resolution field still said the hint advertises it and describes 'adding the identity-check it registers'. The docs-currency gate caught it by running the command rather than by reading the file, after the body had already been fixed. Same class as iss-2608242043243131 (the preflight gate list restated by hand in five places with no test deriving it) in a different field: a claim with more than one representation and no check that the representations agree. Candidate detector: a record-lint rule asserting the resolution field does not contradict the body, or more tractably that a record edited in a commit has its resolution field edited in the same commit whenever the body's claims change.
- iss-2608251011427187hooks/bootstrap.sh and hooks.json still deliver SessionStart notices by a non-zero exit, which the harness renders as an opaque banner with the text dropped. iss-2608241115201044 fixed the binary half: abcd hook session-start now exits 0, writes its notice text to stderr and only a CONSTANT to stdout. The shell half is unchanged and inconsistent with it. bootstrap.sh's notice() exits 2 on a REPORTED CONDITION including a successful install, and hooks.json's SessionStart chain propagates that ($s) plus a trailing exit 2 on the missing-binary branch. Under the same premise those messages are dropped too, so a fresh install's success line and the missing-binary complaint are both delivered by the mechanism the binary half abandoned. bootstrap.sh's own comment states the reasoning that makes the binary fix correct — 'a SessionStart hook's stdout becomes model context' — and an adversarial review demonstrated that concern concretely, planting a directive payload in a TRACKED config value that reached context when notices were briefly routed to stdout. So the shell must NOT simply move its text to stdout either. The open question is what channel a shell hook has left: a constant on stdout plus text on stderr mirrors the binary, but bootstrap.sh's exit code also governs the install path, and changing it touches the most safety-critical surface in the repo. Deliberately deferred rather than bundled into the binary fix.
- iss-2608260941298050the changelog should index every record transition rather than curate a subset, which deletes the inclusion judgement and the reason shipped_in exists. Design decision of 2026-08-26, recorded in [dcn-2608260000000003](../../decisions/dcn-2608260000000003-the-changelog-is-an-index-of-record.md) and resting on the less-but-better principle. Today the cut reads two families (intents/shipped, issues/resolved) and renders only records whose impact is non-internal, so impact carries TWO jobs: it decides the version bump, which it must, and it silences a changelog line, which is a publication judgement bolted onto a product one. checkIssueImpact's own comment names the cost — a rule refusing internal would force work into a user-facing changelog or push authors into a mislabel. Measured consequence of removing the judgement: v0.6.2 saw 175 records enter terminal folders against 98 rendered lines, of which 57 records were internal, so that release becomes roughly 175 entries. Also in scope: principles (30 files) and ADRs (45) are invisible to the cut today, and a new principle is arguably more consequential than half the issues that render. NOT in scope: bundling stays, because one line citing several records that were one user-visible change is fewer lines carrying the same information, which is the better half rather than curation; and impact keeps its version arithmetic. Residue that is NOT a migration artefact and needs a decision: AGENTS.md makes a stale closure legal forever, so some transitions carry no code change even in a greenfield repo, and under this model they render.
- iss-2608260944055780Brief self-contradiction on abcd lint's exit grammar: 05-internals/06-lint.md:174 states "Exit code follows the standalone grammar (blocker -> 1, warn -> 2, clean -> 0)", which inverts the two non-zero codes. internal/core/repolint/repolint.go:147 exitCode() returns 2 on any blocker, 1 on warnings only, 0 clean, and its own comment names the Conftest tri-state; 04-surfaces/16-lint.md:41 agrees with the code. Observed: this tree at 19 errors and 3 warnings exits 2. The consequence is worse than count drift, because an exit code is a number a CI job branches on: a job written against 06-lint.md would treat 1 as its failure condition and pass green on a tree full of blockers, a gate that runs and never fires. Same class as iss-142 (the iss-37 phantom-enforcement class) and the same file, different line; iss-181 and iss-251 also sit on this file and cover neither. Brief-tier, so under adr-28 it ships in no release artefact and reaches no installed surface, which is the standing disposition for brief drift and the argument for a lower severity. Refines iss-2608261029074763, which records the wider defect this is one symptom of: 06-lint.md section 3 documents an architecture that was never built, verified as internal/core/lint having no package main so the documented invocation cannot run, --codes-filter, --promote-check, --touched-line and --display-path having zero hits across internal/ and cmd/, no .pre-commit-config.yaml, and IntentLinter, _classify_and_filter, _parse_hunk_lines and _detect_location present in no source file. That record cites this one for the exit grammar rather than restating it. Adjacent and distinct: iss-2608231000561060 covers the gates-CI claim and gate-readiness. Detector: enforcement-claims-are-facts sweep over the brief's exit-code and gating claims. Acceptance corpus: the three lines above.
- iss-2608261029074763brief/05-internals/06-lint.md section 3 documents a lint architecture that does not exist, in flat present tense. Verified 2026-08-26 on main. It describes four CI trigger points for a program invoked as 'internal/core/lint --stdin --display-path <canonical> --json --touched-line <N>'; internal/core/lint is a library package with no package main, so that invocation cannot run at all, and cmd/ holds only abcd, abcd-gen-cli-ref, abcd-gen-surface, record-lint and scaffold-sync. Four flags it specifies are absent from the whole codebase: --codes-filter, --promote-check, --touched-line and --display-path each return zero hits across internal/ and cmd/, and --corpus's only three hits are an unrelated ahoy config key and two guard test fixtures. The shipped verb takes exactly two flags, --root and --json. Trigger point 1 asserts a pre-commit hook configured by .pre-commit-config.yaml with pass_filenames: false; no such file exists. The named orchestrator internals -- _classify_and_filter, _parse_hunk_lines, _lint_terminology_files, IntentLinter, _detect_location -- are Python-shaped and appear in no source file outside the record itself. Note points 3 and 4 of the same section DO hedge correctly ('design target for CI', 'not among ci.yml's jobs today'), which is what makes points 1 and 2 read as shipped rather than planned; the fix is to mark them the same way or delete what was never built, not to build it. The exit-grammar inversion at line 174 of the same file is the same defect surfacing at one line, and is already captured separately and more precisely as iss-2608260944055780, which names repolint.go:147 exitCode() as the authority; that issue is not superseded here, it is the narrow instance of this general one. This is also the same shape as iss-2608231000561060, which records the surfaces README claiming abcd lint gates CI when it gates nothing, and the enforcement-claims-are-facts principle names the class.
- iss-2608261040378346check-issue-resolution.sh scans cwd-relative and dies silently on a non-iss path, and RS002 reachability-checks a commit: line in a record body. Three sibling holes in the new issue-resolution gate: (1) it never cd's to the repo toplevel like check-reviews.sh does, so a git pathspec run from a subdirectory matches nothing and the gate reports a clean pass having scanned zero records — RS003, the drift detector with no other check, passes vacuously; (2) under set -euo pipefail the id extractors end a matched case with 'basename | grep ^iss-', which exits 1 on a non-iss filename, so when that is the last diff entry the while-loop and the closed= assignment inherit the failure and the script dies exit 1 with no diagnostic, RS001/RS002 never running; (3) RS002 greps the raw range diff for a '+ commit:' line with no frontmatter boundary, so a commit: example in a record's prose body is reachability-checked and raises a false violation — the exact boundary RS003 already draws. Fix: cd to toplevel; make the id extraction non-fatal; read the frontmatter per changed record via a helper RS003 shares.
- iss-2608261041020040check-issue-resolution-cases.sh runs its scratch-repo git commands under the inherited environment, so an ambient GIT_DIR or global core.hooksPath corrupts the caller's repo or breaks the gate. The harness builds ~60 'git -C $d' fixtures but omits the hermetic-env scrub its sibling check-attribution-cases.sh carries (iss-28, iss-313, resolved four days before this script was authored): an inherited absolute GIT_DIR overrides -C and redirects the fixture commits and config onto the ambient repository while every case still prints ok (green-while-corrupting, reachable on a direct make preflight under a git alias / rebase -x / bisect run); and an inherited GIT_CONFIG_GLOBAL / core.hooksPath — which this repo's .githooks/pre-push documents the maintainer uses — fires the developer's global pre-commit hook inside the scratch repos and turns make lint-issues red with no gate diagnostic. Fix: hoist the same unset GIT_DIR family + export GIT_CONFIG_GLOBAL=/dev/null scrub before the first git call.
- iss-2608261041020419CONTEXT.md's surface_coverage sharp-edge says it reads only the command and skill surfaces; its sub-verb pass also reads the CLI command tree. The bullet says the agent, hook, and CLI-verb surfaces are not covered, but subverbs.go reads the committed surface.json command-tree snapshot and files findings under surface_coverage for surface-bearing verbs, including a reverse sweep. The staleness errs in the safe direction (understating enforcement) so it is low-risk, but CLI-verb surfaces are now partly covered; genuinely uncovered are the operator-internal verbs, bare CLI-only verbs, and all of Direction A. Fix: reword to name the sub-verb pass and the truly-uncovered set.
- iss-2608261041027043The 05-internals index and the 04-surfaces row still call shipped site capabilities design targets, contradicting 10-site.md. 05-internals/README.md row 10 says the check gates, the explorer pages and the deploy workflow are design targets, and 04-surfaces/README.md row 22 says the deploy workflow remains a design target — but 10-site.md marks only the abcdev.app MkDocs root as the design target, abcd site check is registered shipped in surface.json, the explorer shipped (itd-136), and the deploy workflow ships (adr-48 accepted, release.yml calls site.yml, CHANGELOG 0.6.6). Both index cells are stale surviving copies of the earlier all-staged claim; outside the release-gate crosscheck's pinned briefDocs corpus, so no gate catches the record-vs-record contradiction. Fix: align both cells with 10-site.md.
- iss-2608261041027268commands/capture.md implies --shipped-in is validated for existence at resolve time; the code shape-checks only, and existence/ancestry run at release derivation. The flag doc says the value must name a tag that exists and that the release can reach, a shape-valid but wrong version is refused — read as a resolve-time precondition. In fact resolve only matches vMAJOR.MINOR.PATCH (workflow.go reShippedIn); a nonexistent shape-valid tag (v9.9.9) is accepted and written, and existence/ancestry are enforced only at derivation (changelog/shipped.go), which keeps a wrong-version record IN the cut with a stated reason rather than dropping it. The system never silently drops the record, but the doc gives false confidence at the point of use that resolve validated the tag. Fix: move the guarantee to derivation-time wording.
- iss-2608261041029596brief/README.md still says the internals README indexes nine chapters and its tree roster omits site, but there are ten. brief/README.md line 52 reads 'indexes the nine chapters' and the tree line 40 lists nine internals topics without site, while 05-internals/README.md indexes ten rows (10-site.md exists on disk). iss-356 designated the tree line and the internals index as the single rosters to keep in sync; a tenth chapter was added and the index updated but the count and tree line were not. No lint rule gates this roster. Fix: nine to ten, add site to the tree line.
- iss-2608261041210476The principle spec-moves-with-the-surface names a promotion trigger that is already armed, yet sits unpromoted in the not-yet-enforced layer. The principle says a record-lint cross-check (every entry under commands/ and skills/ resolves to a brief surface row) WOULD promote it to a discipline; that is exactly surface_coverage Direction B, armed at blocker (lint.go, record-lint.json), documented live. principles/README.md makes promotion unconditional once any mechanical gate lands (the file is then retired to a discipline-kind intent, as itd-79 personas did), but no discipline intent exists for this principle and the file was never retired. The conditional 'would promote' predates the gate and was left stale — the inverse of the phantom-gate family (it understates its own enforcement). RECORDED NOT FIXED this round: the correct remedy is a governance act (mint a discipline-kind intent and retire the principle file, per the itd-79 precedent), which needs the maintainer rather than an autonomous edit. Proposed: promote per principles/README, or if promotion is deliberately deferred, record why on the principle.
- iss-2608261041218890release.yml feeds an unvalidated tag name into 'make build VERSION=$TAG', splicing it textually into the -ldflags shell recipe. TAG is inputs.tag or github.ref_name with no shape-check; the release job runs 'make build VERSION="${TAG}"' and Make substitutes $(VERSION) textually into 'go build -ldflags "...Version=$(VERSION)"', so a tag containing a double-quote closes the quoting and splices a shell command (reproduced: VERSION='v9.9.9";echo INJECTED;x="'). Such a tag is a legal git ref matching the v* trigger. site.yml shape-checks the identical value with a [[ =~ ]] vX.Y.Z pattern and documents why; release.yml shape-checks the sha but not the tag. Bounded: the injectable step is behind the release environment's required reviewer and github.ref_name is settable only by an insider who can already run code in CI, so it grants no new capability — defense-in-depth, but a real shape-check-parity gap that also propagates to the scaffold template (release.yml.tmpl). RECORDED NOT FIXED this round: release.yml cannot be exercised by CI, so an autonomous edit to the release pipeline is deferred to the maintainer. Proposed fix: add a tag=$TAG shape-check step (the site.yml regex, [[ =~ ]] not grep) before make build, in both release.yml and the scaffold template.
- iss-2608261132593030requireIgnoredStore and the ListPrivate warning skip whenever InRepo is false, so with git unanswerable in a repo-shaped tree banlist add --private writes the secret-pattern store unignored with exit 0
- iss-2608261132593151capture validateStrict re-applies IsNull to the already-unquoted impact value, so quoted nulls pass capture while record-lint blocks them, and the IsNull widening added NULL and Null to the split its fix claimed closed
- iss-2608261132596224check-issue-resolution RS001 counts a bare deletion from open as a resolution: the unconditional D branch unions with ids_entering_closed, so a trailer plus git rm passes the gate with no terminal landing
- iss-2608261132597732gitutil.InRepo collapses repo-shaped-but-git-unanswerable into not-a-repo, so TrackedFiles returns nil and the privacy-hygiene lint reports a clean pass after scanning zero files
- iss-2608261133090830the install guide Afterwards section attributes a PATH warning and bin-dir option to the CLI one-liners, which parse no arguments and print no warning; the sentence lost its abcd ahoy install subject in a README rewrite
- iss-2608261133091022invariant 12 and spc-35 still withhold the SessionEnd no-network clause pending iss-2608210934566223, which resolved with a pinning test, so the register under-asserts a property the tree holds
- iss-2608261133091276RS002 and RS003 report an unfetched commit as names-no-commit on a shallow checkout, 85 false blockers on a clean tree, and check-reviews RD002 passes vacuously on the same input; neither script guards for shallow history
- iss-2608261133095909the pre-push hook restates a three-gate preflight roster while the recipe has five, and the preflight-gates drift detector omits the hook from its surface list, so the iss-182 drift recurred on the one unwatched surface
- iss-2608261133097575roadmap prose and adr-9 claim the phase-audit reviewer and PA001 lint exist and run as Go tooling; nothing in the Go tree implements either, and sibling records correctly call them a design target from the predecessor store spc-66
- iss-2608261133204171scanner.New lstats only the .abcd ancestor while its config lives two levels down, so a symlinked .abcd/config walks the pii.json read out of the tree; the read belongs in the ReadGuardedInRoot form
- iss-2608261133207814two session-start skew tests flipped their conditions to nonzero but kept messages reporting got exit 0, and both assertions are now unconditionally true
- iss-2608261133208071release.yml bills verify as the full verification gate mirroring the ci check and record-lint jobs while it deliberately runs a nine-gate subset; the adjective overclaims and the mirror sentence is stale
- iss-2608261133208642two planned livery intents refer to registry personas with she and her against the they-them persona rule
- iss-2608261133210491the memory store-lock guard tests mode AND S_IFREG nonzero instead of masking with S_IFMT, so its regular-file assertion also accepts symlink and socket modes; dead defence shielded by O_NOFOLLOW, fold into the iss-129 flock consolidation
- iss-2608261133212164a record clause that defers a property pending a named record stays deferred after that record resolves; a deferral-currency sibling of context_citation_currency would catch the invariant-12 class
- iss-2608261133218490capture validateStrict accepts a quoted legal enum impact and a quoted empty impact that record-lint and the release derivation block; the quoted-scalar acceptance is wider than the nulls the round-8 fix closed
- iss-2608261206490430disembark scan fails open to a wide read on an all-ignored repository
- iss-2608261206491486disembark docs claim all three verbs honour gitignore but only the tree scan does
- iss-2608261206504574CONTRIBUTING teaches the hand-written CHANGELOG flow the release derivation fails closed on
- iss-2608261206504710the brief grounds the live licence gate in the retired adr-18 at eleven sites
- iss-2608261206505136roadmap Planned row claims a linked spec but planned intents legally hold spec_id null
- iss-2608261206505385site check runs in no gate before the release publishes
- iss-2608261206506035shipped intent docs claim intent-auditor ran as an entry precondition it does not gate
- iss-2608261206507510RS001 admits a bare delete of an open record as a declared resolution
- iss-2608261206508851the intent surface contract still calls shipped empty while it holds intents
- iss-2608261312157721main's Unreleased section carries a hand-written entry the derived cut refuses. Commit 3dc7aba3 (round-7 resolutions, PR #511) added a '### Fixed' entry under '## [Unreleased]' on a branch parallel to 5897a85d, the commit that adopted the derived-changelog rule (Unreleased must be EMPTY or the launch ship ingest refuses); neither author could see the other, and the collision only exists on merged main. As written, the next 'launch ship' refuses the cut. The entry's content is already carried by the two resolved records it cites (iss-2608261040378346, iss-2608261041020040), so the remedy is removing the hand-written entry, not relocating it. Structural half: nothing gates Unreleased emptiness at merge time, so any two parallel branches can recreate this class silently until release; a compose-time or CI check on '## [Unreleased]' being empty is the durable fix (same family as iss-220's compose-time-prevention finding). Rounds 8a/8b (#512/#513) were checked and touch no CHANGELOG.
- iss-2608261331317889TestPayloadTreeImplementationsResolveIdentically failed transiently during a pre-push preflight with 'the payload carries 109 rejected file(s)', then passed in isolation minutes later with an identical two-markdown-file diff and a clean tree. Between the two runs a peer session created .claude/worktrees/pr513-conflicts in the shared checkout, so the plausible mechanism is the payload walk sweeping a sibling worktree mid-population — the iss-213 class (a peer's activity silently invalidating a verification result), now reaching the payload scan through the preflight gate. Not reproduced deterministically; captured as a sighting so the flake has a marker if it recurs.
- iss-2608261338035835the-record-lands-with-the-act names an armed rung in present tense and its promotion never fired. The principle's Promotion paragraph states 'The armed rung is make lint-issues, a CI step and a pre-push gate' — verified true: RS001-RS003 live in scripts/check-issue-resolution.sh, wired at Makefile lint-issues and included in preflight. Per the principles README promotion contract (enforced principle -> discipline-kind intent), the gate shipping should have minted a discipline; none exists. Third instance of the promotion-pipeline class alongside iss-390 (examples-use-reserved-identifiers) and iss-2608261041210476 (spec-moves-with-the-surface), and the only one with no ledger record until now. The class evidence is now three: the promotion ritual that only a human can perform is the step that gets skipped, which is the-record-lands-with-the-act applied to its own pipeline.
- iss-2608261437040448the served install script template misses the eol=lf pin its shell siblings carry
- iss-2608261437040578cleanLessonProse kept the pre-migration body the CleanProse consolidation claims routed
- iss-2608261437041050a ledger record missing schema_version vanishes from capture surfaces while every gate stays green
- iss-2608261437041111README and AGENTS quote the superseded RS001 leave-open rule the round-8 fix retired
- iss-2608261437042550README counts one plugin-only command where the plugin surface carries three
- iss-2608261437042674itd-5 scope step still carries the tiebreak its own amendment struck
- iss-2608261437043634the live disciplines bucket was never swept for the spc-28 intent-auditor rename
- iss-2608261437043962itd-5 names a phantom task_classes enum as source of truth and carries the retired intent_review token
- iss-2608261437044340itd-43 specifies work against the retired terminology tree its own spec records as delivered
- iss-2608261437044382RD002's rename leg is dead under a pathspec and a git failure reads as clean
- iss-2608261437046261CHANGELOG header promises a Breaking section the derived ingest cannot emit
- iss-2608261437046287capture --blocked-by writes an unverified cross-reference its own blocker then refuses
- iss-2608261437046944itd-24 glossary_terms_used still lists the retired core/epic term
- iss-2608261437047643intent verbs compare spec_id raw while lint canonicalises so a lint-green slug or zero-padded spelling bricks reconcile and ready
- iss-2608261437047965site-src README claims the record explorer ships the data-theme control nothing sets
- iss-2608261437047992CONTRIBUTING AGENTS and the ci.yml header understate the Linux leg and the record-lint job
- iss-2608261437048689firstRootSHA is the one unbounded git read on the lifeboat probe path
- iss-2608261437049307ScanSpecLinks swallows intent-tree read errors the spec half propagates
- iss-2608261447039180an unknown frontmatter property hides a ledger record the same way a missing one did
- iss-2608261447262355The test suite can adopt and overwrite a developer's real abcd on PATH, because hermeticRepo does not scrub it and effectiveBinTarget prefers an owned PATH entry over an explicitly set ABCD_BIN_TARGET.
- iss-2608261532379188Every memory-store reader outside ingest follows a committed symlink unbounded. internal/core/memory/ingest.go adjudicates the store as a trust boundary (maxMemoryPageBytes: a committed page symlink to /dev/zero would hang or OOM the CLI) and routes its own reads through fsutil.ReadGuarded, but the sibling readers kept raw os.ReadFile: readOrEmpty (bare.go, reached with no type check for index.md/contradictions.md), bareHeadroomLines and the lint WalkDir sweeps (lint.go — WalkDir yields symlinks as non-dir entries and the read follows them), loadQuotationBudget (coverage.go reading config.json), the .coverage_index.json reads (bare.go, coverage.go — its literal sibling .sources_index.json is guarded), triStateRead (writer.go), and the ingest licence probes (provenance.go manifestLicence/licenceFileLicence under an arbitrary sourceRoot). Reproduced: five distinct hangs via committed mode-120000 fixtures against abcd memory and abcd memory lint. The ReadDir-filtered sites (ask.go QueryPages, barePageInfos) carry the ReadDir-to-open swap window and no size cap — the exact TOCTOU ingest.go documents closing. Same class as the resolved lint.LoadConfig unguarded read (major/security). Detector: watched-fail tests planting a symlinked page/index; acceptance: every memory-store and source read routes through the guarded primitive.
- iss-2608261532488176The issue-resolution gate reports OK having scanned zero records whenever a git probe fails. scripts/check-issue-resolution.sh ledger arm: cd "$(git rev-parse --show-toplevel)" collapses to cd '' (rc 0) when the substitution fails under set -e; the ls-tree listing carries || true so a git failure reads as an empty ledger and check_ledger returns 0 with 'no ledger records — nothing to check'; and the is-shallow probe compares a failed substitution against 'true', so the exit-2 environment-fault arm is disarmed by the same fault it exists to report. Reproduced: GIT_TEST_ASSUME_DIFFERENT_OWNER=1 (git's dubious-ownership refusal, the reachable local form for containers/sudo/devcontainers) turns 113-records-checked into OK exit 0; from a non-git cwd likewise. The commits arm fails closed (bare assignment) — divergence within one file, and RS003 is the sole detector for resolved_by.commit shas rewritten by the squash/rebase merges the repo permits. Same class as the round-9 check-reviews.sh fail-closed rewrite (every git probe rc-checked, exit 2), which left this sibling untouched. Detector: cases asserting exit 2 under a failing git; acceptance: every git probe on the ledger arm is rc-checked and a git fault exits 2, with the legitimate empty-ledger pass kept loud.
- iss-2608261533033587docs lint's findings renderer asserts 'Severity/RuleID are enum-constrained' and prints both unsanitised, but neither is constrained: Severity is verbatim committed-config text and RuleID for the banned_tokens family is the token's configured id. The config file is adjudicated a trust boundary in internal/core/lint/config.go (cross-repo-clonable), and the same surface sanitises the enum-validated banlist severity — so the one unvalidated pair on the line is the unsanitised one. ToUpper does not neutralise OSC/CSI escapes (verified), and RuleID gets no ToUpper at all. Sibling scope: the recorded cmd/record-lint File/Message gap asserts the abcd CLI renderer sanitises — true for File/Message only. Acceptance: the renderer sanitises every config-derived field or the loader makes the comment true by validation.
- iss-2608261533033894A record-lint or docs-lint rule whose severity is missing, misspelt, or off-enum emits findings that print but count toward no exit code, so the gate exits 0 beside a non-empty findings list. internal/core/lint/config.go decodes with a plain json.Unmarshal (a misspelt key silently zero-values the field) and validates only banned-token successors; the exit paths in cmd/record-lint and abcd docs lint count Severity == blocker verbatim. The sibling engines fail closed on exactly this vocabulary (repolint Evaluate refuses a finding severity outside error/warn as a rule bug; guard Validate rejects an unknown tier on the committed guard.json; banlist AddPublic refuses to write a severity lint will happily read). The config is a documented trust boundary in this very file. The same underlying cause silently disarms a rule via a misspelt enabled key. All 27 live rules spell both correctly today — latent, one character from silent. Detector: watched-fail test loading a config with an off-enum severity; acceptance: LoadConfig refuses an enabled rule or token whose severity is outside the engine's enum, and unknown config keys are refused.
- iss-2608261533173466The intake protocol's contained-review stage pins a container that cannot build the module. The S4 recipe pins golang:1.25 while go.mod declares a higher toolchain, and --network=none in the same line blocks the GOTOOLCHAIN auto rescue, so the one command the protocol hands a maintainer fails at the toolchain check and S5's build-or-INCONCLUSIVE tri-state misreads the stale pin as an inconclusive contribution. Drift, not born broken: the pin matched go.mod when written; the toolchain bump that advertised lockstep did not include this file, and the work tier sits outside every lint-configured tree. The recipe also lacks any module-cache provision, so even a corrected tag fails on dependency fetch under --network=none — the line has never worked as written. S4 is load-bearing: a recorded maintainer decision cites it as the mitigation that closed a review-agent exposure question. Acceptance: the pin tracks the module toolchain and the recipe provisions modules before the network is cut.
- iss-2608261533174500docs/reference/terminology.md's RAG row claims 'the sources corpus ships the script-first version' — a false shipped-ness claim on a page whose sibling rows use ship as a precise delivery marker (No MCP server ships today; abcd ships zero skills). Nothing corpus-related is in the repo or any released artefact; the consult and ingest commands refuse when the corpus is absent and point at a README no user has; and the committed script-first-mvp principle states a script MVP never ships as product behaviour, naming this corpus tooling as the live instance. Same defect class as the open Memory-row overstatement on the same page. Acceptance: the row states the corpus as a user-tier script MVP with core absorption tracked, not as shipped behaviour.
- iss-2608261533290815repolint privacy-hygiene silently skips a tracked file it cannot open: readTrackedFile returns not-ok with no oversize marker on an open failure, and the caller emits a finding only for the oversize case — so an EACCES/ENOTDIR tracked file produces no finding and the rule reports the repository clean, against the engine contract that a check that cannot run must not be silently reported as passing. The oversize arm of the same helper got exactly this fix; the open arm beside it stayed silent. Constraint on the fix: TrackedFiles lists index entries, so ENOENT (deleted-in-worktree, sparse checkout) must stay silent and only genuine unreadability warns. Acceptance: a non-ENOENT open failure yields a not-scanned warn finding, watched-fail via an ENOTDIR fixture.
- iss-2608261533297309gitutil.runBounded returns strings.TrimSpace over the whole capture buffer, and lifeboat's pathIsIgnored NUL-splits that string from ls-files -z to build the not-ignored set. The -z form exists so whitespace in filenames cannot desync the list, but the shared trim strips leading whitespace off the first entry, so a repo whose first-sorting path begins with space/tab/CR/newline gets that one file silently classified ignored and dropped from the evidence walk — the quiet-evidence-loss shape the adapter's own contract forbids. Verified: -z disables quoting, the trailing NUL survives (NUL is not IsSpace), only the leading side is damaged; TrackedFiles bypasses the trim via raw Output. One-path blast radius, rare shape. Acceptance: NUL-list consumers receive the raw buffer (or a trailing-only trim) with a watched-fail test on a leading-whitespace name.
- iss-2608261533419396commands/site.md's frontmatter description enumerates write posture for the bare and build forms only, while check — added later with the argument-hint updated in the same diff — renders the whole site into an output directory that has no index.html. The body documents this correctly; the description line is a stale roster, and it drops the counter-intuitive form. House style names every form's posture, surprising ones explicitly (identity, version). Acceptance: the description discloses check's render-if-absent write.
- iss-2608261533419897scanIntentTree and the two spec-store stat probes in internal/core/lint swallow every stat error as tree-absent, unlike scanIssueLedger and scanRecordStores which part ENOENT from real faults — the doctrine the round-9 ScanSpecLinks fix states as a tree that is present but cannot be read IS a fault. No leg is currently reachable past markdownFiles, os.ReadDir, and the armed delivery_state floor (adjudicated: the claimed vacuous-blocker triggers are all closed one line later or upstream), so this is a consistency alignment, not a live defect: part ENOENT from other errors at the three sites and stop discarding WalkDir errors, matching the sibling scanners. Recorded for a scoped consolidation rather than fixed mid-hunt.
- iss-2608261543489261Optional feature: a local model within the harness captures prompts and sanitises, cleans and PII-checks them before they are piped through to the harness's foundation model. A small on-machine model sits at the prompt seam (the UserPromptSubmit surface is the natural hook) and rewrites or flags secrets, private names and PII locally, so nothing sensitive leaves the machine unredacted — the redact-on-write posture the history store already takes for transcripts, applied upstream to live prompts. Composes with the existing scanner and banlist layers rather than replacing them, and with the privacy legibility thread of the UX work: the product thinker gets one plain claim, nothing leaves this machine unchecked. Opt-in adapter per the host-delegated default; a missing local model degrades loudly to pass-through, never silently.related itd-2609292109005937
- iss-2608261550394120A repo-controlled rule body can forge a domain heading in the rendered rules injection block: renderDomain emits the body verbatim after its bullet prefix, so a body carrying a flush-left '## NAME' continuation line — or one that starts after a lone CR, U+2028 or U+2029, which are line starts to host-side multiline parsers — splits the block and impersonates or replaces a real domain. A red-team execution replaced a bundled domain's content end to end. Control characters, bidi overrides and C1/zero-width runes also reach the rendered block unmasked. A test-first fix (sanitizeRuleBody plus render_sanitize_test.go: separator normalisation before the trailing trim, heading-defusing indent, the canonical termsafe mask, render proven a fixed point across the pipeline boundary) sits unmerged in a local lab worktree cut at 089c0d61; promotion needs only the module-path update.
- iss-2608261550491547The rules hook stderr doubles its prefix on load errors: the hook prints 'abcd rules: ...; injecting nothing' around an error that already carries the rules package's own 'rules:' prefix, so the user reads 'abcd rules: rules: ...'. Cosmetic; unwrap or drop one prefix.
- iss-2608261550497978An empty or all-whitespace rule string passes rules.json validation and renders as a bare contentless bullet in the injected block: the loader validates domain names and states but not rule bodies. Refuse empty or whitespace-only rules at load, or drop them at render loudly.
- iss-2608261550498779Duplicate domain keys in .abcd/rules.json resolve silently last-wins: the JSON decoder keeps the final occurrence, so a repo carrying two blocks for the same domain loses the first with no diagnostic — an easy state to reach after a merge. Detect duplicate keys at load with a token-level scan and refuse or warn.
- iss-2608261550580260The prompt-router emits only domains whose content changed this turn, so a client that snapshots injected rules — a host-side adaptor staging them into a system prompt, or a future MCP consumer — keeps a domain that was deleted or renamed mid-session until session end: there is no removal signal in the protocol. Emit the full active-domain-name set, or tombstones for removals, so a snapshotting client can prune. A local second-harness adaptor lab hit this and had to accept the lingering snapshot as a recorded gap.
- iss-2608261550596333hook session-end exits 0 on every path by design and reports its outcome only as human stderr text, so a programmatic caller can detect success solely by string-matching 'abcd history: staged' or 'already staged'. A local adaptor lab shipped a silent permanent-loss bug from exactly this: non-matching stderr was first treated as success, and finished sessions were watermarked as captured when staging had failed. Give the hook a machine-readable result channel — a JSON line on stdout, or a documented stable contract — without breaking the never-wedge-the-session exit-0 behaviour toward the host.
- iss-2608261551077971Rule injection has no per-repo size budget: recall keywords and rule bodies are repo-controlled, so a hostile or bloated rules.json can push roughly 260KB into a session's context in one turn (recurring, not once: the refresh backstop clears the dedup ledger every 15 prompts by default and it is also cleared on every SessionStart/PreCompact, so the payload re-lands at least every 15 turns and after each compaction). The existing 256KiB read cap bounds the file, not the injected total across domains. Decide and enforce a per-repo injection budget with loud truncation.
- iss-2608261551087492A malformed or oversized repo guard.json disables the entire guard registry, bundled hazards included: the guard fail-opens loud (exit 1) when the repo layer cannot load, so one broken repo file switches off protections that never depended on it. This is the recorded fail-open doctrine, and a red-team round demonstrated its cost end to end. Decide the blast radius deliberately: fall back to bundled defaults when only the repo layer is broken, or keep whole-registry fail-open and record why in an ADR.
- iss-2608261635558358Audit verdicts do not propagate to the resolved issues that rode the audited spec. An issue fixed inside a spec resolves at the fixing change (Resolves trailer, watched-fail test, RS001-RS003 provenance), which is correct and deliberate — but when the intent's audit later returns NOT_MET or MET_WITH_CONCERNS on a criterion, nothing walks back from the verdict to the resolved issues whose resolved_by points into that spec: they stay resolved while the audit says the delivery fell short. The design-consistent remedy is audit back-propagation, not a pending-verification state (a candidate queue is the forgotten post-merge step the close-with-the-act rule exists to avoid): the auditor's verdict names the resolved issues riding the failed criterion and files the recurrence treatment for each — a new issue citing the old disposition, per recurrence-is-signal — so a hollow fix is surfaced by the audit rather than waiting for the defect to bite. Kin: iss-2608241612007530 (a trailerless fix is invisible to the gate) and iss-2608250844259345 (resolution frontmatter unchecked against the body) — the three together are the closure loop's three unwatched edges.
- iss-2608261719070527docs/explanation/rationale.md rests its load-bearing audience definition on an external social-media URL. The page defines who a product thinker is by linking a third-party post — a link-rot-prone foundation for the record's most important audience claim. When the page is next edited (the adopted plan expands it with the ownership/movability/build-to-learn rationale), the definition should be restated in the page's own words with the link demoted to a credited source under citation health (itd-101's alive-links scope).
- iss-2608270500184205abcd memory ask (RenderCitedMatches) prints citation fields to the terminal without termsafe.Sanitize, so an escape/control sequence in a stored page reaches the terminal raw. The termsafe sweep covered history/intent/record-lint/launch/disembark/cite render sites but not the memory-ask surface. GitHub mirror: #250
- iss-2608270500186632abcd memory ingest renders the attacker-derived IngestResult.Licence field to the terminal without sanitisation. No sibling record covers the memory-ingest licence render site. GitHub mirror: #262
- iss-2608270500190007maxGraveyardFindingsPerSignal documents that the last retained finding notes the cap, but 6 of 10 signals truncate silently with no such note. GitHub mirror: #292
- iss-2608270500191643ML001 checkLicence reads only the scalar source.class, never the plural classes: [external_pdf], so a plural-list licence passes with zero blockers. GitHub mirror: #320
- iss-2608270500192596abcd guard tokenizer has no backtick command-substitution case, so a blocker inside backticks (e.g. `gh repo delete ...`) passes unflagged. GitHub mirror: #312
- iss-2608270500192615PrecheckPayload's destination-inside-repository gate compares paths case-sensitively, so on a case-folding filesystem a case-variant --payload-dir slips the overlap gate and the render writes inside the working tree. GitHub mirror: #329
- iss-2608270500193735planEmbark's claimed map dedups targets case-sensitively, so two lifeboat files differing only in case both plan Create and the second silently overwrites on a case-folding filesystem. GitHub mirror: #326
- iss-2608270500194738backfillLegacy gates frontmatter presence on HasPrefix(text, '---') while the canonical parsers tolerate a leading HTML comment, demoting real source: provenance. GitHub mirror: #288
- iss-2608270500195431graveyard layer-2 keys ADR findings by the filename number, so two ADRs sharing it collapse to one finding and adr-012 vs adr-12 defeats cross-home dedup. GitHub mirror: #291
- iss-2608270500196428disembark review writes untrusted _provenance.json fields into the durable review .md via termsafe.Sanitize, which does not neutralise CommonMark HTML-block openers (<), allowing a hostile lifeboat to inject markdown structure into a persisted file. GitHub mirror: #325
- iss-2608270500197290checkLicence's unconditional return in the sources branch skips the scalar source.class licence check when both shapes are present, so an external_* page with an empty/junk sources: [] passes ML001. GitHub mirror: #330
- iss-2608270500198285abcd guard matchSegment/commandOf compares command basename byte-exact, so GIT push --force and other case-variant spellings bypass the matcher on a case-insensitive macOS filesystem. GitHub mirror: #315
- iss-2608270500198416abcd guard reserved keyword set omits bash coproc, so 'coproc git push --force' never reaches command position and every blocker run through coproc is silently allowed. GitHub mirror: #318
- iss-2608270500198764record-lint validateIntent/checkRecordFilename never validate the intent frontmatter id, while intent.Load fail-closes the whole corpus on an empty id, so a malformed id passes lint but breaks the loader. GitHub mirror: #279
- iss-2608270500199536memory yaml.go asymmetric delimiter parse: opening --- is TrimSpace-tolerant but closing is byte-exact, so a trailing-space closing delimiter drops source: and bypasses ML001. GitHub mirror: #304
- iss-2608270500200205abcd guard isShellFamily omits rbash and yash, so their -c payloads are never descended into and every blocker run through them is silently allowed. GitHub mirror: #353
- iss-2608270500201901a relative ABCD_PLUGIN_ROOT makes ahoy install write a self-referential (abcd -> abcd, ELOOP) or dangling PATH entry and report it as wrote:, because the anti-dangling guard stats against the process CWD while the kernel resolves against the link's directory. GitHub mirror: #334
- iss-2608270500202144the leading \b on every secret token pattern is defeated by a word-char prefix from a percent-encoded delimiter (%3Dghp_...), so a live PAT/JWT/AWS key embedded in a URL-encoded URL survives history.Capture redaction and is written raw into the committed transcript. GitHub mirror: #370
- iss-2608270500202696validateSourceBlock's single-source branch requires only class, so an external_* page written without source_hash passes validation and abcd memory lint reports only an MQ003 info whose 'no external source' reason is false, so the MQ001/MQ002 quotation-budget blockers never run. GitHub mirror: #362
- iss-2608270500202786walkLifeboatFiles counts only regular files, so an untrusted lifeboat made purely of directories never trips maxEmbarkFiles: a deep directory chain walks unbounded and can OOM the CLI. GitHub mirror: #337
- iss-2608270500203019walkLifeboatFiles walks an untrusted lifeboat with fs.WalkDir (unbounded ReadDir(-1) per directory), so one wide directory materialises and sorts its entire entry list before the maxEmbarkFiles cap can fire. GitHub mirror: #343
- iss-2608270500205262abcd guard silently allows every blocker run through watch '<cmd>' and GNU parallel: these single-string launchers pass their command to sh -c but are in no launcher table, so the quoted payload stays one opaque token. GitHub mirror: #354
- iss-2608270500206633record-lint reads record frontmatter with the lenient canonical scanner while capture's strict parser refuses the same bytes, so a duplicated key or 'id : ' (space before colon) ships lint-green but is skipped by every capture verb, silencing the armed issue_impact_valid blocker and bypassing record_schema. GitHub mirror: #357
- iss-2608270500207078record-lint and docs-lint test the .md extension case-sensitively, so renaming a record to .MD flips the gate from blockers to exit 0, voiding every blocking rule including record_schema's own malformed-filename check while the lifeboat still packs the file. GitHub mirror: #333
- iss-2608270500207987a status: superseded (content-exempt) spec passes record-lint but spec.Load validates intent/id unconditionally, so a malformed intent/id aborts the entire load. GitHub mirror: #331
- iss-2608270500208672capture's private frontmatter parser matches ledger delimiters byte-exact while record-lint and the graveyard use the canonical whitespace-tolerant scanner, so a '--- ' (trailing-space) delimiter yields a lint-green issue file every capture verb refuses and abcd iss-N reports 'not found'. GitHub mirror: #338
- iss-2608270500208736a roots entry pointing at a non-existent directory makes docs-lint / record-lint pass with zero findings, silently disarming every per-file blocker rule for that tree; the shipped scaffold's roots default triggers it in any adopter whose docs live elsewhere. GitHub mirror: #360
- iss-2608270500209138the aws_access_key secret pattern matches only AKIA, so an ASIA-prefixed temporary STS access key ID ships and writes to history un-redacted while its shape-identical AKIA sibling is a hard_fail block. GitHub mirror: #358
- iss-2608270500209352abcd capture kebab-cases the home path into the slug/filename before redaction, so the username still lands in the issue filename even though the body is redacted. GitHub mirror: #485
- iss-2608270500210055README and docs state no requirements, but git is an undocumented hard runtime dependency; there is no Requirements/Prerequisites heading. GitHub mirror: #496
- iss-2608270500214438manifest_path from version-location.json is not path-contained: validateVersionLocation only checks non-empty (unlike launch include patterns which reject .. and absolute), so editManifest can stamp a payload outside the destination. GitHub mirror: #488
- iss-2608270512210664Repo-object settings that gate merge behaviour (delete_branch_on_merge, allow_merge_commit/allow_squash_merge/allow_rebase_merge) have no source-of-truth in the tree: the .abcd/work/rulesets/ mirror covers branch RULESETS only (protection, review, merge queue), not the repository-object settings that live behind the separate GET repos/{owner}/{repo} API. delete_branch_on_merge was enabled 2026-08-27 with no accompanying tree record, which the rulesets README's own rule forbids ('refreshed by hand in the same change as the settings edit it records'). Fix: add a repo-settings.json snapshot sibling to the ruleset mirror (or fold repo settings into that mirror) and record the merge-hygiene settings there; itd-92's drift check should then cover it.
- iss-2608270539033662abcd should propagate its convention DEFAULTS to the repos it manages, not only enforce them in its own repo. The AI-attribution footer (the kernel 'Assisted-by: Claude:<model>' trailer prescribed in AGENTS.md and enforced by .github/workflows/attribution.yml + scripts/check-attribution.sh) is the motivating example: ahoy install / prepare-this-repo do not currently write the attribution convention or its CI gate into a managed repo (a grep of internal/core/ahoy and internal/core/repolint for 'Assisted-by' is empty). The same holds for other defaults abcd owns (the rules-loader domains, the commit gates). Narrower existing records: iss-193 (attribution-identity enforcement belongs in abcd for every managed repo) and itd-91 (ai-attribution-preference, draft intent) cover the attribution slice specifically; this record is the general defaults-propagation capability those are instances of — candidate for promotion to an intent.
- iss-2608270540523859Move CONTRIBUTING.md and SECURITY.md from repo root to .github/ to de-clutter root. NOT a plain git mv: both are load-bearing inputs to abcd's own site build. Required coupled changes: (1) internal/core/site/compose.go footer builds 'blob/main/SECURITY.md' links from a hardcoded root-relative list — update it or the security link silently drops; (2) the contributors/attribution page is config-driven from CONTRIBUTING.md via record_pages.contributors.policy.file (.abcd/config/site or equivalent) — repoint to .github/CONTRIBUTING.md; (3) remove CONTRIBUTING/SECURITY stems from the stray_root_docs allowlist (internal/core/lint/config.go); (4) fix ~6 relative links (README.md, ACKNOWLEDGEMENTS.md, AGENTS.md, CONTRIBUTING.md->SECURITY.md, and site markdown/explorer tests pinning ../../CONTRIBUTING.md and CONTRIBUTING.md#attribution); (5) internal/core/lifeboat/probe.go known-files list names CONTRIBUTING.md; (6) confirm GitHub still surfaces both community-health files from .github/ (it recognises root, docs/, and .github/). Verify with site-render + docs-lint gates. Related to the root-layout / config-placement ADR discussion and the governance/ mirror rename.
- iss-2608270550201935Ship an advisory-dedup echo into 'abcd capture': on write, run a NON-BLOCKING similarity scan over open/ issues plus draft intents, and when a strong match is found return it in the capture result (e.g. 'captured iss-N; possible overlap: itd-91, iss-193 — review?') WITHOUT gating the write. This gives the user immediate 'this area is already tracked' reassurance while keeping capture one-line and friction-free — verifier-selects/gates-decide: the tool proposes the overlap, the human disposes (keep / wontfix / promote). Distinct from itd-84's capture-time VALIDATOR (a deterministic pre-pass that decides INTENT decomposition FILE-AS-IS/SPLIT/HOLD, not issue-duplicate detection) and from itd-87 (recurrence-escalation in capture). The deeper cross-corpus combine — merging issue clusters and promoting to intents — is a separate periodic step (e.g. a 'capture list --dedupe' view), not per-capture. Motivated 2026-08-27 by a session that recorded a duplicate of itd-91 and caught it only after the write; until this ships, the documented protocol (agent recall-checks the ledger before recording) is the gate. Candidate for promotion to an intent.
- iss-2608270559310755launch scaffold's release.yml.tmpl is hardcoded to abcd-cli's OWN artifact shape, so it calls itself a 'generic bare-repo' workflow but is not generic: it runs 'make build' to cross-compile 'the four binaries', 'sha256sum abcd-* > checksums.txt', and 'gh release create <tag> bin/abcd-* bin/checksums.txt' as literals (only the verify/Run step is a <% %> substitution). A scaffolded repo that is not a Go CLI producing four abcd-* binaries via make build therefore gets a release workflow that builds/publishes the wrong (or no matching) assets, and its install path expects artifacts the release never produces. This is the confirmed 'asset gap' seen in a scaffolded non-abcd-cli repo (its install expected four tarballs + SHA256SUMS the workflow does not publish). Fix requires a product decision on how a non-abcd-cli repo declares/derives its build+artifact shape (parameterise the build command / artifact glob / checksum name via render.go substitutions with a repo-declared shape; or detect Go-CLI vs other; or scaffold only the generic release plumbing by default and make binary build/publish opt-in). Neighbour iss-2608261041218890 (release.yml tag not shape-checked before make build) is a different defect in the same template. Do NOT touch abcd-cli's own .github/workflows/release.yml.
- iss-2608270559313719abcd launch --dry-run (and ship) in a NON-plugin-payload repo dies with a raw 'include config not found: .abcd/config/launch-payload.json' (LoadIncludes preflight in internal/core/launch/includes.go), giving the operator no idea WHY. launch preview/ship is a plugin-payload-repo feature (it needs launch-payload.json, and ship additionally needs .claude-plugin/plugin.json); a repo that ships no plugin bundle legitimately has neither and should be told so, not handed a missing-file error. Fix (loud-staging/legibility): when the launch config is absent AND the repo is not a plugin-payload repo, the dry-run should explain 'launch preview/ship applies to plugin-payload repos; this repo's release path is launch scaffold + the CHANGELOG roll + auto-release' rather than reporting a raw missing include config. Surfaced from a Testimony (non-plugin repo) onboarding session.
- iss-2608270636272755abcd's remote-config apply verb should enable GitHub native secret scanning AND secret-scanning push protection by default on every managed repo (belt-and-braces alongside the CI gitleaks full-history scan): push protection blocks a secret at push time, earlier than CI, and secret scanning covers the default branch continuously. Enabled by hand on [redacted-user]/abcd 2026-08-27 via PATCH /repos/{o}/{r} security_and_analysis (both were disabled). Notes: push protection requires secret scanning enabled first; both are free on public repos; secret_scanning_non_provider_patterns and secret_scanning_validity_checks remain optional further hardening. Homes: the read-only VERIFY side is itd-92 (the doctor now reports these toggles); the APPLY-by-default belongs to the separate adr-44-bound apply intent itd-92 defers to, adjacent to itd-106 (abcd sets up the CI a repo requires); the desired state should be mirrored in the repo-settings.json sibling (iss-2608270512210664).related itd-153
- iss-2608270645473170The capture/scanner redaction over-masks the owner segment of a public 'owner/repo' string, replacing a legitimate public GitHub org/user name with [redacted-user] even when it is the very repository the record lives in. Observed 2026-08-27 when a captured issue body referencing this repo's own owner/repo slug had the owner masked. Not harmful (the slug still reads), but a false positive: the identity/path redaction treats an owner/repo owner as a sensitive identifier unconditionally. Consider exempting the repo's own owner (and public org names) from identity redaction, or narrowing the owner-segment match. Adjacent: iss-324 (scanner ispathsegmentbyte includes the slash in a third-party path).
- iss-2608270655490198launch installsurface.go dirTree.resolve carries a bespoke partial path guard (rejects absolute and a leading ../ but not an embedded a/../../b) instead of the canonical fsutil.ValidRelPath. Read-only payload smoke so lower severity, but it should use the one canonical containment. Flagged by the #488 fix agent.
- iss-2608270655490511launch bundle scanner skips the .lock extension as if binary, but lockfiles are text and can carry secrets, so an included .lock ships unscanned (same class as the .svg gap the launch-payload fix closed, but pre-existing and out of that scope). Flagged by the launch-payload fix agent.
- iss-2608270655495573memory persisted-file WRITE path still emits raw control characters: yaml.go dumpString, RenderIndex/RenderContradictions/renderLogEvent, and the source-block licence written into page frontmatter are not run through termsafe.CleanProse, so a raw cat/git diff/pager over a committed memory page replays escapes. Lower-acuity write-time follow-up to the terminal-render fix (#250/#262), which closed the acute read path. Flagged by the #250/#262 fix agent.
- iss-2608270655497992abcd guard wrappers map omits the zsh precommand modifiers noglob and nocorrect, which behave like the command/exec/nohup wrappers already handled, so a blocker after noglob/nocorrect stays out of command position. Wrapper-family sibling of the closed coproc/#318 keyword gap. Flagged by the #318 fix agent.
- iss-2608270655498099site build's two lint.LoadConfig(joinRepo(...)) reads delegate into the external lint package and are not ancestor-symlink contained like the rest of site's reads now are (post-#487). A committed directory symlink ancestor of the lint config path is followed. Separate hardening in the lint package. Flagged by the #487 fix agent.
- iss-2608270655499478record-lint vs capture parser divergence remainder: block-sequence frontmatter fields are legitimate and used in 21+ intent/adr records but only capture's strict ledger parser rejects them, so a correct fix is store-scoped (share capture's typed strict parser through the canonical frontmatter package) rather than a universal rejection. The duplicate-key and space-before-colon halves of #357 are fixed; this block-sequence remainder is the follow-up. Flagged by the lint-integrity fix agent.
- iss-2608270720336165The percent-decode pre-pass added for #370 (internal/adapter/scanner/percent.go / scanner.go ScanText) re-runs only the token-pattern matchers on the decoded copy, not the IDENTITY matchers (matchers.findings runs on the raw line alone), so a percent-encoded home path or email (e.g. %2Fhome%2Falice%2F.ssh, %61lice%40host) can survive redaction into a committed artifact (memory --keep-original, intent body, capture ledger). The literal $HOME backstop also sees only the encoded bytes. This is a scope boundary of the #370 fix as designed (its comment scopes to the leading-\b token patterns), not an integration regression — surfaced by the consolidated adversarial review of the security cut. Fix: run the identity matchers (and the $HOME backstop) over the decoded copy too, mapping hits back to raw spans as the token path already does.
- iss-2608270726594752abcd's vulnerability-reporting policy is below SOTA (ISO/IEC 29147, CERT/CC coordinated disclosure, disclose.io). SECURITY.md covers the reporting channel, a one-week acknowledgement, scope and supported versions, but lacks: (1) a coordinated-disclosure timeline / embargo window (e.g. fix-within-N-days, public disclosure after fix or 90 days); (2) a safe-harbor clause for good-faith research; (3) the credit policy decided 2026-08-27 (opt-in GHSA credits field / Reported-by on public issues / never ACKNOWLEDGEMENTS). And the repo publishes no security.txt (RFC 9116, /.well-known/security.txt), the machine-readable 'where to report' pointer. Fix (docs-only): extend SECURITY.md with the timeline, safe harbor and credit policy, and add a served security.txt. Maps to the reporting side of the 2026-08-27 security-advisory-handling pilot (ISO 29147); the handling side maps to ISO 30111 and graduates to the automation intent.
- iss-2608270735420161Hardened the git check-ignore probes to run under the isolatedGit exec pins (core.hooksPath, core.fsmonitor).
- iss-2608270735421311Hardened the public install one-liners to match bootstrap's curl lockdown (-q first, proxy/CA scrub, proto pins).
- iss-2608270735422415intent redacts caller text before persisting a draft, so a secret or home path is not committed (GitHub mirror: #486).
- iss-2608270735422516launch scans the payload on the materialising render path, so a secret in an included file cannot ship unscanned (GitHub mirror: #328).
- iss-2608270735422697site build reads repository sources through an os.Root, so a committed directory-symlink ancestor is not followed (GitHub mirror: #487).
- iss-2608270735423546urlguard blocks the provider platform magic IP so an SSRF fetch to the host-platform endpoint is refused (GitHub mirror: #324).
- iss-2608270735427309Hardened the memory store's reads, lint and coverage against a committed store-directory symlink.
- iss-2608270735428304launch's structural deny is applied per path segment and case-insensitively, so a nested or case-varied denied namespace cannot enter the payload (GitHub mirror: #335).
- iss-2608270735428527Hardened ahoy install to contain its writes within the repository root and to refuse a non-real .abcd directory.
- iss-2608270735433799Hardened the launch bundle scanner to fail closed on an include-selected file it did not scan.
- iss-2608270735436138Hardened abcd memory ingest to scan and redact acquired source text before it is written to the store.
- iss-2608270908332975parseSpec reads id/intent with no null gate, so id: NULL yields a malformed-shape diagnosis while lint's schema gate reports the field unset — the spec-family sibling of the iss-286 divergence
- iss-2608270908339164glossary index tests presence with TrimSpace-empty only, so term: NULL or status: ~ is accepted as a literal value and mints a term named NULL — a YAML null becoming data rather than a diagnosis
- iss-2608270908340925ahoy receipt classification's under() is a third verbatim copy of the lexical containment compare and is case-sensitive, so a case-variant path is mis-classified for receipt redaction on a case-folding filesystem — route through fsutil.PathWithin
- iss-2608270908341622ahoy's home redaction tests HasPrefix(p, home+sep) case-sensitively, so a case-variant HOME spelling leaks the identity path in rendered output on a case-folding filesystem
- iss-2608270908341877externalSourceHashes derives external classes from sources entries and the scalar source.class but never the plural source.classes, so a plural-shape page's source_hash is dropped from quotation-coverage accounting — the resolved plural-classes licence gap's coverage sibling
- iss-2608270908342149checkQuotation returns before the span loop when a page has no external hashes, so a legitimately hashless page quoting a 160-word contiguous span emits no MQ001 at all, while 06-lint.md states the denominator-free span half still applies — fixing it changes lint output for legitimate pages, so the contract call is a human decision
- iss-2608270908342889capture's validateStrict refuses enum membership, kebab slugs, unknown fields and folder-to-field invariants that no lint rule mirrors, so a record capture skips is lint-green and invisible to every capture verb — fail-soft, but a lost-record class with no armed detector
- iss-2608270908344367synthesis_principles dedups principles by ADR id with a silent first-wins map, so a genuine ADR-number collision drops a prn-adr-N with no marker while the neighbouring review and lessons ingests announce their drops
- iss-2608270908344426an ADR with an absent or null frontmatter id is lint-green — record_schema declares no required ADR fields and checkRecordFilename returns early — while describeADR cannot dispatch it and recordid.Resolver resolves it from the filename, so two readers of one store disagree and abcd adr-N reports not found: the ADR-family analogue of the resolved intent and spec loader-parity defects
- iss-2608270908346617record filename grammar diverges: lint's schema accepts an arbitrary tail and zero ordinal where recordid and capture require a kebab slug and positive ordinal, so a file like iss-5 with an underscore tail is lint-visible but dropped by capture's scanLedger into neither Issues nor Skipped and is a hard CitationError when cited — a silently lost record
- iss-2608270908346940two ADRs sharing a filename ordinal make the second unreachable: describeADR routes on the first matching ordinal and no lint rule checks ADR id uniqueness, the backstop recordid.Resolver's first-in-scan-order comment assumes exists
- iss-2608270908348042five delimiter-compare variants remain beside the canonical frontmatter.IsDelimiter: gate-side TrimSpace compares in lint and glossary accept an indented delimiter the canonical rule refuses, intent and changelog carry tolerant local copies, memory keeps its own close predicate, and site tests a bare HasPrefix — one consolidation pass onto the canonical predicate closes the family
- iss-2608270908348796probe's record-home listing reads at most maxDirEntries entries per directory, so a home beyond the bound silently drops records from every graveyard scanner's input set with no per-scan notice — the input-set sibling of the resolved per-signal cap announcements, beside the iss-134 determinism note
- iss-2608270908349399update's Homebrew Cellar refusal matches brewCellarPrefixes case-sensitively, so a case-variant Cellar path on macOS falls through to the generic foreign-symlink refusal and the operator gets the wrong remedy text
- iss-2608270908349721graveyard's intent and wontfix-issue signals keep the silent first-wins drop the ADR path just lost, and the package has no canonicaliser for itd or iss ids, so itd-7 and itd-007 read as distinct findings — the two remaining families of the resolved ADR collision defect
- iss-2608270926030978FoldPath lower-cases but never normalises Unicode, while APFS is normalisation-insensitive as well as case-insensitive, so NFC and NFD spellings of one directory compute as non-overlapping in every folded gate — the payload-destination gate, the pack overlap gate and embark's claimed key close the case half of an equivalence class whose normalisation half stays open
- iss-2608270926031827the intent and spec loader-parity lint gate reads frontmatter from the first delimiter while the loaders require it on line 0, so a record led by a blank line or an HTML comment is lint-green yet fail-closes the whole store for every puller — the parity rule must refuse a preamble-led record in the families whose loaders refuse it
- iss-2608270926036528gvCanonADRID returns empty when the ADR ordinal overflows Atoi, so an overlong id silently drops the finding the previous regexp path emitted — canonicalise textually by trimming leading zeros so overflow cannot unmake an identity
- iss-2608270926036966IsDelimiter trims a BOM on every line, so a mid-file zero-width no-break space before --- closes frontmatter.Fields early while intent's writer walks past it — abcd intent plan then inserts kind and spec_id into the record body, reports success, and reload shows an empty spec link; changelog's bodyStart carries the same stale rule under a comment claiming exact agreement. BOM tolerance belongs to the first line only
- iss-2608270926037088graveyard evidence is terminal-safe but not markdown-safe and untyped: termsafe.Sanitize leaves CommonMark and raw-HTML openers for the layer-3 interpreter to read, and cap or shadow notices share the plain evidence string array with record-influenced text, so a crafted path can forge an omission notice — a typed field or CleanProse pass closes the channel
- iss-2608270926037660derivedClasses takes the classes list in an else-if that shadows the scalar class, so a memory page declaring class: external_pdf beside classes: [session_memory] and no licence passes ML001 that main raised — the lint path never runs the write-path exclusivity validator, so nothing else catches the combination; the derivation must union the scalar with the list
- iss-2608270930248619pack.go's within() is dead production code after the fsutil consolidation — its only caller is a test while pathOverlaps calls fsutil.PathsOverlap directly; remove the wrapper and point the test at the production path
- iss-2608270945464715banlist's declaresFormat strips a BOM from any line with no index guard while every other reader trims it at line 0 only — its misplaced-declaration caller fails closed, so an inconsistency in the BOM-position family rather than a defect
- iss-2608270945468534SourceClasses shadows in the opposite direction to the lint derivation — it returns the scalar class alone when both shapes are present, so a both-shapes page renders under its scalar class in the generated index and write log while lint counts the union; display-only and behind the write-path exclusivity check, but the last surviving instance of the shape-shadowing root
- iss-2608270945469978gvADRIDFromFilename still parses the filename digit run with Atoi and returns empty on an over-int ordinal, so a huge filename ordinal with no frontmatter id skips the record silently — the filename-fallback edge of the resolved textual-canonicalisation fix
- iss-2608271014245874The /abcd:version binary-missing recovery guidance over-promotes the build-from-source rung, so an agent facing a failed provisioning tells the user to install Go — which is a dependency of neither supported install route. Both the plugin route (hooks/bootstrap.sh fetches a checksum-verified prebuilt release binary) and the CLI one-liner download a prebuilt binary; Go is only for building from source in a contributor checkout or an unsupported platform. commands/version.md's Binary resolution section lists 'go run ./cmd/abcd' as a peer rung without telling the reader that a genuinely missing binary is recovered no-Go: bootstrap re-provisions on the next networked session, reinstalling the plugin, or the CLI one-liner. External GitHub issue #494: a contributor concluded Go was required.
- iss-260827112130121604-surfaces/05-intent.md states bare-command-as-help is a universal abcd convention showing status plus suggested next actions on every command. False against the binary (version prints a version block; the docs/history/disembark cobra parents print help with no board; no bare verb emits suggested next actions) and contradicted elsewhere in the same brief. Found by the v0.6.7 release-gate brief-surface cross-check.
- iss-2608271121307905The brief command enumerations omit the shipped site verb: 04-surfaces/08-abcd.md counts the /abcd:<verb> surface as nineteen verb files and 05-internals/08-skills.md as sixteen binary-backed top-level commands, both stale by one since site (Go verb, commands/site.md, sub-verbs build and check) shipped. Found by the v0.6.7 release-gate brief-surface cross-check.
- iss-2608271140346423The abcd guard coverage prose in three user-facing places still describes the pre-gh-312 backtick limitation: guard.go's 'guard check --help' string and the generated docs/reference/cli/commands.md say the top-level backtick substitution is not followed (a disclosed v1 limit, iss-148), and commands/guard.md lists 'one inside a backtick substitution' among what an allow does not see. The gh-312 fix now follows top-level backticks into command position like the dollar-paren form, which the v0.6.7 Security changelog advertises — so the shipped help and docs contradict the release's own changelog and under-report a security capability.
- iss-2608271322159887the change landing the externally proposed README requirements structure carried only a Reported-by trailer: the ACKNOWLEDGEMENTS entry owed in the same change was omitted, and the contributor's offered branch was re-authored rather than adopted, so the contributor appears nowhere in the contributor graph
- iss-2608271539271972the pilot note's second-operator fold-in landed without a self-consistency sweep: the '### Merge landed as (fill in at cut)' stub for the PR #526 merge is unfilled with its two-parent check unticked, F-N/F-O/F-D sit at '##' as peers of the umbrella heading that enumerates them as subordinate, and both enumeration captions (the umbrella and the final verdict's acceptance-criteria cite) still cap at F-V although F-W exists
- iss-2608271702469341intake.md graduates to the durable record when the contribute-triage verb ships: .abcd/work/intake.md stays in the working tier today as the live S1-S6 external-contribution runbook (the 2026-08-27 structural review re-adjudicated its placement: live operating state, cited in force by [dcn-2608190000000002](../../decisions/dcn-2608190000000002-review-agents-keep-their-bash-grant.md) and filed-against by ledger records), but its own header declares it the script-first MVP rung that a future 'abcd contribute triage' verb absorbs. When that verb ships, the protocol content is no longer working state and the document's home moves up: promote the durable protocol description into .abcd/development/ (brief surface or discipline record) in a change that says why, leave or redirect the working-tier path for in-flight citers (iss-276 and resolved iss-2608261533173466 cite found_at .abcd/work/intake.md; [dcn-2608190000000002](../../decisions/dcn-2608190000000002-review-agents-keep-their-bash-grant.md) cites its S4 rule), and record the supersession of the highlight-not-inventory adjudication ([dcn-2608210000000001](../../decisions/dcn-2608210000000001-bug-hunt-round-4-branch-bughunt-b.md), [dcn-2608220000000001](../../decisions/dcn-2608220000000001-bug-hunt-round-7-branch-bughunt-b.md)) for this file. Trigger is the verb shipping, not a date.
- iss-2608271707587825promote the attribution-rewrite tables to the durable record: .abcd/work/attribution-rewrite-2026-08-06/ holds the sha and tag translation tables for the 2026-08-06 history rewrite, and its own README declares them historical and complete (one event, nothing appends) — durable-record shape, not working state. The 2026-08-27 structural review also found the sha-map is the only translation key for the five pre-rewrite receipt-directory ids under .abcd/work/reviews/. Move the directory to .abcd/development/research/data/ via the tier charter's promotion path (an artefact that proves durable moves up, in a change that says why), repoint the reviews-charter reference and the DECISIONS.md mention, and log the supersession of the highlight-not-inventory adjudication for this path. Deletion is off the table: the 725-row sha-map is the sole old-to-new history bridge.
- iss-2608271711530571docs/README.md advertises tutorials/ as a populated Diataxis home while the directory holds only a 6-line README and zero content pages. Until the iss-216 getting-started page lands (the real close), the table row overstates the tree: mark the tutorials row as not yet populated and name iss-216 so a reader is not routed to an empty home.
- iss-2608271711535817the brief's canonical docs tree drifted from the shipped tree: .abcd/development/brief/05-internals/03-configuration.md line 441 names the task-oriented home guides/ while the shipped directory, docs/README.md and every other reference say how-to/, and the tree block lacks an assets/ line although adr-47 decision 2 sanctions that directory. Correct the tree block — rename guides/ to how-to/ keeping the comment, add the assets/ line citing adr-47. No file moves; the shipped tree is the truth.
- iss-2608271711538151docs/requirements.txt is published verbatim into the built site: mkdocs.yml sets docs_dir: docs with no exclude_docs, so the Python pin file ships as a public page of the rendered site. Fix is one line — exclude_docs: requirements.txt in mkdocs.yml. Moving the file was considered and rejected: CODEOWNERS, two site.yml lines and an out-of-tree wrangler build command all name the current path.
- iss-2608271711539855the docs-lint harness rules miss bare host-name tokens in paths and env vars: docs/how-to/install.md names the host harness twice in hand-written prose — a .claude-plugin/ directory link and the $CLAUDE_PLUGIN_DATA cache variable — with no docs-lint finding and no sanctioned allow escape. Fix the detector first: widen the harness/claude-code pattern in .abcd/docs-lint.json so a product-name token inside a path or env var is caught, and watch it fire on both install.md sites before deciding the prose remedy. Whether install pages get a per-line allow marker is already an open decision on iss-216 — do not pre-empt it here.
- iss-2608271804174103the capture allocator lock is git-tracked against the repo's own ignore rule: .abcd/work/issues/.iss-alloc.lock is committed as the empty blob although .gitignore declares it out of the tree, unlike its sibling .abcd/work/.decisions.lock which is correctly untracked. Fix is git rm --cached — nothing on disk changes and the allocator keeps flocking the same path.
- iss-2608271804176759the specs store has no charter and its id namespace is doubly allocated: specs/ is the only durable-tier record family with no README at any level (directory_coverage flags specs/, open/ and closed/ independently), the live store is spc-2..spc-42 while the retired predecessor store minted its own spc-1..spc-83, and above-ceiling references now collide — spc-33 and spc-37 resolve to live specs on different subjects than the retired records the citations meant. Write the three READMEs first (grammar, open-to-closed lifecycle, intent back-link, the no-status-field rule per adr-3, and the mandatory predecessor-store qualifier), then re-scope iss-239 with the corrected live range and the two collisions.
- iss-2608271804178239filename-slug agreement is unenforced across the record stores and two records have drifted: superseded itd-47's frontmatter slug embeds the foreign handle spc-12 (now a live unrelated spec) and its H1 carries the same stale prefix, and iss-2608231237300997 is the single ledger record whose filename slug disagrees with its frontmatter slug. Fix the two instances (frontmatter+H1 edit for itd-47; rename to the frontmatter slug for the iss record, id unchanged) and close the class: capture validateInvariants and the record-lint schema check filename id but never slug.
- iss-2608271804179102two convention documents route artefacts to the retired .abcd/logbook/ tier: the reviews charter sends per-invocation artifacts (oracle audits, grill reports, disembark audits) there and the research-notes README sends run logs and ephemeral acceptance output there, but .abcd/logbook/ does not exist, is not tracked, and is not gitignored — the sanctioned destination is .abcd/.work.local/logs/. Repoint both clauses in one sweep, citing the iss-56 adjudication; this is the deferred half of iss-73's own resolution note.
- iss-2608271804181894seven committed intents carry prd_path values pointing into .abcd/intents/, a directory that has never existed (intents live at .abcd/development/intents/), and no PRD exists at any path because the grill sub-verb that writes them is unshipped (itd-27). Set prd_path: null on all seven — the honest majority form — rather than repointing at a layout no record has adopted.
- iss-2608271804188295drafts/itd-70 is a machine-emitted stub, not a press-release intent: no press release, no scope, no acceptance criteria, and a provenance line citing spc-75 which exists nowhere (iss-239's class). The drafts lint sanctions its frontmatter shape, so the only defensible action is editorial — flesh it into a press release before anyone plans it, or delete it and let open iss-194 carry the release-retention concern.
- iss-2608271804189287the .abcd namespace documents lag the tree in four places: .abcd/README.md describes only the three subdirectories and none of the nine tracked root files the binary reads; the config/ directory and its three members are documented nowhere; the brief's canonical layout tree lists corpus.json which does not exist and nothing reads (annotate as the itd-25 design target rather than delete); and both CLAUDE.md and .abcd/README.md misstate .work.local/'s contents (missing reviews/ — the intent-audit receipt outbox — and private-names.txt, the per-machine banlist layer). One documentation sweep, framed as an index pointing at the owning records, not duplicated schemas.
- iss-2608271804491365five sha-keyed semantic-gate receipt directories under work/reviews/ name commits unreachable from HEAD: three are old-history ids from the 2026-08-06 attribution rewrite (translatable via the sha-map) and two are squashed-away branch heads with no current-history equivalent. Do not rename receipt directories; add a Receipt keys paragraph to the reviews charter recording the translation route and naming the five, so a reader stops bisecting for commits that history rewrote. Related: iss-2608271707587825 promotes the translation tables to research/data — repoint this paragraph when that lands.
- iss-2608271804494611everything under .abcd/work/ sits under no lint root: record-lint's root is .abcd/development and docs-lint's roots are docs and README.md, so the issue ledger, the reviews charter, rulesets/, DECISIONS.md, the .abcd root config files, the plugin trees, and every root prose file except README.md are gated by nothing — which means structural fixes in those areas can silently regress. iss-279 and iss-2608230752354928 capture two slices (docs-lint roots; relative links under work/); this record is the umbrella: decide the lint-root coverage for the working tier and root prose, or record why they stay ungated.
- iss-2608271804494867DECISIONS.md violates its own newest-last ordering in five places (backwards date steps among the 247 dated bullets), and nothing gates it. Do not reorder — reordering is what append-only forbids, and a naive date-monotonicity rule would refuse honest back-dated tail entries. Gate the position instead: a CI check that every line a diff adds to DECISIONS.md lands at the tail, never inserted above an existing entry.
- iss-2608271804496010eight pruned ADR ids are still cited by later records, and for four of them (adr-4, adr-8, adr-16, adr-18) the citations are live by-name references that the decisions charter's retention clause says keep a record restorable: either restore those four from the pruning commits as status superseded records, or record a maintainer ruling that body-prose citations do not count as cite for the retention clause. Needs the maintainer's call — the two remedies diverge and neither is obviously right.
- iss-2608271804497247body-prose record-id references resolve against nothing: the context_citation_currency rule's record_stores mapping covers one file, and the site record export extracts only the eight typed frontmatter edges, so adr-N/itd-N/spc-N/iss-N tokens in body prose across the durable record are checked by no gate (the mechanism behind this review's dangling-id findings). Widen the existing gate rather than adding a second: extend the export's reference extraction to body-prose tokens, flow them into the same Unresolved set and site-baseline ratchet, and seed the baseline with the first run's backlog.
- iss-2608271804497507the plugin record trees are held only by README prose: agents/ is a second record family with its own constitution (itd-5 frontmatter per prompt, an injection-canary fixture for every untrusted-input agent, a per-agent changelog) and commands/, hooks/, .claude-plugin/ carry similar structure, but no lint root or gate checks any of it — currently conformant, enforced by nothing. Decide the gate: either a record-lint root over the plugin trees with rules for the frontmatter/fixture/changelog invariants, or an explicit ruling that these trees stay prose-governed.
- iss-2608271804499169the binary declares two per-repo config paths the tree never instantiates: rule_privacy reads .abcd/config/pii.json and the launch includes-closure reads .abcd/config/scripts-closure.json, but .abcd/config/ holds neither and no doc mentions them. Both read as optional overrides, so nothing is broken — but code-declared record paths and tree-instantiated ones have no reconciliation check in either direction. Document the two optional files where the config/ members get their index entry, and consider a parity sweep between code path literals and the documented namespace.
- iss-2608271804499683the brief's adapters chapter cites a retired reviews layout: 02-adapters has the RepoPrompt adapter falling back to flat .abcd/work/reviews/*.md and its adapter table repeats that source, but the reviews charter's grammar is dated subdirectories (<YYYY-MM-DD>-<scope>/*.md) and the flat form does not exist in the tree; 01-agents' review-collator glob has the same problem plus an input the charter excludes from the folder. Correct both citations to the charter grammar and cite reviews/README.md as the source of truth so the brief stops carrying a second layout.
- iss-2608271817300337ADR seed from the security-advisory pilot's verified trust rules (itd-149 decomposition, part 2): auto-merge arms only after a comprehensive no-bypass required-check set AND an independent adversarial APPROVE, never on CI-green alone (F-N); the two release gates that are human-by-design stay human (F-Q); a verdict is never transferred — every required pass re-runs against the final content commit (F-U). These are trust-boundary rules, not intent scope: file the ADR with its brief invariant, then link itd-149 to it at planning.
- iss-2608271817309715principle seed from the pilot's F-W (itd-149 decomposition, part 3): the authorship default for external contributions is to ADOPT the contributor's commit, preserving their contributor-graph authorship; re-authoring with a Reported-by trailer is the honest fallback only when there is no branch to adopt, and the ACKNOWLEDGEMENTS entry rides the fix in the same change. No existing principle covers the authorship default; file it under development/principles/ (or fold into CONTRIBUTING) as its own act.
- iss-2608271858577043adversarial review round over the structural-review sweep (assembled diff, pre-merge): the DA001 append-only gate as first written enforced position but not preservation — a tail-reaching rewrite of committed decisions passed clean (reproduced on a copy of the live ledger), merge commits were skipped wholesale so a forged merge resolution landed unchecked (reproduced), and a non-canonical list bullet slipped the header exemption (reproduced); its refusal output echoed attacker bytes unsanitised, and seeding an empty ledger was refused. The new capture-side slug invariant was reader-only, so a drifted record turned into a silent skip instead of a red gate. Fixes ride the same change; flagged-not-fixed sibling: on merge_group events BASE_SHA is empty for ALL three diff-ranged gates (RS001/RS002/DA001), so the merge-queue entry does not run them although AGENTS.md claims it runs the lot — pre-existing pattern, needs its own decision.
- iss-2608271920597660the preflight gate-roster drift test is containment-based and a file that enumerates the roster twice defeats it: TestPreflightGateListIsNotRestatedWrongly does whole-file strings.Contains per gate, so one current enumeration satisfies the check while a second, stale enumeration in the same file misleads readers (observed live: the AGENTS.md build block still said four lint gates while its concurrent-sessions section said six). Region-scoping was evaluated and rejected in-session — any 'a region naming N gates must name all' heuristic false-positives on prose that legitimately names a subset (CI descriptions name three), and a marker comment reintroduces the sentinel defeat the test's own comment rejects. Needs a design that distinguishes roster enumerations from subset mentions.
- iss-2608280706531199docs/ violates the writing-style em-dash rule in list items across explanation, how-to and reference pages; the rule is review-only, so nothing gates it
- iss-2608280739112123capture's ledger reader is stricter than the shared recordid grammar: after standardising lint and the resolver on recordid.FilenameNumRe, capture's scanLedger/alloc/validate still use their own reFilenameID (strict kebab, no double/leading/trailing hyphen), so a hand-crafted iss-5--x.md is lint-green and resolver-visible but silently absent from capture list. Harmless direction (lint too lenient, capture cannot mint such a slug, no committed record hits it) but it leaves the writer/reader/resolver/gate on two grammars instead of one. Route scanLedger, alloc and validate through recordid.FilenameNumRe("iss") so all four share one grammar. Follow-up to the batch that closed iss-2608270908346617.
- iss-2608280750324657writing-style guide lacks an audience model: the audience-by-placement position is enacted by the tier layout and machine surfaces but ratified nowhere, and the guide has no accessible-language rules in checkable form
- iss-2608280801427648whether an adopted open-licensed style guide (Google, Microsoft, GitLab, errata-ai/Vale packages) replaces parts of the house writing guide, and how a managed repo names its chosen guide in .abcd/rules.json: routed out of itd-141 at its closure (adr-54); files as its own intent if it goes live
- iss-2608280801428646writing-style guide forward-claims staged masking lints (itd-141) that corpus evidence shows cannot ship as machine checks: the staged-lints sentence and the two lint-staged row labels over-state future machinery
- iss-2608280807166510fsutil.ValidRelPath is slash-only, so a backslash traversal escapes on a Windows target: path.Clean leaves backslashes untouched, so '..\\..\\x' passes ValidRelPath and, after filepath.Join/FromSlash on GOOS=windows, can walk out of the intended root. The gap is shared by every ValidRelPath caller (installsurface dirTree, positioning surfaces, lifeboat manifests) and is pre-existing, not introduced by the path-canonicalisation batch. Decide whether Windows is a target that ingests attacker-controlled relative config/manifest paths; if so, ValidRelPath should reject a segment containing filepath.Separator (or any backslash) as well as forward-slash traversal.
- iss-2608280813441672the rules-loader DOCUMENTATION domain text in .abcd/rules.json still claims the punctuation lint is staged as itd-141, which adr-54 falsified at the planning interview
- iss-2608280824478819The canonical credit surface is incomplete: design-shaping inspirations fully credited in the committed record never propagated to ACKNOWLEDGEMENTS.md. Backfill set from the 2026-08-28 attribution review: add Inspirations entries for CARL and PAUL (both Kahler, MIT; mechanisms adopted per itd-3 and itd-1), SpecStory (adr-29 seam, specstory-import ships in CLI help), the Karpathy LLM-wiki gist (memory-substrate pattern), gitleaks and TruffleHog (integrated scanners, one self-declared adapted regex), and Dieter Rams; complete the Diataxis entry with the author and CC-BY-SA 4.0; widen the mattpocock entry (ADR three-clause test, PRD shape); add Dell'Acqua et al. 2023 to the CSL references; add source URLs to the Horn and Weng credits and the arXiv id to the Iacob citation; record the skills' authorship in the socratic/first-principles research note; fix the dead to-prd deep link in itd-27.
- iss-2608280825450623no documented protocol tells an agent to run abcd docs lint over a drafted docs artefact before presenting it: style feedback arrives at commit time instead of draft time
- iss-2608280851288836encodeHiddenRunes is duplicated byte-for-byte in memory/ingest.go and cite/fetch.go: both packages carry an identical unexported percent-encoder for hidden runes (Trojan-source/JSON-escape class), added independently to close the same redirect-URL leak. termsafe is the canonical home for untrusted-boundary sanitisers; two private copies will drift, and a rune class added to one leaves the other door open. Export one termsafe.EncodeHiddenRunes and route both call sites through it. Follow-up to the batch that fixed iss-357.
- iss-2608281222011114the guard health report still says a broken repo guard.json means commands run unchecked, but the fail-safe fix (iss-2608261551087492) keeps the bundled hazards armed in that case: guard_health.go's guardRegistryUnloadableReason and the RegistryLoadable bool model a broken repo layer as fully-unguarded, which is now false. The health check should distinguish 'repo overrides dropped, bundled hazards still armed' (a mild, expected state) from 'no registry at all' (the only genuinely-unguarded state, which the embed makes unreachable). Refine the health model and reword the reason. Follow-up to the fail-safe change.
- iss-2608281752471145the opt-in gitleaks adapter's test fixtures commit a verbatim secret-shaped literal (a 40-char high-entropy generic-api-key value) in internal/adapter/gitleaks/gitleaks_test.go and internal/core/history/gitleaks_augment_test.go, which trips the full-history gitleaks CI scan (gitleaks git, fetch-depth 0) and fails the PR and every PR batched with it in the merge queue. Secret-shaped test fixtures must be CONSTRUCTED AT RUNTIME, never committed verbatim, so no literal ever enters git history for the full-history scan to find. Fix: a shared runtime generator produces the synthetic high-entropy value; the two fixtures call it; no literal in source. Because the literal is already committed on the branch and history rewrite is off the table (never force-push), the fix lands on a fresh branch where the literal never entered history. Also record the doctrine as a durable principle.
- iss-2608281948217899harness_session_url's opacity heuristic accepts a UUID, a base62 token (digit plus uppercase) and a long lowercase-hex run, and rejects an all-lowercase non-hex id such as session_zk3n9q2mvx8rtq. The rejection is deliberate: without it every documentation slug that follows the word session (there is one in .abcd/development/research/notes/2026-08-22-context-window-management-sota.md) becomes a finding. Whether any harness in scope mints an all-lowercase id is a fact about external services that cannot be settled from the repository. Settle it by enumerating the session-URL spellings the covered harnesses actually emit, then either widen the opacity test or record the coverage boundary in the pattern's own comment. Found by adversarial security review of itd-152.
- iss-2608281948289198agent_contract enumerates agents/*.md non-recursively, so a prompt filed at agents/<name>/<name>.md is skipped entirely — it draws no trust-contract finding, no canary demand and no changelog demand, which is a silent opt-out of the whole rule by choosing a directory. The flat layout is the documented convention (agents/README.md), so this is a gap rather than a supported layout: either refuse a markdown file found one level down as a misfiled prompt, or walk the tree. Found by adversarial security review of itd-151.
- iss-2608282026038930The guard now refuses an unquoted brace group rather than expanding it (itd-156/spc-49 scoped the expander out), so every ordinary shell brace an agent writes is blocked: mkdir -p foo/{a,b}, cp x{,.bak}, rm -rf dir{1..9}. That is the intended fail-closed posture — a word whose argv the guard cannot compute is one it cannot check — but it is a real usability cost on the PreToolUse path, paid on every command that uses a shell convenience nobody meant as a hazard. The scoped follow-up is the bounded expander the intent already names: enumerate the Cartesian product of a group's alternatives (nested groups and {a..z} ranges included) under a hard cap on the number of words produced, check each expansion against the registry, and refuse only when the cap is hit or an expansion matches a blocker. Detector: a corpus of everyday brace commands whose verdicts should be allow; acceptance: mkdir -p foo/{a,b} allows while git push {--force,} origin main still blocks.
- iss-2608282026177429itd-154 does not ship the literal 'provisioning the abcd binary...' stderr line spc-47 AC2 asks for, and the reason is a conflict inside the record rather than an oversight: only the FIRST line of a hook's stderr reaches the transcript (iss-208, measured on the first manual install), and bootstrap.sh already spends that line on the success notice's one-time ahoy-install instruction, placed first for exactly that reason (iss-207). An announcement printed ahead of it takes the line from the success and, worse, from the refusal's cause on the failing path — which is the silence itd-154 exists to end. Both orderings were reproduced during the adversarial review. What ships instead is the EXIT trap that converts a silent death into the same loud refusal, naming provisioning in the one line it emits; the residue is a run that HANGS (process still alive, trap not yet fired) or is SIGKILLed, which still leaves nothing. The fix that would satisfy both is a breadcrumb: write a marker at the start of provisioning, remove it on any terminal line, and have the next session fold 'a previous attempt did not finish' into its own terminal line rather than into a new one. Detector: kill -9 a provisioning run, start a second session, expect the next run's first line to name the previous failure.
- iss-2608282038283692A stale remote branch carrying a secret literal fails the gitleaks gate on every open pull request, and deleting the branch is the only remedy: the CI job checks out with fetch-depth 0, which fetches every remote ref, so 'gitleaks git' scans all of them rather than the pull request's own history. A literal committed on a branch whose pull request was closed and superseded therefore keeps failing unrelated pull requests, and the failure names neither the branch nor the file when the run log truncates the findings, so the natural diagnosis (a leak in this pull request) is wrong. Observed 2026-08-28: commit 9ffbbfbc on the superseded branch of a closed pull request blocked all seven open pull requests until the branch was deleted. Worth either scoping the scan to the pull request's own commits, or adding a cleanup gate that refuses to leave a leaking branch on the remote after its pull request closes.
- iss-2608282124231752scanner.ScrubOutbound has no front door: it is defined, tested and documented as the outbound-artefact scrub, but no CLI command, plugin verb or routine prompt calls it, and internal/ cannot be imported from outside the module, so the posting-time half of the harness-leak class is unmitigated in practice. This is not an oversight in spc-45, which deliberately scopes a forge client out; the gap is that nothing hands the primitive to the party that does post. Two candidate shapes for a future change: a small stdin-reading verb (abcd scrub --label pr-body) that the autonomous routine prompts pipe every PR body, issue and comment through before posting; or wiring the primitive into whatever posting path lands with itd-107, so an assembled routine scrubs by construction. Until one lands, the operative control is the re-read-and-strip policy in scanner.OutboundPolicy, as AGENTS.md, iss-178 and spc-45 state.related itd-107 · related itd-152
- iss-2608290808193471Nothing ties a merged implementation to closing its spec, so twelve specs stayed open and twelve intents stayed planned after the code that realises them landed on main: abcd spec close is the verb that advances the intent planned to shipped, closes the spec open to closed, and emits the fidelity-audit receipt, but no gate, lint rule or CI step notices that a spec is still open while its acceptance criteria are demonstrably delivered. The consequence is not cosmetic: the changelog composer reads the shipped-intent and resolved-issue folders, so a release cut derived while the intents sit in planned announces the resolved issues and omits every intent the release actually delivers. Found after the itd-150..162 implementation merged with all fourteen issues resolved but all twelve specs left open. Wants a detector for the shape 'spec open, linked intent planned, and the spec's own scope files changed since the spec was written', which is the same reference-graph the dangling-supersedes ratchet already walks.
- iss-2608290810032799The attribution gate validates the Assisted-by trailer's SHAPE but cannot tell whether the model id names the model that actually did the work, so a wrong but well-formed id passes green. In the itd-150..162 run four implementation agents were briefed with an incorrect model id: two used it as instructed and their commits passed the gate, two recognised it as a false disclosure and stamped their real id instead. The convention exists precisely to prevent a false disclosure, and the gate is blind to the only failure that matters. A full mechanical fix may be impossible because the runner cannot attest which model produced a commit, but two partial rungs exist: refuse a vendor and model pair absent from a maintained known-models list, so a typo or a stale id is caught; and have the dispatching harness supply its own model id to the agent, so a hand-written briefing cannot introduce a wrong one. Distinct from iss-211 (making the attribution preference portable) and iss-220 (composing the trailer at creation time): this is about the truthfulness of a trailer that is present and well-formed.
- iss-2608290810033503The forge reported a pull request as conflicting when it merged cleanly against both the current main and the tip of the pull request queued ahead of it, and dropped its armed auto-merge as a result. Verified by merging locally against both refs with zero conflicting paths, twice, several minutes apart. The state cleared only after pushing a merge of main into the branch, which forced the forge to recompute, after which it reported mergeable and auto-merge could be re-armed. Cost roughly twenty minutes of diagnosis on the assumption that a real conflict existed. Recording it so a future run recognises the shape: a conflicting verdict that no local merge reproduces is a stale computation, and updating the branch is the cheap remedy rather than hunting for a conflict that is not there.
- iss-2608290810034854Two adversarial reviews over the assembled multi-branch diff each returned a blocker that the same class of review had already passed over on the individual branch, and both blockers were branch-local rather than merge-only: a bare git-directory existence check that let a worktree read and enforce an unrelated repository's private name store, and a test fixture built from a live session identifier and carried past the repository's own new detector by three separate escapes in one commit. The lesson is not that more review is better. A reviewer reading one branch in isolation judges the diff against itself, while a reviewer reading the assembled tree judges it against the repository's stated invariants and notices a change that contradicts one. Worth recording in the reviews charter as the reason an integration-level pass is not redundant with the per-branch pass, and worth giving the per-branch reviewer the invariants explicitly rather than hoping it infers them.
- iss-2608290810036869git push can report success while pushing nothing, when the pre-push preflight outlasts the SSH idle timeout. The hook runs the full preflight, which takes minutes, and the connection is opened before the hook runs, so the server closes it mid-hook: the push dies with a connection-closed message, the remote ref is unchanged, and the preflight's own passing output scrolls past the failure so the whole thing reads as a clean run. Hit twice in one session. The second time the push was also piped to another command, which returns that command's exit status, so a failed push reported zero. Remedies that worked: set SSH keepalive options for the push, never pipe the push, and confirm with a remote ref listing that the tip actually moved. Worth considering whether the hook should run before the connection is opened, or whether a push wrapper should verify the remote tip afterwards; the silent half is the defect, not the slowness.
- iss-2608290810037524The capture verb refuses an unrecognised source value with a message that names neither the offending flag nor the accepted set, and blames the wrong layer: an invalid source produces a malformed-frontmatter error quoting the value, when the value came from a command-line flag and never reached any frontmatter the caller wrote. The accepted values are discoverable only by grepping existing records. The flag's help text lists no enumeration either. The same shape likely applies to category and to any other closed-set flag on this path. A closed set should be named in the refusal and in the help text.
- iss-2608290810037763Adversarial cost guards in the scanner's adjacency tests assert wall-clock seconds, which is a property of the machine rather than of the code, so they pass locally and fail on slower CI hardware under the race detector. One failed on both CI runners at 22.5 seconds against a 15 second bar while passing locally at 11.0 seconds on the same commit; the branch that introduced the probe and the merged tree measured identically, so it was not a regression. It was fixed for the costliest shape by shrinking that case's input, which is the lever the test file's own helper documents, but three sibling bars carry the same fragility and the same thin headroom. The machine-independent cost-CLASS guard beside them is the better model: it doubles the input and asserts the growth ratio, which no hardware difference can flip. Worth converting the remaining wall-clock ceilings to ratio assertions, or at least measuring a per-machine baseline and asserting a multiple of it.
- iss-2608290811463906Each run should record the model SETTINGS alongside the model id, because the id alone does not determine behaviour and so does not make a run interpretable or reproducible. Whatever the current model exposes belongs in the record: reasoning or thinking depth, temperature and other sampling parameters, a seed where one exists, the context-window variant, and any speed or quality mode the harness offers. Two runs stamped with the same model id can differ substantially on all of these, so a record that names only the id invites a false comparison between them: an audit verdict, a benchmark, or a regression blamed on a code change may in fact be a settings difference. This matters most where a verdict is treated as evidence. The intent-audit verdict already carries a verifier block of id and version, which is the natural place to widen; the per-run transcript store is the natural home for the settings of an ordinary session; and the Assisted-by trailer is NOT the place, since its accepted shape is a vendor and model pair and widening it would break the gate that reads it. The hard constraint is the same one iss-2608290810032799 records: a model cannot reliably introspect the settings it is running under, so the harness has to supply them. That makes this a capability of the dispatching layer rather than something an agent can be instructed to self-report, and any design that asks the agent to state its own settings inherits exactly the truthfulness problem that the attribution gate already has.related itd-166
- iss-2608290819228175A decision recorded in an intent, an ADR or the decision log should point at the section of the redacted transcript where it was actually made, so the reasoning behind a record is recoverable rather than lost with the session that produced it. This is the Naur point the lifeboat work already rests on: the record is the floor of recoverable theory, not the theory itself, and today nothing leads from a decision back to the conversation that reached it. The store is closer to this than it first appears. A transcript record already carries session_id, a source_sha256 content hash, and captured_at as an RFC3339 nanosecond timestamp, so the SESSION is timestamped and content-addressed already. What is missing is granularity inside one transcript: there is no per-turn or per-section anchor, so a link can name the session but not the passage. Two constraints shape the design and both rule out the obvious approach. A line number is the wrong anchor, and the repository already refuses that shape elsewhere through the no-brittle-line-refs rule, which tells an author to use a section anchor instead. And redaction rewrites spans in place, so any byte offset or line number computed against the raw transcript is invalid against the stored redacted one: an anchor has to be derived from the redacted artefact, or be content-addressed rather than positional. The plausible shape is therefore a typed cross-reference carrying session_id plus source_sha256 plus a stable intra-transcript anchor, minted when the decision is recorded rather than reconstructed later, with per-turn timestamps or ids added to the stored transcript so such an anchor exists to name. Worth deciding whether the anchor is a turn id, a content hash of the passage, or a heading, and whether the link is stored on the decision record, in the transcript, or both.related itd-171
- iss-2608290820473197An INCONCLUSIVE fidelity verdict is terminal, so an audit that could not decide anything is indistinguishable from one that passed. The ingest does not branch on the verdict value: it rolls the per-criterion verdicts into counts and replaces the parked OWED marker with INGESTED whatever they say, so a verdict of all-INCONCLUSIVE closes the receipt exactly as a verdict of all-MET does. The re-emit verb then refuses to reopen it, reporting already_ingested and leaving the Audit Notes untouched, which is correct for a decided audit and wrong for an undecided one. The consequence is that there is no way to ensure the re-run that an INCONCLUSIVE calls for. The only lever that produces a fresh receipt is editing the acceptance-criteria section, because the receipt digest is taken over that section alone, which conflates two unrelated acts: clarifying a promise, and retrying an audit that was merely under-fed. This is a loud-staging violation in the precise sense the principle names, since a stage that degraded presents as a completed one. The narrow fix is for the ingest to branch: an INCONCLUSIVE leaves the receipt OWED, or moves it to a distinct re-run state, so the outstanding work stays visible without minting a ledger issue for what is an input fault rather than a product defect.
- iss-2608290822140563The fidelity audit runs after the merge, so its verdict arrives when the cheap remedies are already gone, and the code refuses any other ordering: the ingest rejects an intent that is not in the shipped bucket, and the emit fires from the ship move itself, so an intent cannot be audited against the candidate diff on a branch. The stated reason is sound as far as it goes, that a report-only review must never un-ship what has already shipped, but it answers a question that only arises because the audit was placed after the merge in the first place. Audited before the merge, a failing criterion has three cheap answers: fix the branch, revise the promise before making it, or decline to merge. Audited after, it has none, because there is no un-ship path and the code is on the trunk. The counter-argument is real and should not be waved away: a branch is not the tree that lands, since the merge queue lands merge commits and a semantic conflict with a concurrently merging change can alter the delivered reality after the verdict was formed, so the post-merge audit judges what is actually true while a pre-merge one judges a candidate. The shape that gets both is to gate on the pre-merge verdict and bind it to a content hash of the tree it judged, then check deterministically after the merge that the landed content still matches, reopening the receipt only on a mismatch, which costs one hash comparison rather than a second audit and reuses the content-addressing the transcript store already relies on. Whatever the ordering, the model's verdict must stay a proposal and a human acknowledgement must remain the gate, because a non-deterministic verdict that can block a merge on its own is a trust step this repository has not taken and would train people to route around the gate.
- iss-2608290833558547The README and the roles page state as achieved what is still the design intention, which is the front-door version of the loud-staging violation the project exists to refuse. Three claims outrun the code. The README says the records are checked by gates that refuse rather than warn, but the lint engine carries a warn severity and uses it: this run's own preflight emitted a warn-level finding and a docs-lint line reading one finding and zero blockers, so an advisory tier exists by design and the sentence denies it. The README then says what these records claim about the product being built stays true as the product moves, but the only mechanism that could make that true is the intent-fidelity audit, and that audit is report-only by construction, refuses to run against anything but an already-shipped intent, cannot be re-run once an inconclusive verdict is ingested, and is read by no gate. Empirically the claim is false today: twelve intents describe capabilities that are on the trunk, not one has been audited, and twelve specifications sit open while the code realising them has shipped, with nothing detecting the drift. The roles page goes further than the README and promises the product thinker a moment of reading the verdict on whether the why was delivered, and promises the facilitator will say what to do about a mismatch, when no verdict has ever been produced and no remedy path for a failed criterion exists. The README also flattens the three roles into agents and humans, which contradicts the roles page it links to and is the same conflation that makes it easy to argue a facilitator duty must stay manual because it is a human decision. The honest rewrite keeps the ambition and stages it: most gates refuse, the fidelity judgement is recorded rather than enforced today, and the sentence about product truth is stated as what the audit is for rather than what is already guaranteed.
- iss-2608290856036953The ratchet that would make a fidelity verdict binding waits on a corpus of real verdicts, because there are none. A baseline ratchet is how this repository already converts an advisory signal into a red gate: today's failures are baselined, a new one fails, and a fixed one invites a shrink. Applied to the intent audit it would make a newly failed acceptance criterion fail a gate rather than sit in prose. It is deliberately split out of the intent that gives a failed verdict a tracked record, and sequenced behind it, because a ratchet baselines whatever number it finds and no intent has been audited even once: seeding it now would baseline a number nobody has looked at. It also needs the audit's position relative to the merge settled first, since a ratchet on a post-merge verdict fails the next unrelated change rather than the one that caused the failure, and it needs its blocking behaviour declared for both facilitator modes.
- iss-2608290944122400Efficiency pressure is the defeater this framework has no answer to, and it is the one that turns a voluntary verification ladder back into a rubber stamp. A practitioner framing of Elish's moral crumple zone names three conditions that hollow out a human in the loop: no transparency into what the automation did, no authority to change anything, and an organisation's drive for efficiency. Tested against this framework the first is partly answered and the second is answered well, since the product thinker sets the acceptance criteria, owns the register they are addressed in, chooses the verification rung, and configures the facilitator, which is real authority over the things that determine the outcome rather than a veto at the end. The third is unanswered. Climbing the verification ladder costs money, time, and subscriptions, and nothing in the design resists the pull towards the cheapest rung. For a solo builder the organisation exerting that pressure is the builder, which makes the pressure harder to notice rather than weaker. Worth deciding whether the framework should make the chosen rung visible in what it produces, so that shipping on the cheapest rung is a stated position rather than a silent default, and whether a project whose blast radius reaches strangers should have to say so out loud before the ladder can be lowered. Note also that the same framing arrives independently at the escalation ladder, calling it tiered routing where higher-stakes cases go to humans and lower-stakes ones to automation, which is convergent evidence for that design rather than a new idea.
- iss-2608290956522870Responsibility for delivered work has no home in the record, because the attribution trailer discloses who helped rather than who is answerable. The convention names an assisting tool, which is disclosure and deliberately not authorship, and nothing anywhere records the act that actually carries responsibility: a named person accepting a delivered promise as matching what they asked for. Adding a co-authorship trailer for the tool is the wrong repair and this repository already refuses it, since it asserts an authorship a tool cannot hold and inflates the contributor graph, and the largest project to deliberate the question chose the assisting form over the co-developed one for exactly that reason. The right shape is a separate acceptance trailer naming the human who accepted delivery, which only a person can sign, so an automated facilitator structurally cannot. It belongs on the intent rather than on a commit, because what is accepted is a delivered promise and not a diff, with a mirror on the merge commit if a commit-level trace is wanted. It should carry the verification rung alongside the name, because an acceptance is worth exactly as much as the checking behind it and an acceptance on the cheapest automatic check should not read identically to one that followed an outside audit.
- iss-2608291009106041abcd cannot colour a selection the host renders, which bounds where role colouring can work at all. Tested by embedding terminal colour codes in a host-rendered option preview: the host escaped them rather than interpreting them, so the reader saw the raw codes. This is the working stance stated plainly, that the harness owns the pixels and abcd owns the words, arriving as a measured constraint rather than a position. Two consequences follow. Role colouring is available only on surfaces abcd renders itself, which today means its own terminal output and later the product thinker's own surface, and on a host-rendered prompt the addressee marker has to carry the distinction through its words and its glyph alone. And a design that assumes colour is available everywhere would degrade silently on exactly the surface a product thinker is most likely to meet first.
- iss-2608291444328326The launch payload's `local_username` identity rule takes the username from the last segment of HOME and hard-fails every case-insensitive occurrence of it in the payload. On a machine whose account name is an ordinary word that is also product vocabulary (an account named with the same three-letter word as the `ahoy install` track-latest flag and the "-shim" install mode it names, which appears in commands/ahoy.md, commands/update.md, commands/launch.md and docs/reference/cli/commands.md), `TestPayloadTreeImplementationsResolveIdentically` and `TestRenderPayloadLeavesSourceTreeUnversioned` fail on a pristine main (9 hard-fail findings at e6efe28f), and with them `make preflight` and the pre-push hook, so the v0.6.8 release branch could not be pushed from that machine until HOME was pointed at a symlink alias of the real home directory for the push. CI, which runs under a different account name, passes.
- iss-2608291807454357GHSA-9wv7-88w3-f77m: filename-keyed scan skips let a hostile release payload ship a secret in an unscanned binary file. skipByName/skipByFragment in the launch payload scanner skip files before reading them, Skipped entries count as an accepted allow, and the zero-coverage sentinel stays quiet while anything else scans, so a secret placed in notes.png (no valid image data needed) is Included in the payload and passes every gate with zero findings. CWE-693.
- iss-2608291807455620GHSA-fpf2-pg82-72rj: abcd site build and site check follow symlinks in the output path, and the .abcd-site-build marker is name-only. inspectOutDir uses os.ReadDir/os.Stat (follows a symlinked leaf), purgeOutDir runs os.RemoveAll through the same path, and MkdirAll plus os.OpenRoot open a symlink's target as the containment root; no Lstat/EvalSymlinks guard exists, and an ancestor symlink is missed even by a leaf-only Lstat. A committed marker forges ours classification so a later --out purges the directory's other entries (with --out . that includes .git). CWE-59.
- iss-2608291807456485GHSA-fg9r-3f8g-89m6: the gitleaks adapter executes an attacker-controlled binary from a committed relative path. resolveBinary accepts a relative cfg.Path from the committed .abcd/config/gitleaks.json, validates it only with os.Stat (symlinks follow), resolves it against the working directory, and the runner executes it under a #nosec G204 waiver; the LookPath fallback also honours inherited PATH (CWE-426). Any SessionStart drain or history capture/drain in a hostile checkout runs the attacker's binary with the victim's privileges.
- iss-2608291814551110ultra-v0.6.8 A3: gitleaks toFindings in internal/adapter/gitleaks/gitleaks.go uses strings.Index(ln, needle) per line and never advances a cursor, so when gitleaks reports the same secret twice on one line both reports yield a Finding at the first occurrence; dedupFindings collapses them, sealLine masks one span, and the second occurrence survives verbatim. Retry logs and request+response echoes are exactly this shape. Fix: advance a cursor past each match so every occurrence on the line becomes its own Finding.
- iss-2608291814553362ultra-v0.6.8 A1: recordAttributionOptIn in internal/core/ahoy/attribution_hook.go returns silently when readConfig or writeConfig fails, so ahoy install --attribution writes the prepare-commit-msg hook to disk but attribution.hook: true never lands in config.json and the receipt still reports success. attributionOptedIn then returns false, no gap is raised, and every later plain install is a no-op for the hook — the silent degradation the opt-in exists to remove. Fix: append a change-note on each error path exactly as registerRepo does for its history-lock failure.
- iss-2608291814561674ultra-v0.6.8 C10: clearOutward in internal/core/site/layout.go allocates a fresh forbidden slice and sort.SliceStable's it on every ray, and settle calls it up to 1+2*settleRays times per bubble, twice per build via byLinks. The fixed-point loop jumps rho to the hi of any interval covering it until none does, and every jump only crosses points that interval covers, so it converges to the least uncovered point at or beyond the start whatever the interval order — the sort is not needed for correctness. Fix: drop the sort and reuse one scratch slice across rays; benchmark before and after.
- iss-2608291814562032ultra-v0.6.8 C4 (capture only): site-src/install.sh.tmpl unconditionally unsets the proxy and CA-bundle variables (HTTPS_PROXY, ALL_PROXY, CURL_CA_BUNDLE, SSL_CERT_FILE, SSL_CERT_DIR, CURL_HOME) before any fetch. The lockdown IS the GHSA-x4v8-rxvx-8v89 fix and hooks/bootstrap.sh mirrors it, so it is deliberate; the cost is that a host whose curl finds its CA bundle only through SSL_CERT_FILE (NixOS, minimal containers, custom OpenSSL) or a network reachable only through HTTPS_PROXY cannot install, and the generic could-not-download message does not say why. The review proposes an explicit escape such as ABCD_INSTALL_KEEP_ENV=1; the objection is that an environment-variable opt-out reopens the very vector the lockdown closes (the poisoned environment sets the escape too). Whether to trade the lockdown for those users is a product decision, not a code fix. The purely diagnostic part — naming the ignored variables in the failure message — does not weaken the lockdown.
- iss-2608291814563353ultra-v0.6.8 B2: checkAgentTrustContract in internal/core/lint/agentcontract.go returns early when reads_untrusted_input is absent, so the prompt_version check below it never runs — contradicting its own comment that prompt_version is required for EVERY prompt. checkAgentChangelog then skips the page as already reported, which is untrue on this path: a prompt with only name: in its frontmatter yields one finding instead of the declaration finding, the missing prompt_version finding and the changelog finding. Fix: record the declaration finding and fall through.
- iss-2608291814563403ultra-v0.6.8 C5: internal/core/memory/schema.go checks licence with lic == "" in validateSourceEntry (the sources[] shape) but strings.TrimSpace(lic) == "" in the single-source branch. The YAML reader trims unquoted scalars but keeps interior whitespace in quoted ones, so licence: " " passes on a sources[] entry and is refused on the single-source shape; hasLicence in lint.go already trims. Fix: one shared requireLicence next to requireClass/requireCitation/requireDate, used by both branches.
- iss-2608291814563789ultra-v0.6.8 C9: QueryPages in internal/core/memory/ask.go splits every page's frontmatter three times — pageInfoFrom, pageBody and pageSourceBlock each call splitFileFrontmatter (a full normaliseNewlines plus strings.Split of up to maxMemoryPageBytes), and two of them re-run parseFrontmatter on the same region. abcd memory ask does this over the whole store per question. Fix: split and parse once per page and thread (region, body) into the three consumers; measure before and after on a synthetic store.
- iss-2608291814565781ultra-v0.6.8 below-cap reuse-5: the memory frontmatter parser (frontmatterOpenIndex in internal/core/memory/yaml.go) trims lines with strings.TrimSpace, which does not strip U+FEFF, while the record-lint parser uses frontmatter.TrimBOM, so a BOM-led memory page is a page with frontmatter to record-lint and a page without it to memory. Pre-existing, not introduced by the reviewed slice.
- iss-2608291814565929ultra-v0.6.8 C8: safeMemoryDir in internal/core/memory/writer.go duplicates validatedMemoryDir's segment walk (same Lstat, same symlink/non-dir refusal, same UnsafeStorePathError); they differ only in the IsNotExist arm (create vs return absent). Because safeMemoryDir returns an empty path when the store is absent, bare.go and lint.go each carry an if !present { mem = Dir(root) } fallback with a comment explaining why. This is the GHSA-72rp-qxm2-r8vq guard, so two walkers means a hardening fix to one leaves the other open. Fix: one walker memoryDir(repoRoot, create) (string, bool, error) that always returns Dir(repoRoot); both wrappers become one-liners and the call-site fallbacks disappear.
- iss-2608291814566067ultra-v0.6.8 altitude 1: the store redactor (internal/core/memory/redact.go) is applied at the Ingest call site only. fileBack in internal/core/memory/ask.go builds PageWrites from the host-delegated distiller's page and hands them to WritePages with no redaction, so a secret or an absolute home path the distiller echoes into a page body lands in the committed .abcd/memory store unscanned — GHSA-j5f5-phgm-9m73 one door over. Fix: redact inside WritePages, the single write primitive, so no PageWrite reaches disk unscanned; Ingest's per-body loop then collapses into it.
- iss-2608291814568191ultra-v0.6.8 C2: the check job in .github/workflows/ci.yml checks out with the default shallow depth (no fetch-depth: 0, unlike the release-gate, record-lint and secret-scan jobs), so BASE_SHA is never a present object, git cat-file -e always fails, and the record-lint step always takes the unarmed fallback. The -agent-diff arm the comment says enforces agent_contract's unbumped-edit check is structurally unreachable, and the step reports green without saying it downgraded. Fix: fetch-depth: 0 on that checkout and a ::warning:: on the fallback so a silent downgrade is visible.
- iss-2608291814568971ultra-v0.6.8 C3: the literal HOME backstop in internal/core/memory/redact.go (and its twin in internal/core/history/history.go) is strings.ReplaceAll(text, home, "~") with no path-boundary anchor, so with HOME=/root a page body naming /rootfs/etc/hosts or 'the /root-cause' is silently rewritten to ~fs/etc/hosts and 'the ~-cause' before it is committed; any short home ([redacted-path] inside [redacted-path]/...) corrupts the same way. The strings.Contains(redacted, home) fail-closed check that follows ReplaceAll can never be true, so the 'home path survived redaction' refusal is dead code. Fix once in the shared home (C7): anchor the replacement on a path boundary and make the survivor check boundary-aware so it can actually fire.
- iss-2608291814569036ultra-v0.6.8 C7: memoryBlockingResidual and memoryCallerHome in internal/core/memory/redact.go are byte-for-byte copies of history.blockingResidual (internal/core/history/history.go) and history.callerHome (internal/core/history/store.go); scanner.ProbeIdentity carries the same home resolution inline. Two committed-store redactors that are meant to agree on what counts as a leak now have to be fixed twice (C3 is the concrete cost). Both packages already import internal/adapter/scanner, so one exported home there has no cycle risk. Neither copy has a unit test of its own (the below-cap conv-3 note); the shared home gets them.
- iss-2608291814572914ultra-v0.6.8 altitude 3: the memory store's symlink guard is a per-verb pre-check repeated at five entry points (Bare, QueryPages, Ingest, Lint, runMemoryCoverageLint) rather than a containment mechanism, and fileBack in ask.go reached Dir(root) and existingPageFrontmatter without it. The site package fixed the identical class (gh #487) by opening one os.Root and routing every read through fsutil.ReadGuardedInRoot. Deeper fix: memory holds a store-root handle the same way so containment is structural rather than remembered at each verb.
- iss-2608291814573570ultra-v0.6.8 below-cap eff-2/simp-1: the release job in .github/workflows/release.yml re-derives the content sha (go run ./cmd/record-lint --derive-content-sha) instead of consuming the verify job's output — a second compile plus a full-history walk per release, and a second derivation that can in principle diverge from the one the gate passed. Cleanup: emit the sha as a verify job output and consume it.
- iss-2608291814575169ultra-v0.6.8 altitude 4: lint-decisions in the Makefile adds a fourth bash gate (DA001-DA004) on top of the shell stopgap the Makefile itself calls temporary, and ci.yml carries the same base-ref-resolution shell three times (record-lint, issue-resolution, decisions-append) with a hand-copied zero-sha/absent-commit guard per step; preflight checks origin/main..HEAD while CI checks BASE_SHA..HEAD. Deeper fix: DA001-DA004 belong in internal/core/lint as a record-lint verb that derives the base ref once.
- iss-2608291814575788ultra-v0.6.8 altitude 2: the opt-in gitleaks augmentation is bolted onto history.Capture alone (internal/core/history/history.go), while the other write paths that build scanner.New — capture, memory ingest, launch dry-run, repolint, the CLI scan — never see it. Deeper fix: fold the gitleaks adapter into internal/adapter/scanner so scanner.New reads the opt-in, ScanText/ScanBundle return the union, and ErrConfiguredNotFound surfaces as the existing Unavailable state; every consumer then inherits it.
- iss-2608291814576261ultra-v0.6.8 altitude 6: the fail-safe policy for a broken repo guard layer (keep bundled hazards armed, drop overrides, exit 1 on allow) is decided in internal/surface/cli/guard.go by inspecting len(reg.Entries) after a guard.Load error, not in core; the plugin hook and any later MCP surface re-derive their own answer and can disagree (ahoy.GuardHealth already carries RepoOverridesDropped separately). guard.Load does return Defaults() with the error, so the dead-branch reading in the review is a stale-base artefact; the placement point stands. Deeper fix: a typed load result in internal/core/guard with the check verb's Decision carrying the drop notice as a warn-level outcome, so surfaces only format it.
- iss-2608291814578333ultra-v0.6.8 altitude 5: the .git first-segment exclusion in internal/core/positioning/config.go Surface.validate is a one-off guard layered on fsutil.ValidRelPath, which every other repo-relative path consumer (site manifest, lint config, record-lint) relies on without it — so another committed config naming a repo-relative file can still quote .git/config and leak a credential-bearing remote URL. Deeper fix: a shared fsutil predicate (denied root segments, case-folded) used by every validator, or enforcement in ReadGuardedInRoot for repo roots.
- iss-2608291817368607GitHub #486 sibling: abcd ideate record writes the verdict payload's idea text and the three legs' prose (claims, grill hits, kill attempts, rejected alternatives) to .abcd/development/research/<date>-ideate-<slug>.md through termsafe.CleanProse only — no pass through internal/adapter/scanner (internal/core/ideate/record.go validate, render.go). A secret or absolute home path in the host-produced JSON is committed verbatim, the same class capture (redactLedgerText) and intent (redactIntentText) close. Stance (fail-closed like intent, or redact-and-report like capture) is a design choice to settle before fixing.
- iss-2608291832160371GHSA-9wv7 residual, now narrowed to its second half. The container half is CLOSED: the byte branch decodes the formats the standard library gives it — zip, gzip, bzip2, zlib, tar, and PNG's compressed chunks (IDAT, zTXt, a compressed iTXt, iCCP) — keyed on MAGIC BYTES rather than the filename, and scans what comes out with the same byte rules, so a token in a gzip member, a zip entry or a DEFLATEd zTXt chunk is a finding where it used to ship invisible, and a zip renamed .png is labelled and decoded as a zip. Decoding draws on one budget per payload file: 4 MiB of inflated output (the byte-scan read cap, so a file costs at most twice what it costs today), 4 nesting levels, 1024 entries. A container that would exceed any of the three is refused rather than decoded — a decompressor with no output bound would be a denial of service. The formats abcd still cannot read — JPEG entropy streams, PDF FlateDecode, GIF LZW, WebP, the mp4/mov/webm/mp3 boxes and frames, xz, 7z, zstd, and any unrecognised magic — stay content_unverified exactly as before, and an archive holding one opaque entry stays unverified naming that entry; the report carries the decoded tier, the unverified tier, the reason per unverified path and the magic-keyed format separately, so "decoded and clean" is never folded into one green with "could not be read". xz, 7z and zstd have no standard-library decoder: decoding them needs a third-party dependency, which is a sign-off, not an omission. The decoded tier claims the bytes were READ, so each walk proves that rather than assuming it: a zip's catalogued entries must tile the archive and its directory records must tile the region up to its end record, which must close the file (a prepended local record, a gap anywhere, a trailer, or a declared directory size inflated to swallow one, all refuse it); an entry is read to the end of its catalogued extent, since a DEFLATE stream can stop short of it; a tar must end where its end-of-archive marker says; a compressed stream's trailer is covered like the stream; every entry is read from its physical extent, whatever its mode bits, typeflag or directory-shaped name claim, because an archive reader hands back an empty body for an entry that calls itself a directory however much data it carries; a nested region is scanned raw exactly as a top-level file is, since "the caller already scanned these bytes" holds only at the top; every span whose length or content the format lets the file choose — a zip's two entry names and two extra fields, its entry and archive comments, a gzip header's FEXTRA, filename and comment, a tar header's name, linkname, uname, gname and every PAX record and extended attribute it carries, plus the zero padding between an entry and its block boundary, and every PNG chunk the spec calls plaintext — is judged rather than taken on the spec's word, because a payload is whatever its length field says it is: a field carrying the signature of any known container refuses to promote the file, naming the field and the format, and the signature search is held to the format sniff by a totality test so a format the sniff names can never lack a signature. That rule is deliberately blunt rather than decoding what it finds, because the decoding version shipped a hole twice — a member that would not open was read as a member that was not there — and because decoding from every signature offset was quadratic in the field's length. Its price is noise where a signature is short ASCII: an ordinary source path inside an archive trips it (internal/ftype.go reads as mp4, docs/ID3-tags.md as mp3, RIFF.md as webp, cmd/ustar/ as tar), as does a chance zlib pair in a palette at roughly 1% for a 192-byte field, and a JPEG thumbnail in a camera-export PNG's eXIf chunk trips it honestly — all reported unverified naming the field; and a region counts as covered by the byte scan only when ALL of it reads as text rather than its first 8 KiB. Where a walk cannot account for a byte the file stays unverified with the reason — the bytes may be innocent, but nothing read them. Three residuals, stated rather than hidden: a member encoded so that no signature abcd knows appears anywhere in it can sit inside a field and be counted as read, which is the same residual the top-level branch has always had; a member buried inside a PNG's inflated pixel data or its ICC profile is scanned as bytes but not walked, because asking a region rule to vouch for either would refuse every real image; and the short NUL-terminated sub-fields inside a compressed PNG text chunk are stepped over.
- iss-2608291848181384ultra-v0.6.8 follow-up observation: redactLine in internal/adapter/scanner/redact.go rewrites an identity finding's placeholder with strings.ReplaceAll over the whole line, so a local_username finding the detector reported only where the username is word-bounded also rewrites every other substring occurrence on that line — under HOME=/root a line carrying a bare 'root' word also has '/rootfs/etc/hosts' rewritten to '/[redacted-user]fs/etc/hosts'. home_path_self now sweeps by its own anchor; the other identity kinds still rewrite by substring. Pre-existing; surfaced when the home-span suppression stopped hiding it. Fix: apply identity placeholders by the reported byte span (columns stay valid after sealLine) or at least by the detector's own word boundary.
- iss-2608291849371769Launch payload scanner pre-existing debt: (1) the text branch of ScanBundle reads a bundle file with an uncapped os.ReadFile while the skip-listed branch is capped at maxBinaryScanBytes, so a large text file has no memory bound; (2) .gitignore sits on defaultSkipFilenames and therefore takes the byte-rule branch though it is text, so its prose/identity coverage is weaker than any other text file; findings also accumulate uncapped across files.
- iss-2608291915432717ultra-v0.6.8 follow-up observation (security review of the branch): a third party's home path nested under a longer path — /Volumes/Backup/Users/alice/x, or any prefix before /Users or /home — is reported by no detector in internal/adapter/scanner/identity.go and is committed verbatim by memory and history. leadingBoundaryOK refuses the generic-home match when the byte before /Users is a path-segment byte, home_path_self correctly declines it, and local_username does not match a foreign name. The caller's OWN name in the same shape is still caught hard_fail by local_username, so this is the warn-class home_path_other gap only. The generic regex also covers two segments at most, so a home under a deeper root ([redacted-path]/alice) is only ever matched by its first two. Pre-existing on main, identical before and after the branch. Fix: let home_path_other evaluate a /Users|/home segment that follows a path byte, or widen the regex to a nested root.
- iss-2608291924452604PrimaryWorktreeRoot trusts rev-parse stdout: git rev-parse echoes an unrecognised option to stdout and exits 0, and --path-format only exists from git 2.31, so on an older git the --git-dir, --git-common-dir and --show-toplevel answers read as the flag text plus the path and every comparison silently fails closed to no primary store; validate each answer as a single absolute path or drop the flag
- iss-2608291941060605ultra-v0.6.8 follow-up (review of the branch): registerRepo in internal/core/ahoy/apply.go appends the raw lock error to the install receipt's change-notes ('history registration for <sha> skipped (' + lockErr.Error() + ')'), and that error carries the absolute lock path under the user's home (~/.abcd/history/...), so the receipt and --json output name the home directory and username — bypassing the receiptPath scrub that note() routes every written path through. The same shape recurs in recordAttributionOptIn's new notes (an os.PathError naming <repo>/.abcd/config.json). Fix: render every change-note that embeds an error through receiptPath, whose embedded-root pass covers sentences.
- iss-2608291941064448ultra-v0.6.8 follow-up (review of the branch): WritePages in internal/core/memory/writer.go redacts only PageWrite.Body. PageWrite.Frontmatter is rendered by renderWrites and written verbatim, and on ask --file-back it is host-supplied: source.citation.title, recall entries and any other frontmatter string a distiller echoes reach the committed .abcd/memory store unscanned (reproduced with a synthetic token and a home path in citation.title). Pre-existing on main — Ingest never redacted frontmatter either — but the door beside GHSA-j5f5-phgm-9m73 remains open one field over. Fix: redact every string leaf of the frontmatter mapping through the store redactor inside WritePages before dumpFrontmatter, with the same fail-closed gate as the body; IngestEvent.Origin reaching registry.md is the same class.
- iss-2608291941067275ultra-v0.6.8 C4, the diagnostic half: the installer's fetch failure in site-src/install.sh.tmpl said only 'check the network', so on a host that reaches GitHub through HTTPS_PROXY or finds its CA bundle through SSL_CERT_FILE — both deliberately unset by the GHSA-x4v8-rxvx-8v89 lockdown — the cause was misdiagnosed. The message now names the variables the installer ignores (both cases of the proxy names) and says how to install by hand; the lockdown itself and whether to offer an escape from it stay with iss-2608291814562032.
- iss-2608291957114882Status.OutDir and Result.OutDir carry an absolute path into abcd site --json and site build --json when --out is absolute; the iss-81 rule is that machine output never carries a developer-identity path and fsutil.RepoRel is the canonical primitive, unused here
- iss-2608292005445725ultra-v0.6.8 follow-up (confirmation pass): homeSweepable in internal/adapter/scanner/residual.go waives the leading half of the home anchor unconditionally inside a URL span (if inAnySpan(at, urls) { return !nameContinues(text, end) }), so with HOME=/root (Docker, CI-as-root) ordinary URLs are corrupted and false hard-fails raised: https://docs.example.com/root/index.html is committed as https://docs.example.com~/index.html, and git@github.com:acme/root/tool.git and https://pkg.go.dev/example.com/mod/root scan as home_path_self hard_fail. Proposed narrowing: waive the leading anchor only when the match begins at the first '/' after the URL authority (scheme://host[:port]), so a home that is the URL's path root is swept and one buried deeper in the path is judged by the ordinary anchor.
- iss-2608292005449546ultra-v0.6.8 follow-up (confirmation pass), corrected by the v0.6.9 combined-diff review: a home behind a URL host or under a longer root with a '.', '-' or '_' continuation — https://ci.example.com/Users/<user>.zip, /Users/<user>-old/x, /Volumes/T7/Users/<user>_snapshot/x — is committed VERBATIM by capture and intent, which have no store-side backstop, and passes through memory and history too: home_path_self declines on nameContinues (which treats '.' and '-' before a letter as a longer name), home_path_other declines at its leading boundary, local_username is URL-suppressed or fails its word boundary, and sweepUserSegment applies the same nameContinues, so the rewriting backstop does not cover these shapes either. This is a REGRESSION against main, which redacted all of them (verified by overlay), introduced by the trailing anchor in 27081ac1 and its follow-ups. Three predicates disagree on '_': nameContinues (boundary), isHomeSegmentByte (continues), isWordRune/wordBounded (continues), and the '_' shape falls through that seam. The branch's tests pin only the '/'-trailing shape behind a host. Fix: one canonical name-continuation predicate for the home-path anchor — alphanumeric only, so '.', '-' and '_' are boundaries; the alnum case (/Users/everett vs /Users/eve) is the only false positive the trailing anchor exists for. <!-- abcd-lint:allow -->
- iss-2608292034215745v0.6.9 combined-diff security review: a regression created by the MERGE of two branches, present on neither alone. fix/scanner's 95b98abc made the byte scan's rule table explicit: byteScanPolicy(local_username) is bytePolicyDrop, safe there because home_path_self was unanchored and always caught the operator's home in raw bytes. fix/ultra-findings' 27081ac1 anchored home_path_self so a home preceded by a path-segment byte is declined as a longer name. On the merged tree (3e1acc36 onto 44329c40) a raw blob — a PNG or PDF, where the home is typically preceded by an alnum byte with no separator — has home_path_self DECLINE the home at the leading anchor, local_username then dropped by policy, and launch ship publishes the operator's absolute home path. Demonstrated end-to-end: identical bytes as .md hard-fail (1 finding) and as .png pass (0 findings, no kinds); a mid-blob home in a .png likewise. Fix: on bytes, the leading anchor cannot hold (a raw blob has no path syntax to anchor on, and the long literal makes chance collision negligible), so scanBytes must keep home_path_self wherever the literal occurs, or stop dropping local_username inside a /Users|/home segment.
- iss-2608292036125100v0.6.9 security pass: the caller's own home nested under a longer root — /Volumes/T7<HOME>/x, /mnt/backup<HOME>_snapshot/x — is reported by nothing when HOME is not under /Users or /home (a temp or CI home such as /var/folders/.../<user> or /workspaces/<user>). home_path_self declines it at the leading anchor (the byte before the home is a path-segment byte), home_path_other's regex does not match such a root, local_username fails its word boundary inside the longer token, and the backstop's user-segment rewrite covers only /Users/<user> and /home/<user>. For a /Users or /home home the backstop rewrites the segment, so the shape is covered there. main's unanchored sweep took it everywhere. Fix: extend SurvivingCallerHome's user-segment rewrite to the caller's actual home root (basename plus its parent segment), or waive the leading anchor for the literal home when the byte before it is a path-segment byte and the home is at least two segments long.
- iss-2608292037564347v0.6.9 combined ruthless review: three sites carry the same path-boundary predicate in different polarities and now disagree on a trailing suffix. fsutil.isPathBoundary (internal/fsutil/paths.go) and scanner.isPathSegmentByte (internal/adapter/scanner/identity.go) are the same byte class inverted, and scanner.nameContinues (internal/adapter/scanner/residual.go) is the home-path anchor's rule — alphanumeric only. So fsutil.RedactRoot / RedactHome leave 'cannot access /Users/<user>.' untouched (the '.' is a segment byte to them) while SweepCallerHome sweeps it, and the CLI error scrub and the install receipt disagree with the store redactors about the same sentence. Proposal: one home for the predicate — fsutil exports the boundary rule, scanner imports it, and the alnum-only trailing rule is the shared definition — taken in its own pass because fsutil's callers (error scrub, receipts, RedactRoot) are a different set from the scanner's.
- iss-2608292038186663v0.6.9 combined ruthless review: nine wrappers around 'git rev-parse --show-toplevel' exist and only one validates the answer. internal/core/site/outdir.go checkoutRoot holds the output to a single absolute line that contains the invoking directory; the other eight — internal/surface/cli/cli.go, internal/surface/cli/banlist.go, internal/core/capture/roots.go, internal/core/ahoy/remote.go, internal/core/banlist/worktree.go, cmd/record-lint and cmd/scaffold-sync, plus the site one — each re-derive the call. Proposal: one gitutil.Toplevel(dir) carrying the single-absolute-line-containing-the-invoking-directory rule, with every wrapper calling it. This REFINES iss-2608291924452604 (the ledger has no typed link, so the relation is stated here and in related_issues).
- iss-2608292246210181TestGallopingProbeCostIsLinearInLineLength in internal/adapter/scanner is a wall-clock scaling test (quadruple the line, require under 8x) that sits in release.yml's verify job, so a loaded shared runner can refuse a tag on timing alone: the v0.6.9 auto-release measured 8.4x (2.16s to 18.1s) after the same tree passed the merge-queue check leg, while the release machine measures 4.0x across three runs; the tag was already minted, so the refusal consumed nothing but needed a manual rerun. The scaling property should be asserted on operation counts or a deterministic probe budget rather than elapsed time, or the test excluded from the verify lane.
- iss-2608300002540238Lapse: anticipation. Those populating this cycle's record know what the readings will look for, and the instrument is specified alongside the record it will read. The manifest mitigates by showing what a reading actually saw; the mitigation is partial. Made once at the outset, per the protocol, rather than reconstructed later. Timestamp: 2026-08-28.
- iss-2608300002544153Lapse: commitments made outside the tooling. The workstream's rulings (the construal-admissibility extension, the detection and disposition record design, the closing-run schedule and interpretations, the supply-regime check, the invocation constraint, the lapse-log field, and the three elicitation rulings) were committed in design discussion before the refusing commands existed. Disclosed here once; the decision-log entry carries the rulings themselves. Timestamp: 2026-08-28.
- iss-2608300002547145Lapse: the pre-tooling window. The workstream's earliest ledger entries (the ledger-design construal, the mechanism/content distinction, the extend-not-duplicate decision, the adopted rulings, and this entry itself) are hand-authored before the surfaces existed to write them through commands - the format precedes its enforcement. Point in the process: preparation, before the first schema commit. Timestamp: 2026-08-28 (at the lapse, not at write-up).
- iss-2608300002557321Lapse: autonomy acted on an inferred go-ahead. Session 1's orchestrator read the facilitator's status update that the product thinker would provide the construal as a go-ahead - the inference rested on a misread word in the update - and ran Phase 1 filing (five local commits, nothing pushed) before the construal existed. It was stopped on challenge and the branch deleted. Remedy, procedural: an autonomous run starts only on an explicit go, never on an inference from a status update. Timestamp: 2026-08-29 (at the lapse; written up 2026-08-30 at the restart).
- iss-2608300002557676Disclosure: recording cost per conjecture is partly an artefact of how design work items were grouped into filings (the assembler and its manifest share one intent and therefore one mechanism claim, one scope-condition set, one recorded ground; the two evals were split into their own intents for exactly this reason). Any per-conjecture cost reporting must carry this caveat from the ledger, not discover it at write-up. Timestamp: 2026-08-28.
- iss-2608300108376943A bundle of intents cannot share one spec through the ceremony: a spec's intent back-link is a single itd-N, intent link refuses a spec that names a different intent, and spec close refuses a disagreeing link, so the bundle-member kind (itd-114 vocabulary) has no shared-spec path. Ruling (13) of the cold-reading workstream binds the instrument trio (itd-183, itd-184, itd-185) as one bundle with a shared spec; the planning session stamps bundle-member and plans three specs written as one cross-linked design instead, logged as an improvisation. Either the spec back-link becomes a list, or the bundle kind's contract states that members carry sibling specs.
- iss-2608300114352100The session-1 lapse record explains the misread go-ahead as a homonym and thereby discloses a participant's first name; the filing's own 2026-08-29 decision line rules that roles, never names, appear in any record or commit. Found by the Phase 1 adversarial review; the text also reached the pushed filing branch, so the branch history carries it until the PR is squash-merged or the branch rewritten.
- iss-2608300114357633The decision log's last word on two questions is the opposite of what the filing branch does: it defers the brief-lifeboat mapping row to itd-143's build while the branch adds the row, and it records the roadmap phase home as deferred while the branch authors Phase 7 on a facilitator ruling that the log never records. Append-only, so the remedy is appended lines carrying both rulings.
- iss-2608300114359543Record consistency findings from the Phase 1 adversarial review: itd-142 and itd-143 attribute the 2026-08-28 rulings to a third role name; itd-143 still describes the not-yet-real marker as pending in a form the same filing ratifies differently; 06-framing.md places a dated preface between the Construal heading and the token, so the section is not statement-first as its own rule and itd-143's projection criterion require; invariant 15 carries an adoption-date marker no sibling carries; 04-scope.md line 24 still counts seven phase docs; Phase 7 and the log say 'Phase 2 planning' where roadmap Phase 2 is a shipped phase; the phases README says phases 1-6 are organised by capability moment; the lifeboat mapping comment counts 23 rows.
- 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-2608300143316805The scribe protocol, the definition's Delivery section, and the changelog entry claim record_schema judges a scribe-emitted reading or disposition record the moment it is committed and that the validation path exists today; on this base no reading or disposition schema or store exists (spc-58 is open), so record_schema refuses the directory as an undeclared bucket and a malformed record is indistinguishable from a well-formed one. The dependency on spc-58 must be stated in all three places.
- iss-2608300143317262The scribe's guard test can be satisfied by a definition that names shipped-tree material: the allow-list root constant is .abcd/work/ (broader than the .abcd/work/issues/ the definition, brief and changelog state); only the first Inputs-prefixed heading is scanned; only single-backtick tokens containing an ASCII slash are read as paths (a bare path, a fenced block, or a fullwidth solidus is invisible); and the prefix check performs no cleaning, so a dot-dot traversal under the prefix passes. The canary also omits two refusals the definition claims (transcript-store or .work.local material handed as ledger context; an embedded ask for a summary) and its must_not_contain token appears nowhere in the input.
- iss-2608300205044566The committed-ledger gate and the ledger reader disagree on single-quoted scalars: issueScalar in the record-lint issue-shape check strips single quotes, capture's decodeScalar does not, so a hand-authored single-quoted value (severity: 'minor', lapsed_at: '2026-08-28T00:00:00Z') is lint-green while the reader refuses and skips the record invisibly. Pre-existing on unmodified code; every issue-shape check that reads a scalar inherits it, so the fix belongs in issueScalar and moves four checks at once.
- 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-2608300210588414intent ready reports a scope_conditions failure with a backfill remedy on shipped and superseded intents (18 shipped records), which spc-55's Out of scope forbids; and an untouched Mechanism scaffold line is reported as a stated mechanism claim, contradicting the plugin surface's line that the scaffold is not a claim. Detail strings on checks whose verdicts are already settled by the bucket check, so misleading output rather than a wrong gate.
- iss-2608300210588874A planned intent whose scope-condition bullet carries no identity marker is permanently NOT READY: the scope_conditions remedy names abcd intent plan, which exits 2 on a planned record, and the plugin surface forbids hand-typing markers. This is the default path (the scaffold leaves prose, plan stamps nothing, the maintainer writes the bullet after planning) and lands on every corpus record the moment a real condition replaces the nullity token. spc-55 states that Plan is idempotent and a re-run stamps only the unmarked bullets; the code refuses the re-run instead.
- iss-2608300212513349itd-182 review residue: the record-lint issue-shape check reads a quoted whitespace-only lapsed_at as a present malformed value while capture's reader trims it to absent, so the two gates disagree on a hand-authored non-lapse record and lint's message states a reader refusal that does not happen (trim after issueScalar and pin the padded case); the capture-verb prose flag list on the issues README omits --lapsed-at; the five stamped lapse records assert T00:00:00Z where their bodies state only a day and no record page states the date-only-floored-to-midnight-UTC convention.
- 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-2608300224316569A list-valued lapsed_at ([]) on a non-lapse record is lint-green because the record-shape check tests absence with isAbsentValue, which treats an empty inline list as absent, while capture's reader refuses it as not a string and skips the record silently. Same pre-existing class as found_at; the lapsed_at check should test nullness with the frontmatter null set only and let a list-shaped value fall through to the RFC 3339 finding.
- iss-2608300227224016record_schema's nested-store-root exemption is derived from every value in the record_stores config map, including keys naming no store the scanner knows, so a committed config line such as an unknown prefix pointing at .abcd/work/issues/anything hides that directory from the undeclared-bucket blocker without anything scanning it; the file's own comment says a config that could add a bucket could also hide one and that the list is code, not config. Build the nested set from the code-side recordStores looked up in the config, and refuse unknown record_stores keys at parse.
- iss-2608300227226804itd-180 review residue: capture.standingDispositions and lint.standingDisposition read the standing disposition with different parsers (strict with a continue before the supersedes edge is read; lenient reading the edge always) and no test holds them to one answer, so a malformed sibling disposition makes the board and the verb disagree; at ingest, manifest and regime are written verbatim without redaction or an enum check (harmless until a door lands); promote accepts a rejected or declined reading item; a mid-batch I/O failure leaves earlier items written with no result list; the lint import grouping in lint.go differs from goimports order; IssueStatus carries a disposition state outside the State enum for reading items.
- iss-2608300227228575IngestReading's on-disk collision probe checks only the current run's directory, so two runs ingested within one UTC second can mint one rdi-N in two run directories (the adr-45 mint is a second plus four digits, and nothing sequences ingests); afterwards that item can be neither dispositioned nor promoted, findReadingItem reports it present in more than one run, and no tree gate refuses it. The probe must be ledger-wide across every readings/rdg-*/ and redraw on a hit, and the findReadingItem comment claiming two runs can never mint one id is false.
- iss-2608300229100392itd-183 review residue: a projected field takes site.Section.Body, which ends at the next heading of any level, so a ### under a projected ## is dropped silently while the redactor uses the level-aware rule; the intent projection names Scope Conditions and Mechanism, headings no shipped record carries, so the charter's five-fields claim is not what the run does (three fields travel today); the two artefact writes are sequential os.WriteFile calls, non-atomic and overwrite-in-place; git status collapses an untracked directory so admitted files inside it are not refused; a preamble before --- lets origin through on whole-file rows (record_schema refuses such records); storeNodeType carries adr/iss entries no row uses; the --dry-run help overclaims when --out is inside the repository.
- iss-2608300229101513The exclusion floor's key and heading redaction is first-occurrence and exact-match: a duplicated origin key keeps its second copy, a frontmatter closed with four dashes is cut by StripFrontmatter but not read by Fields so the key survives in the body, and a heading spelled in another case is not redacted; the manifest still asserts the key and heading as refused. record_schema refuses the first two shapes in this repository, the third it does not. Make the key/heading half fail-closed like the path half: refuse the file on a duplicate excluded key, on an excluded key still at column 0 inside the first --- region, and on any heading matching an excluded title case-insensitively.
- iss-2608300229102495The dirty-tree gate discards a rename or copy's source path and mis-parses a worktree rename, so an included file renamed out of the include set is neither in the bundle nor refused and the manifest names HEAD for a bundle that does not equal HEAD; and the unconfigured-scan refusal checks only that a store key exists, so a store whose directory is absent (or an uncommitted retarget of .abcd/record-lint.json, which sits under the deny and is never in the dirty check) enumerates nothing and reports a clean assembly. Keep rename/copy sources in the dirty set for both status columns; stat every store directory the table depends on; add the lint config path to the dirty check.
- iss-2608300229107715The assembler's own prior outputs re-enter as input: a prior run's bundle.json and manifest.json committed anywhere a root row's .json match reaches (the plugin page's own --out ./run-dir example, resolved against the repo root) are admitted whole as config items, so ruling (18) is breached and the prior manifest's repository paths enter the bundle text while that run's manifest still asserts the exclusion. The artefacts self-identify by _type; refuse any admitted .json whose top-level _type is either tag and refuse an --out that resolves to a path any row admits; extend the own-output test beyond .abcd/development/readings/.
- iss-2608300229450257The scribe guard's trailing-punctuation trim runs before the traversal and prefix checks and strips a full stop, so a path whose final segment is .. with no trailing slash (.abcd/work/issues/.., bare, in inline code, or entity-encoded) loses its traversal segment, passes both checks, and admits .abcd/work/ (DECISIONS.md, CONTEXT.md, reviews/, rulesets/) — exactly the case the root constant was narrowed for. Bounded to one level up; ../.. and ../ forms are still refused. Run the traversal check on the raw token before trimming, or refuse to trim a trailing full stop when the remainder would end in /. or /..
- 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-2608300234598982Two pre-existing gate-versus-reader divergences reproduced on main, not introduced by the lapsed_at work: the record-lint issueScalar strips quotes with strings.Trim and never unescapes, so a double-quoted value carrying a backslash escape is lint-red while the reader decodes it (severity: "min\or" reproduces it); and a key line led by a Unicode space is ignored by frontmatter keyRe but read by capture after TrimSpace, so a Unicode-space-led bogus key is lint-green while the reader refuses and skips the record. The first shares its root with iss-2608300205044566 and should fold into it; the second applies to every key.
- iss-2608300234599781A lapsed_at carrying a nested map (an empty same-line value followed by an indented block) is read as absent by the committed-ledger gate because the lenient scanner yields an empty value and the null test passes, while capture's reader builds a map and refuses the record as not a string; on a non-lapse category the gate is green and the record is skipped invisibly. Sibling of the closed list case: when the same-line value is empty, look ahead for an indented continuation (blockSequenceAt already exists for the shape) and treat it as present and malformed.
- iss-2608300235377731A scope-condition identity marker is recognised only when it closes the bullet's first physical line, so an ordinary editor reflow of an 80-column bullet (or prose appended after the marker) moves the marker onto a continuation line, the gate reports the condition unmarked, the named remedy mints a new id, and the old id is folded into the condition text — orphaning any disposition keyed on it. This violates the identity-survives-edits criterion and never-renumbered. Match a well-formed marker anywhere in the bullet including folded continuation lines, strip it from the text, fault on two markers in one bullet, and stamp only marker-free bullets.
- iss-2608300235386715itd-177 review residue: spc-55 names tests in lifecycle_test.go that do not exist (the equivalents live in claims_test.go under other names) and claims the gate reports a deletion as a marker known to the record's history, which no code holds; the stamp-only --json emits an empty spec object while the intent carries a spec_id; the two fix commits moved their issue records to resolved without a Resolves trailer (legal, but the trailer is the convention when the fixing change is the resolving one).
- iss-2608300235388164The claim parser and stamper are fence-blind and comment-blind: a Scope Conditions heading inside a fenced code block shadows the real section (first match wins) so intent plan writes a marker into the fence and intent ready reports READY on the example while the real conditions go unchecked; a fenced example bullet under the real heading is stamped and counted; a commented-out block is read as live and the stamp's closing sequence ends the outer comment early; a hand-typed marker of the wrong shape is silent prose, gets a real marker glued beside it, and the bogus comment leaks into the JSON text; a second Scope Conditions heading is ignored without report; stampPlanned is a read-modify-write with no lock. Track fence state in sectionLineRange, refuse to stamp a section containing a fence or a duplicate heading, fault a malformed marker by name with a delete-it remedy.
- iss-2608300240410495The scribe guard's code-point loop refuses format code points and every non-ASCII code point but not ASCII control characters, so a carriage return, vertical tab, form feed, NUL, escape or DEL splits a path match the way a format code point would; a trailing traversal on the far side of the control character stands alone, produces no finding, and a viewer that renders the control invisibly shows .abcd/work/issues/.. as allowed material. Refuse unicode.IsControl outside LF and TAB with its own class marker; the test should also assert the canary exemplar omits the control shape.
- iss-2608300244483405Two pre-existing gate-versus-reader divergences reproduced on main with found_at, affecting every key and not covered by the single-quote or escape captures: a key whose only continuation is an indented comment line is refused by the reader (nested line is not key: value) while the gate is green; and an indented line following a valued key (or a null one) is refused by the reader (unexpected indented line) while the record-lint gate has no check for stray indented lines anywhere.
- iss-2608300244489638The block-spelled lapsed_at value read by the new blocks map is fed to the RFC 3339 validator, so a single indented continuation line that spells a valid instant is lint-green while capture's reader builds a map and refuses the record as not a string — the exact gap the block-reader commit set out to close, and its own comment says what the block says is not parsed. A block-spelled scalar is never a string to the reader, so its presence is the finding regardless of content: emit the not-an-instant finding unconditionally when the value came from the block.
- iss-2608300250295617The scribe guard's spaced-separator fold is a join, not only a fold: horizontal whitespace after an allowed root's trailing slash glues the next token onto it, so a shipped-tree path written in plain prose after .abcd/work/issues/ (space or TAB, bare or in one code span) becomes a segment under the allowed root and passes the prefix check; demonstrated against the real test. Scan both the folded and the decoded-but-uncollapsed views and union the findings.
- iss-2608300257421526itd-180 second-round residue: spc-58 still says promote refuses a reading item only when the disposition directory is absent while the build refuses any standing state but accepted; lint.StandingDispositions is exported with no production caller (a single reader in the issueschema leaf would retire it); the three reading stores declare no required fields so the committed-tree gate never judges a reading or disposition's content, contrary to the reading package's header claim that the reader refuses what the writer refuses.
- iss-2608300257424138IngestReading redacts every free-text field inside the ledger lock, constructing a fresh scanner per field (each shells out to git config), so a 100-item batch holds the lock about 8 seconds against a 5-second lockTimeout and any concurrent capture, disposition or promote fails with allocator contention; the issue-capture path redacts before taking the lock. Also, promoteReadingItem reads the standing disposition state outside the lock and re-checks only promoted_to inside it, so a disposition landing between preflight and stamp leaves a standing rejected beside a promoted_to; and the readings tree is read through symlinks on the disposition and promote paths (only ingest calls ensureFamilyDir), so a symlinked readings root lets promote write its stamp through the link to a file outside the ledger.
- iss-2608300257429193The two standing-disposition readers still diverge: lint's frontmatterFields tolerates a preamble before the opening --- and reads the supersedes edge, while capture's parser requires --- on line 0, errors, and leaves both dispositions standing, so a comment-led or blank-line-led disposition file makes the board say answered and the verb say two standing (promote refuses). Refuse a preamble-led file in dispositionsOf as the duplicate-key branch does, or converge both packages on one reader in the issueschema leaf; extend the parity table with both shapes.
- iss-2608300258510460The own-artefact refusal is extension- and parse-shaped: it keys on a .json extension and a successful top-level unmarshal, so a prior manifest or bundle committed as .yaml or .toml, or as .json with a BOM, wrapped in another object, wrapped in an array, or carrying a duplicate _type key, is admitted whole while the new manifest asserts the exclusion. Make the check content-signed: refuse any admitted file whose bytes contain either artefact _type tag string before any parse, regardless of extension, keeping the parse as a secondary check.
- iss-2608300258512411itd-183 second-round residue: --out and store checks compare lexically so a symlink into an admitted root passes refuseSelfAdmittingOutDir and a symlinked store directory passes os.Stat then enumerates nothing (Lstat and EvalSymlinks); the two artefact writes are each atomic but not jointly so, and a failed manifest write leaves a bundle that then makes the directory refuse forever; a walk row whose source directory is absent enumerates nothing silently (a brief chapter or glossary), while an empty bucket is legitimately absent and must stay a disclosed residue; the charter and projection comment say three fields travel today but two drafts already carry Scope Conditions and Mechanism so the entailment position projects five; a relative --out resolves against the repo root not the working directory and the render echoes the operator's string; the floor prose does not state that the heading signal is scoped to markdown files.
- iss-2608300258519825The exclusion floor's heading half matches the title the section scanner reports and neither the redactor nor the verifier normalises an ATX closing sequence or recognises a setext heading, so an excluded section travels under '## Audit Notes ##', '## Open Questions #' or an underlined heading while the manifest asserts it refused; the key half misses a quoted key ("origin":) and a block scalar with an internal blank line; and the verifier is not fence-aware while the redactor is, so a fenced example of the record template in any admitted markdown refuses every assembly. Normalise closing hashes and detect setext in both places, accept a quoted key, skip blank lines inside a block, and verify over the same fence-aware section scan the redactor uses.
- iss-2608300259316871The claim parser and stamper are blind to a multi-line HTML comment, so a commented-out bullet under Scope Conditions is counted as a live condition, the stamp writes a marker inside the comment, the marker's closing sequence terminates the outer comment early, a stray closing sequence renders as prose, the parked condition carries a live identity, and ready reports READY — a rewrite that corrupts rendered content. The resolution of iss-2608300235388164 does not cover the comment clause its body names. Extend the mask to a comment span (an unclosed opener masks until the line carrying the closer), let the gate name it and the stamp refuse it exactly as for a fence.
- iss-2608300259321329itd-177 second-round residue: the structural faults (duplicated heading, fenced section) are checked only after the claim-state switch, so a nullity or empty first section hides a second Scope Conditions heading carrying real bullets and the gate passes while the stamp refuses; the malformed-marker guard is case-sensitive so a capitalised near-miss gets a real marker glued beside it; no size check after stamping, so a record near the read cap can be written larger than its own reader accepts and the next Load refuses the whole corpus; a marker inside an inline code span is accepted and excised; the plugin page says every fault is refused by the stamp where two-marker and duplicated-id bullets are skipped rather than refused.
- iss-2608300318192814The post-stamp byte-cap guard sits in stampScopeConditions, before two further growth steps on the draft face of Plan (kind and spec_id rewrites), so a draft within a few bytes of the read cap is written past it and every intent verb then refuses the whole corpus until the file is hand-trimmed; the planned face holds the cap. Cap the final bytes at every intent write through one helper covering the kind, spec_id, stamp and Link writes. Also informational: the stamp write error wraps a PathError that re-introduces the absolute temp path into stderr (a pre-existing pattern), and a degenerate comment or an inline-code opener above the section masks the real heading so the gate reports no section rather than naming the unclosed comment.
- iss-2608300320001985The nested-store-root exemption still blinds record_schema through a known prefix: a committed record_stores line pointing rdi (or dsp, or itd) at another store's declared bucket — .abcd/work/issues/open, or a readings run directory — passes validateRecordStores, marks that bucket a nested root so the parent store skips it, and the misdirected store ignores every file not matching its own filename grammar, so a malformed issue record with five missing required fields yields zero findings; reopens the class iss-2608300227224016 records as closed, whose resolution text is not true as written. Refuse a configured store root that equals or sits inside a declared bucket of any other store, refuse two prefixes resolving to one path, and grant the exemption only when the child is not a bucket the parent declares.
- iss-2608300320011217The symlink refusal on the reading trees covers directories but not disposition files: readDispositions keeps a symlinked dsp-N.md, the standing computation, promote's state read and the board's exit-condition line then read a file outside the ledger, and the verb accepts a supersedes citation of the link; and a disposition whose supersedes_disposition names itself, or a two-record cycle, retires every standing answer so the item reads as undispositioned, the verb accepts an uncited fresh answer, and the board reports nothing. Lstat and IsRegular in all three readers; treat self-supersession as not well-formed and a non-empty record set with no standing answer as a ledger fault.
- iss-2608300320162381An ATX heading preceded by one to three spaces is a heading to every CommonMark renderer but not to the section scan's heading pattern, so both the redactor and the verifier are blind to it and an excluded section travels while the manifest asserts it was refused — the same class as the closing-sequence and case-variant findings closed in the two prior rounds. Widen the section scan to the CommonMark indent, or add a raw-line refusal in the verifier for a non-fenced line matching the indented pattern whose normalised title matches an excluded heading; add both probe shapes to the spelling test.
- iss-2608300320167335itd-183 third-round residue: headings that render identically to an excluded title but differ in bytes (bold, code span, an NBSP inside) travel — compare slugs in the verifier and refuse; a relative --out the operator typed is absolutised against the working directory and echoed unscrubbed on the success surface and in --json out_dir, which the plugin page tells the host to report — echo the operator's string or route through the root redaction; a frontmatter block whose keys are all indented one space is valid YAML that both the field reader and the excluded-key pattern miss so origin travels — refuse; the parse fallback comment overclaims (an escaped tag in a yaml or toml file or a JSON array is admitted; hand-rewritten, so ruling 18 holds).
- iss-2608300320418618opensComment reads a comment opener inside an inline code span as a real opener and the span runs to EOF through every later heading, so a draft whose prose quotes the opener idiom in backticks loses its Scope Conditions and Acceptance Criteria sections: ready reports no section, plan refuses on the AC discipline with a message naming the wrong fault, and the audit body hash would cover an empty AC section. Consult codeSpanRanges in opensComment and skip an opener inside a span; keep the to-EOF rule for a genuinely unclosed opener. Also cosmetic: the stamp trims a two-space hard line break from the bullet's first line.
- iss-2608300326346554The standing-disposition parity test cannot distinguish the converged reader from a divergent one on the three retires-nothing rows it was added for: when two records stand the expected id is empty, so both the outstanding and held consequences are false and a lint walk that stands only the newest record also reports neither — a mutation to newest-standing-wins passed all six rows. Assert lint's observable against the full standing set: an open hold exactly when the single standing record is a hold, none otherwise. Also, promote reads the standing disposition through a symlinked dispositions root (only the item leaf is Lstat-refused on that path), and lint's read-only walk follows or silently skips symlinks where capture refuses.
- iss-2608300335037531The charter, manifest.go and the brief surfaces index describe the manifest as timestamp-free and identical across two assemblies of one repository state, but it carries run_id, a minted timestamp plus entropy, so two dry-run assemblies of one HEAD produce different manifest hashes; state what holds — items and exclusions identical, the bundle byte-identical, the manifest differing only in run_id. Also the AssembleResult.OutDir comment claims a verbatim echo of an operator-supplied path while the front door now absolutises every relative --out against the working directory.
- iss-2608300335369473itd-177 fourth-round residue, all Low: the write cap is applied per write but the final size is known before the first, so a draft within one byte of the cap passes the kind write, is moved to planned, then has its spec_id write refused, leaving a half-planned record neither Plan nor Link repairs (compute the largest intermediate before any write); opensComment resolves code spans before comment openers, so a backtick inside a live comment re-pairs the rest of the line and the mask diverges from CommonMark in both directions (one left-to-right cursor where the first construct wins); the three audit-block upserts and the create-path seed write still call WriteFileAtomic directly and are uncapped, so the helper's one-way claim overstates (pre-existing on the base branch).
- iss-2608300349300138The render-equivalence comparison added for column-0 headings does not reach the indented-ATX and setext refusal loops, which compare by case-fold only, so an indented or underlined heading spelled with bold, a code span, emphasis or a non-breaking space travels while the manifest asserts it was refused — the class the last two commits claim to close, closed on one of three paths. Use the same equality (fold or same rendering) in both loops and add the eight probe spellings to the equivalence test.
- iss-2608300349309723itd-183 fourth-round residue, all Low: sameRendering models only emphasis and code marks, so a heading carrying an HTML comment or tag, an entity, a link wrapper, a homoglyph, or nested in a blockquote or list item renders as the excluded title but slugs differently (strip tags and comments, decode common entities, unwrap links before slugging, or refuse on a slug substring match and correct the comment); top-level YAML spellings of an excluded key that the line pattern misses travel (explicit key, top-level or nested flow mapping, a double-quoted key with an escape); the two --out refusals interpolate the resolved absolute directory built from the operator's relative string, which scrubPaths cannot redact when cwd is not a prefix; status.go reads run-directory names under the assembler's own scratch, worth a charter sentence so it is not mistaken for an invariant-14 breach.
- iss-2608300349493306itd-180 fourth-round residue, all Low: a symlinked item directory or disposition file is reported as outstanding rather than unsafe; a sole standing record that is not well-formed has an empty state and matches no case so the item vanishes from the board; every disposition and reading file read is Lstat then ReadFile rather than fsutil.ReadGuarded, leaving a stat-then-read window a racing local writer could use to swap a symlink under the read that licenses a stamp; pre-existing and not this branch's: record_schema skips a status bucket that is itself a symlink without a finding.
- iss-2608300349499636Two independent standing dispositions on one item — the ordinary result of two branches each answering the item and merging without conflict — make the outstanding report take the first by id and say nothing: an accepted record first hides a held record and its exit condition, and no line says two answers stand, contradicting the rule's own contract that silence is the one answer it must never give by accident; the parity test builds its expectation from the first id so it cannot notice. Emit a contested fault naming every standing id when more than one stands.
- iss-2608300352403199checkDraftFaceSize's probe minter uses constant entropy, so on a draft with two or more unmarked scope-condition bullets the second mint exhausts its redraws with a collision error that the check swallows as though it were a structural refusal, and the pre-write size judgement is silently skipped for the common case; Plan then stamps, writes kind, moves to planned, mints a spec and refuses the spec_id write, leaving the half-planned record and dangling spec the resolution of iss-2608300335369473 claims can no longer happen. Give the probe an advancing entropy source keeping every id sixteen digits wide, narrow or remove the error swallow, and extend the pre-write test to two conditions. Also re-run the check with the real spec id immediately after spec.Create and before the first write, since NextID is predicted outside the mint lock and a width crossing costs the same half-planned state; correct the comment and the resolution text.
- iss-2608300402591658renderedText decodes entities by iterating a Go map, so the decoding order is random and the refusal verdict for a heading such as Audit&nbsp;Notes is nondeterministic (200 calls: refused 77, admitted 123) — a determinism instrument with a coin-flip refusal; and a numeric or hex character reference inside an excluded title is outside the short list, slugs differently, and travels, while the comment claims an entity outside the list is a refusal not a leak. Replace the hand list with html.UnescapeString before slugging, which closes both, and correct the comment.
- iss-2608300402598718itd-183 fifth-round residue, all Low: a heading nested in a blockquote or list item and a homoglyph or format-character title leak, and neither residue is disclosed in the charter or the code although the fourth-round record named them; the raw-HTML refusal's comment says the site's markdown subset admits h1-h6 when the site refuses raw HTML blocks, and the per-line pattern misses an unclosed, multi-line, self-closing or attribute-carrying heading and a div with a heading role; a tagged key, an anchored key and a block-scalar explicit key are spellings the escape-is-the-signal rationale covers but the pattern set does not; the setext scan runs over frontmatter lines so a block scalar ending in the excluded title before the closing --- is refused with the wrong diagnosis.
- iss-2608300829308000itd-183 fifth-round ruthless nits: outDirLabel is empty for the default run directory so a populated default directory would be refused with a blank name (reachable only on a run-id collision); flowKeyRe is unanchored and refuses an excluded key name inside a quoted scalar, and htmlTagRe strips an autolink so a heading followed by one refuses — both fail closed but the corpus's long quoted reason strings in flow mappings are one sentence away from the first; the 'an amp entity' case in the assembler test is assembled and then skipped before its assertion, a probe that tests nothing.
- iss-2608300834193745itd-180 fifth-round nits: the two readers of one record family use different byte caps (lint's citation page limit of 8 MiB, capture's record read limit of 1 MiB), so an oversized disposition stands on the board and is refused by the verb — loud, not silent; the Unsafe finding text describes a directory but is now also emitted for a symlinked record file; the parity test's leading comment still says the expectation is built from the first standing id, which the contested change removed.
- iss-2608300835066901itd-180 fifth-round security findings: the reading walk admits a symlinked rdi-N.md as a real item so the board reports it outstanding and its remedy verb refuses (route a non-regular item file to Unsafe as the dispositions tree does); the contested remedy points at capture disposition --supersedes, which retires one id and adds one so a contested set never shrinks — ruled: the disposition verb refuses under contest exactly as promote does, with a message naming hand repair; every guarded-read failure on a record file is rendered with the not-a-real-directory wording, false for a permission-denied or oversized regular file (carry the reason into the Unsafe entry); and the two readers' byte caps differ (already captured as a nit — export one record cap and use it in both walks, with parity rows at cap and cap+1).
- iss-2608300846120979itd-183 sixth-round residue: the tag and anchor floor catches only the double-bang shorthand at line start — single-bang local and verbatim tags, and an explicit key carrying a tag, an anchor or an escape are all admitted (refuse any tag at line start and any explicit-key line the pattern cannot fully read); the raw-heading scan blanks fenced lines so an HTML block opened outside a fence that continues through fence delimiters is mis-titled and admitted (use the fence mask only to disqualify an open tag on a fenced line); a div with a heading role is neither caught nor disclosed; the renderedText comment does not say a double-encoded reference is deliberately left as the different heading it renders as; the amp-entity test still continues on error rather than asserting the refusal the commit and record claim.
- iss-2608300846123075Two regressions introduced by the sixth-round fixes: confining the setext scan to the frontmatter offset trusts a closer that overshoots into the body, so a record whose first block is closed by three dots or never closed lets a setext excluded heading travel whole (refused before the fix); and anchoring the flow-mapping scan to a brace that opens the line reopens nested flow keys — a key after a newline inside braces, a flow map in a sequence item, a flow map in a flow sequence — all admitted while the fifth-round record claims them refused. Restore the narrow skip (only an indented line in the first block, or refuse a dots-closed or unclosed first block) and widen the flow anchor or track brace depth across the first block.
- iss-2608300848049813itd-180 sixth-round nits: a permission-denied run or item directory aborts the whole outstanding report (and an enabled rule fails the lint run) instead of being routed to Unsafe with a reason as files are; a not-well-formed record is listed as standing indistinguishably from a readable one, and the prescribed hand repair (write supersedes_disposition into the surplus record) is inert when the surplus record is the malformed one because its supersession is discarded — mark illegible ids in the contest message; the board and findReadingItem describe a symlinked item file differently. Pre-existing, out of scope: capture verbs take the working directory as the repo root.
- iss-2608300914552505The quote blanker treats any quote character as a scalar opener, so a quote inside a plain scalar (an apostrophe in ordinary prose) or an escaped quote inside a double-quoted scalar pairs with a later quote and blanks the excluded key sitting between them; the flow-key scan then never sees a nested origin and the value travels while the manifest asserts refusal — demonstrated end to end on three shapes. Blank only quotes in scalar-opening position (line start, after a colon-space, comma, brace, bracket or dash-space) with escape-aware double-quote matching, or refuse a quote that is not in opening position on any flow line as unresolvable; add the three shapes as tests.
- iss-2608300914553076unresolvableFrontmatterShape and the setext first-block bound run on the first --- found anywhere, so a frontmatter-less admitted doc with a thematic break refuses the whole assembly (a lone rule reads as an unclosed block; a rule followed by an image line reads as a YAML tag; a rule followed by an anchor-like line or a dots paragraph likewise); every docs page is admitted and several open with image lines. Scope both to a block opening at line 0 (BOM allowed), which is the only place the stripper recognises one. Residue, pre-existing and shared with the site renderer: a four-space-indented fence delimiter is accepted as a fence while CommonMark reads an indented code block, so a heading between two such lines is masked.
- iss-2608300915534350The raw-heading title is cut at the first closing tag of ANY element, so inline markup inside a heading element — an anchor then text, or emphasis on the first word — truncates or empties the title and the excluded section is admitted (refused before the seventh-round commit); bound the title at the opening element's own closing tag, the next heading open, or a blank line. Also: blockCloser trims indentation before testing three dots so an indented ellipsis inside a block scalar closes the block and refuses the file (test at column 0 only); the double-quoted span does not honour an escaped quote; the setext loop reads the frontmatter closer as an underline of a column-0 last frontmatter line.
- iss-2608300924205748The intent-audit ingest path applies no privacy scanner to agent-produced prose: a rationale, narrowing or evidence reference carrying an absolute home path, a hostname or a person's name is written verbatim into the committed shipped intent record, with only the committed-file privacy lint downstream to catch it. Pre-existing for the per-criterion fields; the scope-condition dispositions inherit the convention. intent/redact.go already wraps scanner.Redact and is the canonical primitive to route the verdict's free-text fields through before the write.
- iss-2608300925423309capture resolve --production-mode and capture wontfix --production-mode on a record that predates disclosure (every existing issue) append a lone production_mode with no origin, and the branch's own record_provenance blocker then reports the record the command just wrote as a state no command produced; the restamp test covers only an already-stamped fixture. Refuse a restamp when the record carries no origin (this record predates disclosure; nothing to restamp), state it in spc-56, and test on an unstamped fixture. Low, noted: resolveProductionMode reads the pin on paths that mint nothing, so a malformed pin refuses unrelated operations — fail-closed by design.
- iss-2608300927241768itd-181 review nits: the intent-auditor definition's frontmatter description still summarises the output without the disposition surface; the brief's intent surface page describes the audit ingest row as the per-criterion write only; the human dead-letter render omits the untested split the JSON reports; the staged-rollout test skips on an unreadable shipped directory where a fatal would be stricter.
- iss-2608300927577163The record_schema grounds check passes three spellings capture's strict reader refuses — single-quoted, empty list, and block-spelled — so a committed record is lint-green and silently skipped by every capture surface, and an empty string is refused by lint while the reader accepts it; the lapsed_at block immediately below already handles every one of these shapes. Mirror the lapsed_at treatment: absence by the null set only, block-spelled via the blocks map, single-quoted as the malformed scalar the reader sees, and add the four spellings to the vocabulary test.
- iss-2608300927577980RecordGrounds accepts text carrying an unclosed HTML comment opener, writes the bullet, and the comment mask then hides that entry and every line after it from the grounds reader and the claims readers, while the result reports success and the CLI says nothing; refuse before the write when the appended bullet does not raise the parsed entry count or leaves a comment open. Notes: the grounds grammar error echoes the raw operand before redaction (terminal only); RecordGrounds writes without the mint lock, like the existing in-place stampers.
- iss-2608300929274006The outstanding report's filename grammar for reading items and dispositions (readingItemFileRe, DispositionFileID) is stricter than the record_schema gate's FilenameNumRe, so a hand-written rdi-N-slug.md or dsp-N-slug.md passes the gate and is then invisible to the report; for those two families the divergence fails toward silence rather than a false claim. One grammar, the resolver's, for every family the report walks.
- iss-2608300930057882itd-179 ruthless findings: the plugin surface instructs the host to report a redacted member from intent ready --grounds --json that the verb never emits — the redaction note goes to stderr and the JSON is the unchanged readiness result, so the redaction-is-never-silent promise is broken on the one plane the feature is wired for (render an envelope carrying the grounds result beside the readiness result); the readiness reader admits a hand-typed entry below the writer's substance floor, so the seventh check under-enforces its own claim (skip sub-floor bullets in ParseGrounds); a successful write followed by a readiness fault exits 2 with no receipt, so a retry appends a duplicate entry; RecordGrounds enforces no bucket rule while the shipped-bucket exemption says never backfilled and the branch itself backfilled three shipped intents (refuse terminal buckets, or word the exemption honestly); missing versus malformed --grounds exit 2 versus 1 unevenly; the 36-record NOT READY consequence and the forward-only choice are recorded nowhere in the decision log.
- iss-2608300931349990itd-178 prose findings: the plugin pages say every record a command writes carries the two keys, but capture disposition writes a dsp record with neither (narrow to intent, spec and issue records, as spc-56 scoped); the same pages assert the keys are excluded from every reading by the input assembler's field projection, describing code not in this tree (the sentence lives in spc-56's out-of-scope list — delete it from the user-facing surface); the internal package map omits the new provenance leaf while listing its sibling leaves.
- iss-2608300933025999The quote blanker blanks a quoted flow KEY as though it were a scalar — {"origin": x} and {a: 1, 'origin': x} sit after a brace or comma, so the span is blanked before the flow scan can read it and the excluded key travels under a manifest asserting refusal (pre-existing on both sides of the eighth-round commit, in the function it rewrote; the flow-key pattern's own quoted-key alternative never fires). Skip a quoted span whose remainder begins with optional whitespace and a colon — a quoted scalar followed by a colon is a key. Also: excludedKeyInFirstBlock still opens its block at the first --- found anywhere, so the frontmatter-less false-refusal class persists on the key path (take the range from firstBlockRange); the escape-aware double-quote alternative admits an invalid-YAML shape the previous commit refused (disclose); a heading whose text follows a blank line inside the element, or carries a line break element, is neither refused nor in the residue list; the per-element regexp cache is unbounded by input-supplied tag names (moot in a one-shot CLI, worth a note for a long-lived transport).
- iss-2608300935215868The outstanding report's admitted set is keyed on proposal alone — run and existence are never checked — so an admission under one run naming a proposal from another silences the other run's item, and a proposal naming nothing passes record_schema because proposal is not resolved the way occasioned_by is (key by run and proposal; resolve proposal on the same terms). Pre-existing, not this branch's: scanRecordStores reads with os.ReadDir and os.ReadFile, no symlink refusal and no size cap, so a symlinked record's frontmatter key names can appear in lint output; the new RS fixtures carry a cited_by property the closed schemas do not know.
- iss-2608300935218982record_schema's required-field check tests absence on the raw value with quotes intact, so a quoted-empty grounds or occasioned_by ("", '', or " ") passes as present while the writer-side model trims and refuses it; a groundless admission is lint-green and the report leg then counts its proposal as admitted, silencing the very report built to catch it. The iss store has the identical pre-existing gap (found_during: "" passes). Strip surrounding quotes before the absence test, using the rule's own issueScalar, and add the quoted-empty spellings to the tests.
- iss-2608300939008274itd-189 ruthless findings: a widening proposal whose admission sits behind an unreadable admissions tree is still reported outstanding with a remedy to write a disposition, contradicting the invariant the disposition side enforces (after the admitted check, break when the admissions tree is unreadable; add the mirror test); the issues README store contract still says the ledger root holds two sibling families while four roots are now declared; the held exclusion on the admission leg is untested; proposal is never resolved while occasioned_by is.
- iss-2608300940486285itd-183 eighth-round security findings: the scalar-position rule treats a colon or a dash as an opener without the whitespace YAML requires, so a quote inside a flow plain scalar (a - 'b, origin: X or a:'b, origin: X) blanks the excluded key beside it — the commit's own test shape with one extra space; verified fix: open a scalar only at line start, after a line-start dash, after a colon followed by whitespace, or after a brace, bracket or comma. The raw-heading title bound stops at a closing tag inside an HTML comment or an attribute string and the opener at a greater-than inside an attribute value, so a heading every browser renders as the excluded title is judged as something else — blank comments and quoted attribute values length-preservingly before bounding, or disclose the three shapes. firstBlockRange recognises a block at line 0 only while excludedKeyInFirstBlock still takes the first --- anywhere (also in the ruthless record). The per-element regexp cache is keyed by an attacker-chosen element name and never evicted — drop it or use one static closer pattern with a case-folded name compare.
- iss-2608300941548519itd-178 second-round observations: the restamp gate tests origin presence, not validity, so a record with an out-of-vocabulary origin accepts a restamp (the origin stays invalid and the lint still reports it — harmless; calling the origin parser would make the intent literal); a record carrying a lone origin, itself a blocker, is silently repaired into a clean pair by a restamp — a legal write inside the lint's declared residual, worth a sentence in spc-56.
- iss-2608301203521317record_schema's store walk reads every record with os.ReadDir and os.ReadFile, with no symlink refusal and no size cap, while the sibling reading walk in readingoutstanding.go reads the same trees through fsutil.ReadGuarded — so a symlinked or oversized record is followed by the gate and declined by the report, and a symlink's target frontmatter can surface in lint output. Pre-existing across all four original stores; noted during the itd-189 security review and left out of that branch's scope. Read the store walk through the same guarded read the report uses.
- iss-2608301203525338record_schema declares a bucketField only for the admission store, so an admission whose run field contradicts its bucket is named while a disposition whose item field contradicts its item-keyed directory is not — the same double claim, checked in one store and not its sibling. The disposition store declares no frontmatter schema this cycle (spc-58's stated gap), so the field was left undeclared rather than half-stating a schema in a second place. Declare it when the disposition store gains its required set.
- iss-2608301206032013a control character in --grounds passes the pre-mint gate and faults inside the locked stamp leaving an orphan draft
- iss-2608301206034359the grounds substance floor counts runes not letters so twenty zero-width spaces satisfy the promoted refusal
- iss-2608301206036067RecordGrounds is an unlocked read-modify-write so a concurrent second grounds write silently discards the first
- iss-2608301206073609hidden runes reach committed records verbatim because termsafe.EncodeHiddenRunes is not applied at the record-write boundary
- iss-2608301206074955an indented continuation under a valued frontmatter key skips the record in every reader while record_schema reports nothing
- iss-2608301212423009the comment authorising the promoted grounds refusal misstates the corpus state it rests on
- iss-2608301212423956two stated guarantees in the grounds path are mutation-vacuous: the wontfix declined-token refusal and the read-back count check
- iss-2608301212424896unescapeScalar in the schema gate is a second independent copy of capture.unquote and the parity table has no escaping row
- iss-2608301212428844itd-179 round-2 ruthless cosmetics: backticked wontfix flag usage, double-counted redaction spans, refusal message names a cause that did not occur
- iss-2608301221402131checkIssueRecordShape's block-spelled lapsed_at leg gates on the same-line value being empty, so it never sees the blocks entry that a block-scalar HEADER now populates: lapsed_at spelled as a header over an indented instant reports 'not an RFC 3339 instant' naming the header byte, instead of the block-spelled message its sibling shape gets. Both refuse the record, so this is message quality rather than a hole — the reader is sent to fix a format that is not the problem. Read the lapse leg through the same schemaRecord accessor the required-field check uses.
- iss-2608301237450133rawHeadingTitleEnds materialises every bound match in the rest of the document per opener making the scan quadratic and hanging the assembler
- iss-2608301237450573pre-existing on the itd-183 branch: a compact nested mapping in a block sequence leaks an excluded key, and rawHTMLHeading's fence comment overclaims
- iss-2608301237456350confining the frontmatter block to line 0 silently admits a delimited block carrying an excluded key that the manifest still asserts was excluded
- iss-2608301237457008deleting escapedQuotedKey narrowed the escaped-key refusal from regex whitespace to space and tab so a CR-preceded escaped excluded key is admitted
- iss-2608301237458660maskMarkupData terminates an attribute value at the next matching quote anywhere in the document so one unclosed quote erases a raw HTML excluded heading from the scan
- iss-2608301237459461renderedText substitutes a space for a removed HTML tag so a tag inside a word splits it and the excluded heading escapes on all four heading paths
- iss-2608301244450106a wontfix reason-derived grounds value skips ValidateText so a control character in wontfix_reason still reaches yamlScalar
- iss-2608301244458074internal/core/frontmatter has no entry in the internal README package map
- iss-2608301251385581the comment mask suppresses heading discovery so an excluded heading wholly inside an HTML comment is admitted though the file still carries it
- iss-2608301251391469TestRawHeadingCaseIsFolded does not discriminate the fold it is named for and the entire package stays green when the guard is removed
- iss-2608301251394412opensTag restates htmlTagRe's rule in hand-written code giving one file two definitions of what opens a tag
- iss-2608301251398360a flow-context explicit key leaks an excluded field and wants the same fix as the compact block-sequence mapping
- iss-2608301301041887the lock assertion in the grounds test is wall-clock so a loaded runner could pass it with no lock held
- iss-2608301301044588the grounds word floor counts letter runs so a language written without inter-word spaces is refused and its bullet is silently dropped by the reader
- iss-2608301306580014the privacy backstop has two blind spots over the issue ledger: the escaped Windows home path yamlScalar writes and a harness_leak root that excludes the ledger
- iss-2608301306587401Link and Plan do unlocked read-modify-writes on records RecordGrounds now locks
- iss-2608301308367566record_stores values are not containment-checked so a committed config walks the record gate outside the repository
- iss-2608301308368922one committed symlink at the admissions root stands down the widening leg for every run while record_schema stays silent
- iss-2608301308369559the blank-required-property message asserts the reader accepts a value it actually refuses inverting the defect the previous commit fixed
- iss-2608301327012166checkRecordJoins does not consult the retired set so one rule gives two answers about one pruned handle
- iss-2608301327012407the new Unadmitted clause in Empty is the one surviving mutation because Empty has no production caller
- iss-2608301327013320an admission whose proposal names an item in a different run passes the gate silently and admits nothing
- iss-2608301349335095an indented code block in a committed issue record turns the site-render preflight gate red, and nothing on the capture path refuses one
- iss-2608301350287219no gate reads a record body as markdown before the site render, so a construct the renderer refuses reaches the branch and turns preflight red at the far end
- iss-2608301350527962the line-bounded attribute mask replaced the browser reading instead of adding to it so an attribute value carrying a greater-than and a line break hides the heading opener
- iss-2608301350533102fenceMask spans the frontmatter so a fence delimiter inside a block scalar switches off the excluded key scan for the rest of the block
- iss-2608301350534164a newline between an attribute name's equals and its opening quote declines the markup mask on both readings so a value carrying a greater-than truncates the heading opener
- iss-2608301350537306maskMarkupData searches the whole remainder of the document for a newline once per attribute assignment making the mask quadratic in file size
- iss-2608301411010342the absent-required-property message names a validating reader for two stores that have none, and this branch certified that claim as store-wide
- iss-2608301411017768the sameBucket join message asserts a per-bucket id mechanism that exists only for reading items, so a cross-family target gets a confidently false diagnosis
- iss-2608301421380392the raw heading soft bound does not match a CRLF blank line so an unclosed heading in a CRLF file reads its title over the rest of the document and travels
- iss-2608301421381157the escaped key refusal returns through an error message asserting the block is unclosed and the key excluded when neither need be true
- iss-2608301421382564a raw heading opener with no hard bound renders its title over the whole remainder so the scan is quadratic in a shape the linearity test does not cover
- iss-2608301423540137the orchestrator committed record bodies to three build branches without running the record and site gates, turning site-render red on two of them
- iss-2608301450065320the assembler's key and heading signals are scoped to markdown so a record-shaped document inside a Go fixture carries its Audit Notes into the bundle while the manifest asserts refusal
- iss-2608301455384564the grounds floor's stated limits: mark-free text in an unnamed scriptio-continua script is refused, and the letter floor is far heavier for CJK than for English
- iss-2608301455387735the character floor is answerable by padding so three letters plus seventeen non-letter runes clear it and an entirely invisible text passes
- iss-2608301455387795two load-bearing conditions in scriptioContinuaOnly have no test so deleting either leaves the whole suite green while the refusal names a property the text lacks
- iss-2608301519253368the join's blocker message asserts per-bucket id minting that the same rule refuses as a fault and that the branch base already made false
- iss-2608301519254240four correct guards in the outstanding report and the join have no killing test so each mutation survives the whole suite
- iss-2608301519254418two message legs tell the author the reader refuses and skips their record when the admission reader counts it and the surprise store has no reader at all
- iss-2608301519255156the gate never judges schema_version's value so fifteen spellings the ledger reader refuses are lint-green
- iss-2608301519255871the proposal join resolves handles numerically while the report keys them as strings so six spellings pass the gate green and admit nothing
- iss-2608301620341037spc-57's Tests section lists none of the grounds floor tests added in rounds three to five
- iss-2608301620343236the len(rs) != 1 guard in scriptioContinuaOnly is unreachable as called so no fixture can enter it
- iss-2608301620346560the scriptio-continua refusal names a three-unit floor while the letter floor asks twenty so satisfying the message earns a second refusal
- iss-2608301634520703mark judged on id and on slug are both unreachable in the case they guard so removing either alone repeats the shape the round was convened for
- iss-2608301634527391the bucketField implies a bucketed store rule is asserted in prose only so a flat store declaring one would report filed under empty
- iss-2608301646042379the control character refusal claims no record field can hold the rune when DEL C1 and bidi all round trip through committed scalars
- iss-2608301646046226grounds text the floor accepts can be refused by the site renderer and the entry is append only so no verb can remove it
- iss-2608301649337920the unsafe finding on an admissions path tells the operator abcd capture refuses it too when capture has no admissions code at all
- iss-2608301649337965isAbsentValue reads an empty flow sequence as absent but not an empty flow mapping or an explicit null tag so a blank grounds passes the gate and silences the report
- iss-2608301649339636the proposal join constrains the target bucket but not its position so an admission naming a non widening item passes clean and admits nothing
- iss-2608301656192369the join and bucket legs strip the scalar twice so a doubly quoted empty value is present to one leg and absent to the other and no leg speaks
- iss-2608301656193936the bucket blocker claims the item goes on being reported unanswered for exactly the target shape the padding leg beside it stands down on
- iss-2608301656200729readerFailsClosed is false for the adr store on the duplicate key leg and the record that resolved it claims all four stores were verified
- iss-2608301656202623three guards in the join and the outstanding report survive their own deletion and one equality check is inert by construction
- iss-2608301657350399five nits from the round five ruthless review including a weak negative assertion in the control refusal test
- iss-2608301657354776a resolve or wontfix replaces the grounds scalar so the conjecture a promote recorded is silently destroyed
- iss-2608301657357989the plugin surface claims the grounds verb refuses a shipped record so no terminal bucket carries grounds while three shipped intents do
- iss-2608301715040589an interactive cp prompt stalls an agent silently and has now cost three sessions time in one day
- iss-2608301726130926two shipped acceptance criteria hold a MET_WITH_CONCERNS that becomes NOT_MET if itd-185 does not land in this phase
- iss-2608301744251874development token metering is parked as a note and owes a file or reject decision at the next phase planningrelated itd-2609292107351737
- 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-2608301744300631an empty collection in superseded_by is an absence to the gate and a rendered link to record Describe so the two readers disagree about whether the record names a successor
- iss-2608301747001641a malformed grounds bullet on an issue record reads as prose so no gate can review it losing coverage the frontmatter rule had
- iss-2608301747003705Issue.Grounds changed from a string to a list in the json envelope on an unreleased branch
- iss-2608301747006182no gate requires a terminal folder record to carry a grounds entry so fourteen resolved records have none
- iss-2608301755006875the shared unanswered tail on the padding and bucket legs is not true of an item whose disposition is declined or held
- iss-2608301803423101an unclosed comment or fence anywhere in an issue record blinds every grounds triage route permanently and promote orphans a draft per attempt
- iss-2608301803425790five nits from the itd-179 delta review including two exported functions with no caller and a renamed citation that now names the wrong predicate
- iss-2608301803426383three doc comments outlived the tests and the rule they describe and one contradicts the comment eight lines below it
- iss-2608301805069999the grounds writer judges the whole file while the reader judges the body so a frontmatter Grounds comment makes triage report success and record nothing
- iss-2608301808193750the blank grounds enumeration claims the trailing comment is the last gap while eleven further nothing carrying spellings pass green
- iss-2608301808197261four nits from the itd-189 delta security review including an unpinned bucket field stand down and a zero width space passing the gate
- iss-2608301808198621isAbsentValue decides on literal strings rather than the yaml null and empty class so chasing spellings cannot close it
- iss-2608301813253101the duplicate key fallback claims every record surface keeps the first value while the disposition reader discards both and reports the record illegible
- iss-2608301813259334three nits from the itd-189 delta ruthless review including a godoc whose ordinals no longer match the code order
- iss-2608301836222858grounds.Vocabulary claimed to be the one copy every gate and every flag description reads, and no surface reads it
- iss-2608301844363341a formatter hook substitutes smart quotes into edited source comments which passes gofmt and every gate and is visible only in a diff
- iss-2608301856299268a size classification for specs and tasks is parked as a note and owes a design and filing decision in a future sessionrelated itd-2609292107351737
- iss-2608301901260461four nits from the itd-189 fix delta review including an inverted test failure message and an over broad negative loop
- iss-2608301901260678the refusal tells an issue author the record is skipped by every issue surface while the changelog derivation reads resolved records leniently
- iss-2608301901264848the nine store enumeration checked one reader per store so rdi and dsp are assigned an answer their second reader contradicts
- iss-2608301908270807the decision log entry says the record states the residual survives and it does not and it cites a label that appears nowhere
- iss-2608301908270888an unclosed comment or fence in an issue body still locks the record out of every triage verb and no open record tracks it
- iss-2608301908284034the vocabulary comment says every refusal renders it when two of thirteen do and the drift record omits the one copy that is a gate
- iss-2608301908288212four nits from the itd-179 fix delta review including a body line offset that is one ahead of the rendered body
- iss-2608301918362294a prose enumeration of where a value is copied cannot be maintained and has now been wrong four times on two different symbols
- iss-2608310912203724a record authored straight into resolved never invokes capture resolve so the grounds obligation reaches only records that pass through the verb
- iss-2608310912206749two specs state prose facts about the tree that are false including a staging count wrong on all three numbers
- iss-2608310912206941the reading item mint has no caller outside its own package so the admission and surprise schemas gate a corpus nothing can populate
- iss-2608310912217521the grounds flag carries two incompatible grammars on one verb family with a floor on three routes and free text on the fourth
- iss-2608310954048572spc-62 states that internal/core/reading already locates the four cold-reading definitions and hashes them for spc-63 instrument identity, and it does not: no non-test file in that package references agents/ at all. A builder reading the spec would take the locator as existing and find nothing to call. The locator is unbuilt work that spc-62 must deliver, and the sentence is a prose claim about code behaviour of exactly the shape itd-195 refuses.
- iss-2608311025494209itd-184 adds four cold-reading definitions to agents/, taking the shipped prompt count from eleven to fifteen, but 05-internals/01-agents.md still says 'Eleven agent prompt files ship in agents/ today' (line 3) and 'Carried today by all eleven shipped prompts -- the five synthesis/composer prompts, the five reviewer/researcher prompts and the ledger scribe alike' (line 106). The four are also absent from that chapter's 'Shipped agents outside the design roster' section, so the roster no longer lists every shipped prompt. The itd-184 builder's lane did not include 05-internals, so the correction was captured rather than taken.
- iss-2608311039531552The strip-a-matched-quote-pair-then-frontmatter.Unquote idiom now exists in three places: capture's reader (internal/core/capture/parse.go decodeScalar), record-lint's schema gate (internal/core/lint/schema.go readerScalar) and the cold-reading definition locator (internal/core/reading/definitions.go scalar). Unquote's own doc says its argument is the scalar's INNER text, so every caller that reads a possibly-quoted frontmatter value has to do the strip first, and a caller that forgets it -- as the locator's first cut did -- refuses well-formed records with a message comparing a value against itself. The idiom belongs beside Unquote in internal/core/frontmatter, with the three call sites moved onto it.
- iss-2608311039586922commands/reading.md describes the bare verb's 'definitions' field as 'the reading definitions present under agents/'. Since itd-184 that field is what the definition locator RESOLVES, not what is present: a cold-reading-<name>.md naming no closed position is invisible to it, and a definition silent about its position or its regime refuses the whole verb with exit 2 rather than being listed. The plugin surface should say resolved rather than present, and say that a malformed definition is a refusal. The itd-184 builder's lane did not include commands/, so the correction was captured rather than taken.
- iss-2608311051046981The new cold-reading-evals CI job is not a required status check: .abcd/work/rulesets/main-protection.json lists attribution, check (macos-latest), check (ubuntu-latest), external-review, gitleaks, record-lint, smoke and zizmor, and the job spc-64 lands reports a conclusion without gating the merge. The whole point of the always-run lane is that a record-only pull request cannot reach main with warm content in included material, and an unrequired check does not stop one. Add cold-reading-evals to the ruleset and to its committed mirror.
- iss-2608311100440709The ac-3 operator-surface guard walks the generated baseline caches under the abcd directory, whose map keys are arbitrary data: the citations baseline is machine-written from cited URLs, so a legitimate citation whose URL contains the substring 'regime' turns the guard red with findings that name no real defect. On a branch whose subject is supply regimes that is not a hypothetical, and the failure sends the reader hunting a regime knob that does not exist. A generated cache is not an operator surface and does not belong in the enumeration.
- iss-2608311100496798The ac-3 operator-surface guard's configuration walk is globbed at two non-recursive directories, so four committed JSON files abcd reads as configuration sit outside it: the persona registry, the release surface, the release-gate manifest and the branch-ruleset mirror. A regime key written into the persona registry leaves the guard green. Two sentences claim otherwise: the guard's own header says nothing is a written list and the guard cannot fall behind the surface it guards, and spc-62's residue paragraph says the walk reaches a file once one carries the key. The glob is a written list of two directories and it has already fallen behind by four files, so both sentences are false as written. A claim about behaviour that the code does not establish is the itd-195 class this very criterion was split to enforce.
- iss-2608311123267602spc-63's payload item shape disagrees with the shipped cold-reading definitions: the spec states items[] = {pattern_named, body} with body fields claim, candidate, characterization, why, while every definition under agents/ instructs a FLAT item carrying pattern plus the record schema's own body fields (claim_surfaced, candidate_id, characterisation, why_a_tension), which is also what issueschema.ReadingBodyFields declares and what capture.IngestReading writes. Building the verb to the spec's table would refuse every output the shipped instrument can produce.
- iss-2608311127491949The ship ceremony's repoint step names two link classes -- every intents/planned link to the shipping intent, and the closing spec's bare sibling links to still-open specs plus bare links to it from open specs. A third class exists and is not named: a link from an ALREADY-CLOSED spec pointing at ../open/<the spec being closed>. Closing spc-62 left spc-61, itself already closed, holding ../open/spc-62 and record-lint refused with a links_resolve BLOCKER. The survey greps the checklist implies (specs/open/ and bare siblings) do not match that shape, so it is invisible until the gate runs. Class (b) is already recorded as having broken two earlier ships; this is a third sibling of the same shape and the checklist should name all three, or the repoint should be mechanical rather than a hand survey.
- iss-2608311145258479The definition locator checks that a regime is a KNOWN value but never that it AGREES with the position it sits under. knownRegime tests membership in the four, so a definition carrying regime evaluative under position widening loads clean: the binary prints all four definitions and exits 0 while the byte-identity and pinning tests go red. The comment at the top of definitions.go argues that answering from a table rather than the file is what would make a drift undetectable, but the file is not checked against the position either, so the drift is undetectable at RUNTIME and caught only in CI. This matters downstream rather than here: spc-63's regime gate resolves a run's position to its definition and reads the regime from LoadDefinition as the source of truth, so a drifted file hands the ingest verb the wrong licence without any refusal, and the gate that exists to catch a reading exceeding its licence would be enforcing the wrong one.
- iss-2608311145286014The reading surface doubles its own error prefix: the CLI layer prepends 'reading: ' and the locator's errors already carry it, so an operator sees 'abcd: reading: reading: agents/...' on a refusal. The path this appears on is the definition-refusal path spc-62 introduced as its own proof of wiring, so the first thing the new surface shows a human on failure is a stutter.
- iss-2608311206480573The ingest verb's missing-body-field guard is mutation-vacuous: removing it (checkItem's len(missing) > 0 branch) leaves every test in internal/core/reading green. No case builds an item that carries the position's own body but leaves one declared field empty or absent, because TestWrongPositionBodyIsUndecodable supplies a FOREIGN body and the unknown-key check fires first. The guard is the one that would catch a reading returning a partial item at its own position.
- iss-2608311207469829The read-block eval never asserts the positive half of the assembler's field projection. All three WARM-FIELD plants sit in headings that redactExcluded strips BEFORE projection runs, so each of them tests the redaction and none tests the projection. Deleting the projection from the shipped-intent include row leaves the whole lane green, and deleting it from all three intent rows is also green. The consequence is real and was demonstrated: with one extra unprojected section added to the fixture's shipped intent, the clean binary keeps that section out of the bundle and the mutant passes it in. The corpus cannot distinguish 'the projection is positive at field granularity' from 'the projection is gone and the redaction cleaned up after it', because it holds no section that is unprojected and unexcluded at the same time. The remedy is a plant, not another floor: a sentinel in a shipped-intent and draft section that is neither projected nor on the exclusion floor.
- iss-2608311207501002The carriers floor added to the read-block eval proves a carrier's PATH is in the manifest and never that its BYTES are in the bundle, so a carrier can arrive empty and every absence assertion over it is vacuous. Emitting empty text for the projected candidates leaves requireCarriers satisfied while the WARM-FIELD and DRAFT-ORIGIN assertions and the item-text half of the field-absence check assert nothing at all; stripping the whole-file text of the disciplines and specs carriers is green the same way. Four of the five carrier rows are affected, and only the two the negative control happens to cover are pinned at content level. The floor was added in the previous round to close exactly this class -- an absence assertion with nothing underneath it -- and it was placed one dimension short of the thing it was meant to measure.
- iss-2608311207560513Four of the read-block eval's oracle tables carry no emptiness floor, so silently emptying any of them is green: carriers, excludedKeys, excludedHeadings and excludedFamilies. Emptying carriers and re-breaking the assembler's store node type restores exactly the defect the previous round was opened to close. Emptying excludedKeys with excludedHeadings disarms the field-absence check entirely, and emptying excludedFamilies disarms half the family-absence check. The holes table did get a floor in that round, but it is a greater-than-zero test over a two-row table, so it can still halve without noticing. A floor of greater-than-zero on a table whose size is known is not a floor; each table should assert its declared count.
- iss-2608311211235195The ingest verb's echo() sanitiser and its length cap are mutation-vacuous: neutralising termsafe.Sanitize, or the maxEchoedRunes truncation, leaves every test green. Both are trust-boundary guards on a path that echoes model-produced payload text to a terminal and into a durable refusal record. Three interpolations also reach a message unsanitised: ParsePosition quotes the payload's raw position token, and the parked manifest's run id, position and assembler version are interpolated verbatim.
- iss-2608311230116767The cold-reading ingest verb walks and deletes in the ledger and the durable readings tree with no containment against a symlinked ancestor. rollbackRun does os.ReadDir and os.Remove on .abcd/work/issues/readings/<run> and .abcd/development/readings/<run>, and writeJSON does os.MkdirAll plus WriteFileAtomic under .abcd/development/readings, so a committed git mode-120000 symlink at either path redirects the delete and the write outside the repository root. The sweep runs as step one of Ingest, before the payload is even read, so no valid payload is needed. capture.refuseSymlinkedDir guards the identical ledger directory one file away, and fsutil provides os.Root-scoped primitives for exactly this.
- iss-2608311230204063The ingest verb hands item body text to capture.IngestReading after redaction only, and capture's yamlScalar refuses runes below 0x20 and nothing above, so a model-authored bidi override, C1 control or zero-width rune lands verbatim in a committed markdown reading record. This diff is what makes that writer reachable, and it makes it reachable exclusively from model output, so a Trojan-Source-style reversed span can reach a record a reviewer reads in a terminal. internal/termsafe carries a lossless encoder for exactly this boundary.
- iss-2608311230204232The ingest verb's unknown-field refusal puts raw payload-controlled JSON key names into ItemRefusal.Field without echo(), so they reach the committed run.json and the --json render un-sanitised and un-capped. encoding/json escapes C0 but not C1, DEL, bidi overrides or zero-width runes, which internal/termsafe/json_test.go already pins. The sibling Detail field goes through renderFields and is clean, and ingest.go's header claims every payload-derived string reaching a terminal or a durable record is sanitised and capped.
- iss-2608311230301576Nothing between the ingest verb's 4 MiB payload cap and the record write enforces issueschema.RecordReadLimit, so one item with a large body produces a committed reading record every reader in this repo then refuses, including the disposition path that makes the item answerable. The item is durable and permanently undispositionable, which is the split RecordReadLimit's own comment says the single constant exists to prevent.
- iss-2608311230305308The ingest verb permits re-ingesting a run id that already committed: run_id is payload-chosen and nothing refuses a second ingest, so the second write overwrites run.json while the first run's reading records stay in the ledger unnamed by any run record, and a later refusal can drop refusal.json beside an existing run.json so one run directory asserts both that it committed and that it was refused. spc-63 and ingest.go both say a rerun is a new run with a new run id, never an amendment; that is a comment rather than a check.
- iss-2608311230307436The ingest stage marker's Records list is written and never read: write() says the marker exists so a rollback removes exactly the files this ingest wrote, but rollbackRun deletes by filename grammar over the whole directory and never opens stage.json. The behaviour is currently safer than the comment, but the comment is load-bearing for the rollback's containment reasoning and is false.
- iss-2608311234532073The ingest verb's durable refusal record loses the reason it exists to carry: refuse() applies echo() to the composed cause, but every payload-derived substring inside that cause is already echoed at composition, so the outer call only truncates trusted prose. Measured: a 338-rune terminal message becomes a 123-rune refusal.json reason cut mid-word, and for an every-item-refused run the per-item refusals are cut off entirely.
- iss-2608311234537042The cold-reading ingest verb's orphan sweep deletes a concurrent invocation's ledger records. sweepOrphanStages and rollbackRun hold no lock, and nothing distinguishes a crashed stage from a live one, so a second ingest starting while the first sits between its ledger write and its commit marker finds the first's stage, sees no run.json, and removes both its records and its stage. The first then writes run.json and exits 0 naming records that no longer exist. capture.IngestReading takes the ledger flock for its own write, but the sweep sits outside it.
- iss-2608311234540729claim_type's closed vocabulary (criterion, causal, context) is enforced nowhere. agents/cold-reading-entailment.md instructs it and spc-63 tables it, but validateItems checks non-blank only, capture.validateReadingStrict has no enum, and issueschema declares only the field name, so an entailment payload carrying an arbitrary claim_type lands in the durable record.
- iss-2608311234541392commands/reading.md tells a host that every list-level refusal leaves a refusal record, but four of the six list-level refusals it enumerates (wrong _type, unresolvable run, manifest hash mismatch, drifted definition) deliberately write nothing, because the run's identity is not yet proven. The same page instructs the host to report refusal_record from the JSON, which the front door can never emit: a refusal returns an exitError and the render is never reached, so IngestResult.RefusalPath is dead surface through the only front door.
- iss-2608311234549104The cold-reading ingest verb's echo() is a fourth copy of the sanitise-and-cap primitive. termsafe.CleanProse/CleanProseLine declares itself the canonical home for the untrusted-prose cleaner every host-delegated ingest boundary needs before a model-supplied string is written into a durable record, and lifeboat, release and ideate all route through it. echo also omits the HTML-opener neutralisation that home performs.
- iss-2608311238236490The cold-reading assembler's exclusion floor carries no entry for the local ledger tier. internal/core/reading/include.go's Exclusions names .abcd/development/decisions, .abcd/work/issues, .abcd/work/DECISIONS.md and the readings family individually, but nothing for .abcd/.work.local — so every manifest the assembler writes is silent about the tier brief invariant 14 exists to keep out, and assertExclusions has nothing to enforce there. The tier IS excluded, by absence from the positive walk and by the .abcd deny segment, so this is a disclosure gap rather than a leak: a reader checking the manifest's asserted exclusions cannot tell that framing traces and declined construals were refused, and invariant 16 says an attestation never states less than the examination behind it establishes. Found while transcribing the exclusion table for itd-186's read-block eval, whose own family list does name the tier; the eval's local-tier falsifiers correctly need no Exclusions row removed, which is how the asymmetry showed up.
- iss-2608311301521073The read-block eval's projected carriers draw both of their markers from the same two fields, so the intent projection can be cut from five contracted fields to two and the lane stays green. The previous round added a second marker to each of the three projected carriers and drew every one of them from the Mechanism section, so the carrier set pins Press Release and Mechanism and nothing else. Narrowing the projection to those two drops Acceptance Criteria, Scope Conditions and spec_id, four manifest items vanish, and nothing notices; narrowing to one field alone is red. This is the third instance of one defect: the floor first measured nothing, then measured paths rather than bytes, and now measures two of five fields. The coverage matrix compounds it by carrying a row whose stated rule is the five contracted fields with a caught-by-carrier mechanism, so the newest row in the matrix is false for three of the five. Note spec_id cannot be pinned by a bundle-bytes marker at all: its projected text is the bare string spc-1, which also travels inside the whole-file spec, so the marker is satisfied without the projection; it has to be pinned off the manifest field column instead.
- iss-2608311301596091Four of the coverage matrix's declarations do not match what the eval does. The two per-position asymmetry rows state a one-part falsifier and claim a leak, but run verbatim both produce a refusal at exit 2 because the path-shaped exclusion entry fires first, and the plant plays no part; the leak appears only under the two-part mutation the rows do not state, which is the pattern the matrix documents twenty lines above for the family rows and then does not apply here. The markdown-only scope of the body redaction is named by no row at all, neither as a catch nor as a gap, and it is falsifiable in two corpus lines: a config file admitted by the root row carries its keys unredacted and the oracle reports three violations, so a runnable falsifier is simply unexercised, which by the matrix's own rule is the worse case than a declared gap. The structural-deny mutation for two of the four denied segments is named by no row, though both are caught. And the first-row-wins tie-break is stated as contract in the assembler and rowed nowhere, which is exactly what a gap row is for. A mislabelled catch is the same class as a mislabelled gap, one notch down, and this branch's own standard says a mislabelled gap would be worse than no matrix.
- iss-2608311302045104The coverage matrix's count pin catches a row deleted but not a row substituted. Replacing the structural deny row for the abcd namespace with a duplicate of the glossary row keeps the row count at 46 and the gap count at 6, orphans no sentinel class, and the lane stays green: the single most load-bearing rule in the assembler's contract leaves the matrix silently. The matrix discloses that it cannot check that it names every rule the assembler has, so this is the declared limit rather than a broken promise, but the by-duplication half of that limit closes with a three-line check that the Rule strings are distinct.
- iss-2608311306530338reading.LoadDefinition reads and hashes the definition file through a plain joined path rather than through the repository root, so a symlinked ancestor under agents/ can serve a definition from outside the repository. The read is harmless in itself, but the hash it returns is the definition half of an instrument identity sold as proving two runs read under the same instructions, and hashing a file that may not be in this repository makes that a claim about an unknown artefact.
- iss-2608311306533109The ingest verb's refusal list is unbounded in count. renderRefusals joins one entry per refused item into the durable refusal reason, and RunRecord.RefusedItems keeps one entry per refused item, with the item count payload-chosen — so a payload of many illegal items produces a refusal record and a terminal message hundreds of kilobytes long. The per-name cap on quoted field names states the principle exactly and does not apply to the refusals themselves.
- iss-2608311306535485The supply-regime gate is evaded by a single non-breaking space: RE2's whitespace and word-boundary classes are ASCII-only and termsafe.Sanitize does not mask U+00A0, so a registered signature's own phrasing with U+00A0 between two words produces no match and the item lands with no refusal and no flag. This is NOT the residue itd-185 discloses, which covers a fix proposal or disposition phrased OUTSIDE the registry; this is the registry's own phrasing with one invisible byte substituted, so it is an evasion of the gate rather than a limit of it.
- iss-2608311306536114The cold-reading ingest verb's orphan sweep deletes committed ledger records without holding capture's ledger lock. The stage lock serialises ingest against ingest only, so a concurrent capture disposition or promote in the same checkout can be reading a reading record while the sweep unlinks it.
- iss-2608311306536908recordBytes under-estimates the reading record by up to a factor of two: it is measured before the record writer escapes backslashes and double quotes, so an item body of quote characters lands a record roughly twice the measured size and past issueschema.RecordReadLimit. The envelope allowance is also measured before the ledger redactor runs, which can lengthen text when a placeholder is longer than the secret it replaces.
- iss-2608311306539528Two of the ingest verb's containment cases are mutation-vacuous. The in-repo symlink case points at an absolute path, which os.Root refuses on its own, so removing the explicit symlinked-directory refusal leaves it green; and removing the contained write alone leaves every case green because refuseARerun probes the same path first and fails closed. The containment is layered and each layer refuses independently, but a case that names one layer must fail when that layer goes.
- iss-2608311331229368spc-65 and itd-187 both prescribe watching TestAssembledInputIsByteIdenticalAcrossRuns red by removing the assembler's walk sort. Run on a copy of the tree, that mutation does not make it red: removing the sort yields a different but still deterministic order, so two assemblies of one commit stay byte-identical and only the order oracle fires. The mutations that do make the identity assertion red are a genuinely nondeterministic walk (candidates rebuilt from a map) and an absolute repository path embedded in the bundle. The record's prescribed hand-run for ac-1 names a mutation that cannot falsify ac-1.
- iss-2608311331273317internal/core/reading/manifest.go documents that two assemblies of one repository state at one commit produce manifests differing in run_id and in nothing else. Nothing asserts it. spc-65 scopes the manifest to two weaker properties (no timestamp-shaped key or scalar, item paths in lexicographic order) and excludes it from the byte comparison, so a nondeterminism confined to the manifest — a changed content hash, an item recorded at a different field — is invisible to the amnesia eval. The cheap closure is a manifest comparison modulo run_id in the same eval.
- iss-2608311351239562The reading record size cap is still evadable, now through the ledger redactor rather than the escaper. The estimate's 2x factor is exact for the YAML escaper and was verified so, but the redactor is the other lengthening step and it expands past 2x: a network address placeholder is 18 bytes for a 7-byte span, so with a separator the growth is 2.375x and it is proportional to body length rather than bounded by the envelope allowance. A body of 65000 repetitions of a short address, well under the payload cap, is accepted by the size check and lands a 1235410-byte record against a 1048576-byte limit, and that record is permanently unanswerable: the disposition verb refuses it as past the cap. This is the third time this defect has been fixed and the second time a fix modelled one lengthening step and missed the next, which is the signature of an estimate standing in for a measurement. The exact byte count exists in one place, in the ledger ingest after the record text is assembled from already-redacted values and before it is written, and refusing there ends the class rather than moving the threshold again.
- iss-2608311351290623The matching fold drops format runes only, so an invisible MARK still evades the supply-regime gate and, worse, defeats the named-provenance rule unconditionally. The combining grapheme joiner and the variation selectors are general category Mn rather than Cf, and both are designed to render as nothing: a registrative body carrying one inside a keyword renders identically to the registered phrasing and lands with no refusal and no flag, which is the evasion the previous fix states it closed, one category over. The provenance consequence is the serious half. The blankness test trims ASCII whitespace on the raw field, so a pattern consisting of a single zero-width rune is ACCEPTED at all four regimes and the record it writes asserts a provenance it does not carry. That contradicts the criterion's own words, which say an empty or absent pattern refuses the item without exception at any regime, and it contradicts the refusal text in the code beside it. The fix is to widen the drop set to the two adjacent property tables the standard library already ships and to run the blankness test over the folded copy rather than the raw field.
- iss-2608311418202794A stable reversal of the field order within one path changes the assembled bundle's bytes and is caught by nothing: not the cold-reading determinism eval, whose order oracle compares paths only and whose byte comparison sees both runs agree, and not the assembler package's own tests. Five items can share one path when a record is projected field by field, so the ordering of those fields inside a path is a real degree of freedom in the artefact a reading is handed. A map-iterated field order is caught, because it differs across processes and fails the byte comparison; a deterministic but reversed one is not. This is the assembler's property rather than the amnesia eval's, so it belongs to spc-61 and predates the eval that exposed it.
- iss-2608311459220516The read-block eval's coverage matrix does not name six of the assembler's rules, and the omission is worse than the limit the matrix discloses: the rules are absent rather than rewritten, so the declared-gap discipline never engaged on them. Two matter. The file-grain of positive inclusion, the per-row Match list, is named by no row and declared no gap; forcing the match to always succeed leaves the fixture manifests byte-identical and the lane green, and on a corpus holding one unmatched-extension file inside an admitted source it admits two extra items and leaks both tokens. Worse, the redaction verifier -- around 130 lines and six refusal paths, the fail-closed half of the key-and-heading floor -- can have its call DELETED OUTRIGHT with the lane still green. It is falsifiable in principle but not against this corpus: with a setext-underlined excluded heading in a record that travels whole, the shipped binary exits 2 naming the heading and the same binary without the verifier exits 0 with the token in the bundle. Four more mechanisms are green under mutation and unnamed: the section-span same-level rule, the block-scalar continuation drop, the case-insensitivity of the deny segments, and the same-rendering check. The fix is additive, six rows with at least two of them gaps.
- iss-2608311459274099The read-block eval's heading oracle matches ATX headings only, so a setext-underlined or raw-HTML excluded heading arriving in a bundle item would satisfy the field-absence assertion completely. That state is unreachable today, but only because the assembler refuses it through the redaction verifier -- which is itself the mechanism no plant exercises and whose call can be deleted with the lane green. So both sides of one seam rest on a single unfalsified guard: the assembler's refusal is untested by the eval, and the eval's own oracle would not catch what that refusal is keeping out. Neither half is visible from the other, which is why three review rounds over the vacuity of this eval did not surface it and a fidelity audit did.
- iss-2608311501186646The assembled input for a real reading of this repository is about 9.8 MB at every position, roughly 2.45 million tokens, so no reading can be handed one. Measured by running the shipped assembler over the tree at a real commit: widening 9808456 bytes across 951 items, entailment 10156762 across 1297, comparative and detection the same as widening, with the largest single item at 280242 bytes. Field projection works and is not the problem: 104 of the 951 items are projected to a named field and 847 travel whole, so the whole-file rows dominate by two orders of magnitude. The evals cannot see this because they run over a miniature fixture repository of about thirty files, which is the right corpus for asserting a firewall and the wrong one for asserting that the artefact fits anywhere. Nothing in the record states a size budget for the assembled input, and no criterion measures one, so the instrument can be entirely correct and still undeliverable. The instrument has never been run, which is how this survived thirteen intents.
- iss-2608311501240566Three of the four reading positions receive a byte-identical item set. Comparing the manifests of a real assembly at one commit, widening, comparative and detection each carry the same 951 items with the same fields, and only entailment differs, by the 346 draft and planned items the drafts asymmetry admits. That asymmetry is itd-183's and it works exactly as designed. The other three do not. The definitions state four distinct objects: widening reads the brief, glossary, disciplines, specs and shipped tree; comparative reads the candidate set, which is the widening reading's pre-admission output, against the declared selection criteria; detection reads the shipped tree against the claim record. What the assembler actually passes at comparative and at detection is the widening object unchanged. The comparative case is the sharper one, because its object is not a subset of the repository at all but the output of a previous reading, and the assembler has no channel for it -- spc-64 says as much in passing, that the in-cycle candidate set arrives by whatever channel spc-61 defines and the eval makes no claim about it, but nothing states that the position therefore receives the wrong object. No criterion measures cross-position differentiation, and the evals run on a fixture too small for the difference to show.
- iss-2608311502420570The amnesia eval's absolute-path guard is a two-string check rather than a path detector, so it misses the leak class it was added to close. It looks for the two fixture roots by name only. Both roots are created under one temporary parent, and planting that shared parent string in the bundle leaves the whole lane green: the byte comparison cannot see it, because both runs carry the same string and therefore still agree, and the subtest is not looking for it. The two-path design exists precisely because a run-to-run comparison in one directory cannot see an absolute path embedded in the output, and this guard reintroduces that blindness one level up. It is also the repository's own privacy rule at stake, not only determinism: no absolute local path may enter an artefact.
- iss-2608311502474022The amnesia eval's timestamp scan rests on a premise that is already false for paths. spc-65 confines the scan to the manifest on the ground that the manifest carries paths, field names and hashes only, so a timestamp-shaped token there is unambiguously a defect. But the packed-digit rule is an unanchored run of eight or more digits and item paths are scanned as plain scalars, so a manifest naming a record path that carries a long numeric id is reported as a packed run of digits, which is how a moment travels. Fed a path holding a real nineteen-digit capture id, the scan fires. It is latent today because no admitted record family carries such a path, but the justification the scoping decision rests on is wrong now rather than at some future point, and the scan will produce a false finding the first time such a family is admitted.
- iss-2608311504353427The intent-audit ingest does not neutralise markdown link syntax in untrusted verdict text, so a verdict that quotes code containing a bracket-then-parenthesis sequence writes a live markdown link into the committed record and record-lint then refuses the whole tree with a links_resolve blocker. Hit for real: an auditor quoting an assembled-input element path of the form `items[0](itm-0001)` produced a link whose target itm-0001 resolves to nothing, and the gate failed on a record the ingest had just written. The oneLine sanitiser already neutralises the two shapes that matter for spoofing -- newlines, so injected content cannot break out of its line, and HTML comment delimiters, so untrusted text cannot forge a review marker -- and link syntax belongs in the same set for a different reason: not spoofing but a self-inflicted gate failure that no amount of care in the auditor can prevent, because the offending text is a faithful quotation of the code under audit. The repair available today is a hand edit of the rendered line, which is the same accepted repair as the grounds body-lockout.
- iss-2608311517509690The orphan sweep silently deletes committed reading records. With an orphaned stage present and its record already in the ledger, an ingest whose payload fails at the type check deleted a committed record from the durable tier and printed only the type error: the rolled-back and cleared-stage fields are dropped on the error path, and the JSON render emits an error object without them, because the surface renders those fields only when a refusal record exists. The code's own comment says this must not happen. It is the worst shape a defect can take here, because the loss is durable, silent, and triggered by a payload that was itself refused: an operator sees a validation error and has no way to learn that a record was destroyed while it was being reported.
- iss-2608311517547712The provenance field is a signature-free channel through the supply-regime gate. The semantic detectors read the body text only, and the envelope pattern field is excluded from it, so an item whose pattern carries the registry's exact phrasing lands with exit 0 at every regime: a registrative pattern reading that the fix is to rewrite the charter, an explicative one carrying a disposition, an evaluative one recommending a candidate. No byte is substituted and no phrasing is novel; the detector simply does not read that field. By the intent's own test, which puts the registry's own phrasing on the defect side and only novel phrasing on the residue side, this is a defect and a wider one than the confusables class that IS disclosed. It is also the field every item must carry, so the channel is always available.
- iss-2608311518056854The supply-regime registry refuses a reading for quoting the document it read, and the rate is high: fourteen of thirty-four realistic reading outputs were refused, all by one failure mode. The disposition detector matches the bare token followed by a colon or equals, and this repository's records carry that token everywhere, so any explicative claim that quotes a record refuses. So do a claim reporting that a clause settles a licensing question, a claim quoting a paper that closes by recommending further study, a claim reporting that a suite scores below a threshold, and a detection reading that one section says a fix is merged while another says it is pending, which is the canonical shape of a detection finding. This is not the NFKC normalisation, which was measured innocent: an A/B over thirty-four cases flipped five outcomes and every one was the registry's own phrase in compatibility code points, with no innocent case newly refused. The noise predates it and is structural, because the detectors cannot distinguish a reading that PROPOSES from a reading that REPORTS someone else proposing, and the second is most of what a reading legitimately does. The intent records signature noise as its open question, but the disclosed residue names only under-catching; on this evidence over-catching is the larger risk and the residue should say so.
- iss-2608311518109233All three reserved-name tables in the supply-regime gate are mutation-vacuous: emptying any of them leaves the whole package green, because every test iterates the table under test rather than naming what it should contain. No test anywhere pins the literal field names that three acceptance criteria enumerate, so the criteria are satisfied by a gate that would still pass if the names it refuses were deleted. The signature registry has a floor asserting a minimum count; the reserved tables have none. The earlier vacuity sweep on this branch swept code BRANCHES and never data tables, which is why the shape was invisible to it: a guard whose behaviour is driven by a table is only as bound as the table is pinned. Also unpinned by the same reasoning: the per-position body field sets.
- iss-2608311518199679The shipped terminal help for the ingest verb states three things the code does not do, and because the CLI reference page is generated from the command's own long description, the false text is what an operator reads at the terminal and in the docs alike. It says nothing durable is written until the whole payload validates, which the orphan sweep contradicts by deleting a committed record during a refused run. It describes the orphan sweep in wording that omits the committed-tier delete, which is the exact sentence the code's own comment warns must stay true. And it says each regime has reserved names, which is false at the generative position, where there are none and no signature refusal either. A generated page inherits whatever the source string claims, so one wrong sentence in a Long field becomes a wrong sentence in two shipped surfaces at once.
- iss-2608311518250688Three smaller defects in the ingest verb, each cheap and each an instance of a class this workstream has already recorded. A definition-drift refusal returns bare after instrument identity is proven, so the run is refused and no refusal record is written, contradicting both the criterion that says a list-level refusal writes one and the plugin surface's own corrected sentence. The refusal-list elision entry reaches the DURABLE record carrying ordinal zero, so a refused run writes item 0 into its refusal record although there is no item 0; the terminal renderer has the branch that suppresses it and the record writer does not. And the braille pattern blank is accepted as a provenance value: it renders as nothing but is neither a format rune nor a default-ignorable nor a variation selector nor whitespace, so it clears the blankness test. That last one does not breach the criterion's letter, which speaks of an empty or absent field, but it does breach the residue's claim that every invisible rune is folded away.
- iss-2608311621412224The reading assembler's staged_runs line cannot tell a parked run from an ingested one. Describe lists every rdg-* directory under the assembly parking area, and nothing removes that directory after its run is ingested, so a committed run and one no reading has ever been given render identically. The Status doc comment claimed the filter existed until it was corrected; the behaviour did not. An operator reading the bare verb to find out what is outstanding is given a list that grows monotonically and answers a different question. Found while wiring orphaned_ingests, which is a separate field precisely because this one cannot be trusted to mean outstanding.
- iss-2608311632382737The pre-push gate is blind to both eval lanes, so the read-block eval is guarded by nothing that blocks anything. make preflight runs the six lint gates, go build, go vet, go test over the untagged packages and the race lane, and neither make smoke nor make evals-cold-reading; the eval files sit behind a build tag, so the untagged test run does not compile them. A defect in the cold-reading evals therefore passes every local gate and surfaces only in CI. That was not hypothetical: a path-elision defect in the amnesia eval's own guard was unsatisfiable wherever the process temp directory is the Linux one, so it would have landed green locally and red in the merge queue, and it was found by an adversarial review rather than by any gate. Pair this with the CI job not being a required status check and the position is that the eval which certifies the firewall runs in no gate that can stop anything: preflight does not execute it, and the job that does execute it cannot block a merge.
- iss-2608311632439831spc-64's Positions exercised paragraph is stale against the eval it specifies. It says widening, entailment and detection are asserted in full and that at the comparative position the eval asserts only the read-block over the instrument's own stored prior outputs, making no claim about the in-cycle candidate set. The delivered eval asserts every sentinel class at every position, which the first review round required after finding that carving comparative out made an assembler leak at that one position invisible. The spec therefore understates its own delivery, and understating is not harmless here: a reader deciding what the eval covers would conclude that a comparative-only leak goes unnoticed, which is exactly the defect the round closed.
- iss-2608311725218136The ingest verb's payload flag is named for its role rather than its content, breaking the house idiom its four siblings follow and colliding with the global rendering flag. The repository's output-contract pattern names the flag after what the JSON CONTAINS: review-json, verdict-json twice, changelog-json. This one is output-json, which names the role instead, and role is exactly the ambiguous axis here because the global json flag means the opposite direction of travel: one is how abcd renders its own result, the other is a path to what an agent returned. The verb's own example shows both on one line, which is where a reader trips. Renaming it to reading-json makes it unambiguous about whose output it is and consistent with the four siblings. The window is now: the verb shipped today and has no users, so the change costs a flag rename and a page regeneration, and the cost rises the moment anything scripts against it.
- iss-2608311949385350The assembler version pin is advisory, not mechanical: TestAssemblerVersionCoversTheIncludeTable compares sha256 of the rendered include table to a standalone literal digest and never reads AssemblerVersion, so changing the table and updating only the literal is green with the version unmoved
- iss-2608311949421873The include table match grammar disagrees with itself on case for no stated reason: an extension entry is compared with strings.EqualFold while an exact basename entry is compared with ==, so .MD matches but makefile does not match Makefile, and whoever adds a fourth match form has no rule to follow
- iss-2608312019544150prefixDenied in the reading assembler compares case-sensitively while segmentDenied folds case, and deny.go's own header comment claims the deny binds every path component case-insensitively, so the comment is wrong about the boundary it documents
- iss-2608312019547974The cold-reading eval coverage matrix has no row for the MatchSuffix match form and no row asserting a manifest item's kind names its actual material class, so the per-item kind attestation added by itd-198 has no falsifier behind it
- iss-2608312058244357The scope carried in the cold-reading bundle serialised a preset's path selectors verbatim, so a repository path reached the reading's own working set and breached brief invariant 15's pathless-bundle rule; the manifest may carry paths and the bundle may not, and one Scope type was being written to both
- iss-2609010759382400The reading CLI surface test fixture commits without pinning a git identity, relying on an ambient system-level user.name/user.email that a CI runner does not have, so eleven tests fail with 'Author identity unknown' on CI while passing on any developer machine; gittest.Env deliberately does not pin an identity and its doc says callers must supply their own, which lint_surface_test.go does and reading_surface_test.go does not
- iss-2609010818066790The reading assembler test's tree walk lstats every path it enumerates without tolerating ENOENT, so a transient file under .git - git's background maintenance.lock - that exists at enumeration and is gone by the stat fails the test; it flaked TestAssembleDryRunWritesNothing on the macOS CI leg and is a time-of-check race any concurrent git activity can trigger
- iss-2609011026401952The implement loop has no step that ships an intent once its work merges: abcd intent plan moves drafts to planned and abcd spec close moves planned to shipped, but nothing in the build-review-merge routine invokes the second, so an intent whose code is on main sits in planned indefinitely and launch ship composes the changelog only from terminal folders. Two intents delivering a BREAKING CLI change were about to be released with no changelog line, and the omission is invisible because the cut exits 0 - a planned intent is not a refusal, it is simply not seen
- iss-2609011207114761The changelog composer cannot see the previous release surface, so its `Changed`
- iss-2609011217083577The prose scrubber neutralises angle brackets inside code spans, so a documented
- iss-2609011423385217The release-gate manifest's pinned inputs are stale and under-scope the record
- iss-2609011424033149v0.7.0 ships a verb and four agents the brief does not document anywhere
- iss-2609011424033603the brief's surface prose has drifted from the shipped binary in twenty-one places the machine-checked layer cannot see
- iss-2609011424113262The brief's surface prose has drifted from the shipped binary in twenty-one
- iss-2609011424116881v0.7.0 ships a verb and four agents the brief does not document anywhere. These
- iss-2609012000222546abcd update refuses to replace the very binary that is running it when that binary's release no longer exists on the forge, and its remedy sends the user to remove the file, which removes the only tool that could reinstall. Observed 2026-09-01: ~/.local/bin/abcd was v0.6.6 (byte-identical to the plugin-cache binary the bootstrap provisioned); abcd update resolved v0.7.0, then refused with shape unprovenanced-file because the file's digest appears in no published checksums.txt. The 2026-08-30 decision deleted every release object older than v0.6.9 and notes that v0.6.0-v0.6.6 never had one, and it claims removing old assets affects only a deliberate pin; that is wrong for abcd update, whose ownership proof (spc-32, the OWNED BY PROVENANCE row) walks exactly those deleted manifests, so every v0.6.7, v0.6.8 and plugin-provisioned install now refuses the same way. The remedy text ('remove it and reinstall') names no reinstall command, and once the file is removed the update verb cannot run at all; the user was left with no abcd and recovered only by the README one-liner. Two directions, neither adopted: (1) when the target resolves to the running executable itself (os.Executable after symlink resolution, os.SameFile), the file is abcd by construction and cannot be a foreign binary, so provenance should only derive the old version, reporting it as an unpublished build with its digest and proceeding after the existing TTY confirmation; (2) at minimum the refusal remedy carries the reinstall one-liner or the docs path and states that update cannot run once the file is gone. Part of the ease-of-update design work: users must be able to move the CLI and the plugin route forward without a dead end.
- iss-2609012020476120Four test sites now assert elapsed wall-clock time where they mean to assert behaviour: iss-2608292246210181 and iss-2608290810037763 in the scanner's adjacency tests, iss-2608301301041887 in the grounds lock test, and the bootstrap fresh-install self-check in internal/surface/cli. Each was found by a CI flake and each is being fixed site by site. Worth deciding whether the rule 'a test asserts behaviour or an operation count, never a duration' graduates to a principle under .abcd/development/principles/ or to a lint rule that refuses a time.Since comparison in a _test.go file, so the fifth site is refused at draft time rather than found by the next flake. This is a design decision and was not taken during autonomous-run-2026-09-01, where it was carried from the session handover; the fourth site was fixed on its own merits.
- iss-2609012020479351TestBootstrapFreshInstallSelfCheck in internal/surface/cli asserts wall-clock time: it wraps one exec of the provisioned binary answering version in a timer and fails when elapsed exceeds five seconds. It failed on the macOS CI leg after v0.7.0 merged (run 33496438371: 5.77s, 'want about a second') on a tree the merge-queue leg had just passed; locally the same test passes in about one second. The timer measures a single process spawn of an ~18MB freshly written executable, which on macOS carries first-run code-signature validation against a cold page cache, so the number is a property of the runner, not of the code. The test's own comment names the budget as loosened 'so a loaded CI box cannot fail a check about provisioning on a timing wobble', and it then did exactly that. Fourth site of the class recorded by iss-2608292246210181, iss-2608301301041887 and iss-2608290810037763; carried from the session handover into autonomous-run-2026-09-01. The fix must assert the behaviour the gate is about -- the provisioned binary answers version correctly, as the version report, with no Go on PATH -- and carry no duration at all.
- iss-2609012020521049checkReceiptGate enforces judgeModel non-empty but not the documented pinned-snapshot rule. The release-gate runbook, receipt.example.json and the iss-35 plan all state that a receipt's judgeModel is a pinned model snapshot, never a floating alias, yet checkReceiptGate (internal/core/lint/lint.go) refuses only a blank judgeModel: a receipt carrying a bare family name such as opus or an alias such as claude-opus-latest passes the gate, so the auditability the runbook promises is carried by the receipt author's honesty alone. The v0.7.0 receipts record this gap in their _reviewProvenance. The fix must refuse a judgeModel that carries no version or date component or that names a floating alias, with a test, while leaving every committed receipt (all of which carry a family plus version id) valid.
- iss-2609012023256534RS001 in scripts/check-issue-resolution.sh cannot tell a stale branch from a forgotten resolution, and its message diagnoses the wrong one. On a branch 235 commits behind origin/main the pre-push preflight emitted 84 RS001 violations, every one instructing the reader to resolve an issue that already sat in a terminal folder at the base: the branch's own commits had been squash- or rebase-merged, so origin/main held the moved records, the two-dot diff of the two trees showed no record entering resolved/ or wontfix/, and the trailers went unsatisfied within the range. No line of the output said the branch was behind, and the one remedy that works, a rebase, appeared nowhere. The gate should distinguish the shapes it can prove: a record already terminal at the base ref (with how far behind the head is and which base-side commit placed it there), a record absent from the head tree while the base holds it, and an id with no record anywhere, and name a rebase as the likely remedy where the evidence points to one. Carried from the session handover into autonomous-run-2026-09-01.
- iss-2609012028144617In a source checkout of abcd itself, the plugin-root binary and any abcd on PATH are the last published version, so they are stale by construction and fall further behind with every commit, and the failure is not always a refusal. Three hits in one session while cutting v0.7.0: launch ship refused on its surface guard, correctly and loudly; changelog --json returned an empty cut against a tree with 181 shipped records, no error, a plausible wrong answer briefly read as evidence about the release; and capture would have written records through a schema that predates the origin and production_mode disclosure pair the record gates now require. The plugin skill pages document a resolution ladder that reaches the plugin binary first and falls through to go run ./cmd/abcd only when nothing earlier resolves, and in this checkout the first rung exists and answers, so the fallback written for exactly this case is unreachable by following the ladder literally. The convention every agent in this repository needs is that every abcd invocation here is go run ./cmd/abcd from the repo root; it belongs in the committed record, in AGENTS.md and as a loader domain that fires on prompts naming an abcd verb, rather than in a per-machine handover note. Carried from the session handover into autonomous-run-2026-09-01; the skill pages' resolution order is the other half and stays with iss-2608230943088357.
- iss-2609012029335717GHSA-5qr6-f78x-g2cx (CWE-312): the memory store redacts only the PEM BEGIN header and stores the key body. memory.storeRedactor.redactText scans with the header-only pem_private_key pattern, scanner.Redact masks that one span, and the stage-two BlockingResidual rescan re-runs the same rule over a fingerprinted header and is clean by construction; a text source with a key block lands in the page body and in the --keep-original copy (redactOriginalBytes) with body and END line verbatim. Evidence: memory/redact.go redactText and redactOriginalBytes. The fix is the shared block consumer in scanner.Redact so memory, history and capture cannot drift; the page body and the kept original must carry no body line.
- iss-2609012029335752GHSA-29jw-3jg9-qmhx (CWE-312): the issue-ledger capture redacts only the PEM private-key BEGIN header and commits the key body. The bundled pem_private_key pattern (scanner.DefaultPatterns) matches the header line alone and scanner.Redact seals matched spans per line, so a pasted key block reaches the committed record with its base64 body and END line verbatim while the JSON reports redacted 1; the slug is derived after redaction, so the body prefix becomes the filename, a one-line key in a capture resolve note leaks the same way, and capture promote inherits the body-prefixed slug into the minted intent. Evidence: capture.redactLedgerText, workflow.go deriveSlug, promote.go. The fix must extend redaction over the body through the END line in the shared primitive, bounded so a truncated block cannot swallow the record, mask the span whole, and leave body, END, filename, note and promoted intent free of key bytes.
- iss-2609012029341137GHSA-gxhr-pmwv-r99p (CWE-359): memory identity redaction follows the repo git identity, not the caller. memory.newStoreRedactor builds scanner.New(repoRoot) whose ProbeIdentity reads the single effective user.name and user.email, so with a work persona in the repo the caller global identity is stored verbatim in the page body and the kept original. Evidence: memory/redact.go newStoreRedactor, scanner.ProbeIdentity. One fix in the probe (union of every configured scope) covers the memory, history and capture stores; neither identity may survive in any store write.
- iss-2609012029342529GHSA-rvhr-3455-c5jw (CWE-359): the issue-ledger identity redaction keys on the repo effective git identity and commits the caller other identity in clear text. scanner.ProbeIdentity runs git config --get for user.name and user.email under -C repoRoot, the single last-wins value, so a repo-local persona or a global includeIf persona replaces the global identity in the matcher set; a capture naming both identities redacts the persona and commits the personal address and name, and the post-redaction slug carries the mailbox into the filename while the CLI notice says identifiers are never committed. Evidence: scanner.ProbeIdentity, capture.redactLedgerText, workflow.go deriveSlug. The fix must union every scope git resolves (git config --get-all, includes evaluated) so a persona adds an identity and never displaces one; body and filename must carry neither identity.
- iss-2609012029342817GHSA-v826-5jf4-p8xg (CWE-359): transcript identity redaction is keyed on the repo effective git identity, storing the caller other git identity in clear text. history.Capture uses scanner.New(repoRoot), whose ProbeIdentity resolves one user.name and user.email under -C repoRoot with global config in effect (gitutil.ScrubbedEnv); git last-wins resolution means a repo-local or includeIf persona replaces the unconditional global identity, so a transcript carrying both stores the personal one verbatim with the frontmatter reporting no identity redaction. Evidence: scanner.ProbeIdentity, history.Capture. The fix must union the effective identity with every other value git resolves for the key (git config --get-all), keeping the persona redacted and redacting the global identity too.
- iss-2609012029343438Transcript records are written world-readable: history.Capture writes each redacted record with mode 0644 into a transcripts chain ahoy creates 0755 (apply.go), while the unredacted staging tier is 0700/0600 by stated design. Noted by GHSA-gmp7-9rvm-qcr3 as the amplifier of the PEM leak, it is a separate question from the redaction defect: whether a redacted transcript store under the caller home should be private to the account (records 0600 and the chain 0700) or is meant to be readable by other local accounts. No ADR or decision records the choice, the tightening spans the ahoy-owned directory chain, and no consumer is known to rely on a world-readable store. Fork to decide: tighten both (one mode change in history plus one in ahoy, with a test on the resulting mode) or record the world-readable posture as deliberate.
- iss-2609012029344995GHSA-gmp7-9rvm-qcr3 (CWE-312): the transcript store redacts only the PEM BEGIN header and stores the key body verbatim. history.Capture stage one scans with the header-only pem_private_key pattern and scanner.Redact seals the header span alone; stage two rescans with the same detector, the fingerprinted header no longer matches, and the write proceeds with every body line and the END line in the record while the frontmatter counts one secret. Header and body on one line leak the same way because byte-span sealing stops at the header. Evidence: history.Capture, scanner.DefaultPatterns pem_private_key, scanner.Redact. The fix must consume the body through the END line in the shared primitive with a bound, mask the span whole, and keep the prose after the block; the record mode (0644) is a separate observation.
- iss-2609012035100572GHSA-xq36-hcgf-9wrj (CWE-693): transcript staging is unlocked and content-blind. history.Stage dedups on the session id alone, so a second SessionEnd for one session carrying different bytes is a no-op, and the drain then stores the stale copy and deletes the only copy of the newer transcript; and Stage takes no lock, so two concurrent SessionEnds for one session id both pass the listing check, write two .raw files, and Drain stores two records claiming the same session. Evidence: internal/core/history/staging.go Stage (the session-id-only loop and its no-lock doc comment), stagedFilename's nanosecond stamp, Drain's unlocked list-capture-remove; TestStageIsIdempotentPerSession pins the defect. The fix must establish: the stage handshake is exclusive (fsutil.WithFileLock on staging/.lock around list, content compare and write), identical bytes are a no-op, different bytes replace the staged copy at the existing path (last-writer-wins, the fresher end-of-session bytes being the ones worth keeping) with a Replaced signal the session-end hook reports instead of no-op, and Drain removes a staged file only if it still holds the bytes it captured, leaving a mid-drain replacement for the next pass.
- iss-2609012035110990GHSA-j7v5-q7x6-v3rp (CWE-354, CWE-391): the armed gitleaks augmentation silently drops multi-line and non-verbatim findings. gitleaks.toFindings skips any reported value containing a newline (its doc comment claims a PEM body is native-covered, but the native pem_private_key pattern matches the BEGIN header only) and falls back from Secret to Match only when Secret is empty, never when Secret is absent from the text, so a report that locates nothing yields no finding and no error; Augment returns zero findings on a non-empty report without erroring; and history.Capture's stage two re-scans the redacted text with the native detector only, so an augmented span can never enter BlockingResidual and the record's frontmatter counts findings the redactor never applied. The fix must establish: the needle is located on the whole text and split into one finding per line it crosses, Match is tried when Secret is not verbatim, a report that yields no finding returns gitleaks.ErrFindingNotLocated which Capture refuses the write on, and Capture verifies every augmented finding's span is sealed in the redacted text and returns RedactionResidualError on any survivor. Rejected alternative: re-running gitleaks over the redacted text doubles a 30s-timeout subprocess and is not deterministic across rule sets. Sibling out of scope: internal/core/memory/redact.go redactText is native-only on both stages with no gitleaks augmentation, so it is unaffected. Consequence: an armed repo whose rule reports something absent from the transcript now refuses the capture loudly; the remedy is the rule or enabled:false.
- iss-2609012035113186GHSA-g2v7-wfmv-v28r (CWE-693): launch's structural deny was applied to the first path segment only, so a nested or case-varied denied namespace could enter the release payload. Fixed before this run by 30f62e82 (fix(launch): close nested/case-fold deny bypass and unscanned-payload gap), shipped in v0.6.7; the class record is resolved/iss-2608270735428304 (GitHub mirror #335), which does not name the GHSA id. This record binds the advisory id to its fixing commit so an advisory-keyed search hits. Evidence at v0.7.0: internal/core/launch/bundle.go segmentDenied and pathContainsDeniedSegment; tests TestNestedDeniedNamespaceExcluded and TestCaseFoldDeniedNamespaceExcluded in bundle_denyseg_test.go.
- iss-2609012035115696GHSA-5mmm-3whv-3rqp (CWE-693): launch copied skip-listed payload files (.svg among them) into the bundle unscanned, so a secret in a skip-listed file passed every gate. Fixed before this run by 30f62e82 (.svg removed from the default skip set and wouldRefuseOn failing closed on Unscanned; v0.6.7), deepened by 1f71e608 (every skip-listed file byte-scanned; v0.6.9) and 95b98abc (explicit byte-rule table); the class record is resolved/iss-2608291807454357 (GHSA-9wv7-88w3-f77m, the same skip-by-name mechanism), whose fixing commit names this advisory as precedent. This record binds the advisory id to its fixing commits so an advisory-keyed search hits. Evidence at v0.7.0: internal/core/launch/dryrun.go scanRefusals and internal/adapter/scanner/scanner.go ScanBundle; tests TestSvgPayloadSecretRefuses, TestUnscannedPayloadRefuses, TestUnscannedRefusalCarriesWhy and TestBinaryPayloadSecretRefuses in scan_coverage_test.go.
- iss-2609012036271396GHSA-fh9j-8xmg-m33f (CWE-59, CWE-400): the issue-ledger readers scanLedger (workflow.go) and readWithChecksum (roots.go) load every well-formed iss-N-*.md through a bare os.ReadFile, with no O_NOFOLLOW, no O_NONBLOCK, no regular-file check and no byte cap, and List/Status never pass mutationPreamble so the write path's leaf guards never run on a read. In a hostile clone a committed FIFO at a record name hangs capture list and the bare capture status render, an oversize record is read and serialized unbounded, and a committed symlink to an out-of-tree schema-shaped file has its body (any secret span included) serialized into list --json, with no redactor on the read path. The package already owns the hardened reader (reading.go readRecordGuarded, fsutil.ReadGuarded under issueschema.RecordReadLimit) and the reading family uses it everywhere; the issue family was never swept. The fix must route both readers through it so a FIFO, device, symlink or oversize leaf becomes a SkipRecord the surfaces already render, and Promote, transition and commitCapture inherit the guard through readWithChecksum. Sibling unguarded reads outside this package are captured as their own records.
- iss-2609012037119454GHSA-865x-5m7q-qm79 (CWE-59): ensureLedgerDirs (alloc.go) provisions the ledger with os.MkdirAll(filepath.Dir(issuesRoot)), which follows every ancestor, and only then Lstat-checks the leaves through safeMkdirLeaf; resolveRoots (roots.go) derives issuesRoot with filepath.Abs alone and checks no ancestor. A committed mode-120000 symlink at .abcd or .abcd/work therefore redirects the whole store — issues/, the .iss-alloc.lock flock, the three status directories and the record — to the symlink target outside the checkout, while the result still reports the repo-relative path; and because List and Status walk the same issuesRoot, every read serializes an out-of-tree ledger too. The fix must establish that every segment from repoRoot down to Dir(issuesRoot) is a real directory (a per-segment Lstat walk, created one level at a time with os.Mkdir, modelled on memory.memoryDir from the GHSA-72rp fix), placed where every verb passes first so the readers are covered, and keep the leaf guards; a custom IssuesRoot outside the repo is an operator-typed operand and keeps leaf-only behaviour. Test: .abcd/work symlinked out of tree, capture refuses with ErrPathUnsafe and nothing is written in the target.
- iss-2609012037122078GHSA-cxmf-gw6r-2pf5 (CWE-20, CWE-696): Promote's pre-flight (promote.go) reads the source issue and checks only promoted_to before intent.CreateDraft; validateStrict and validateInvariants run only inside the stamp closure, under the lock, after the draft is minted. A record that is malformed by the package's own invariants — a frontmatter slug that is kebab-valid but disagrees with the filename slug, or an enum value outside the schema, both of which list and record-lint already reject — is therefore minted from anyway: a draft carrying the attacker-chosen slug and a promoted_from back-edge lands in the committed intents/drafts store, the stamp fails on the invariant, the orphan-draft remedy fails on the identical invariant, and every rerun mints one more orphan. Promote's own doc comment (written by ab79b54d for the grounds-append limb) already states that every refusal decidable from the pre-flight bytes is raised before the mint. The fix must run validateStrict and validateInvariants in the pre-flight, keeping the status findIssue returns, so an invalid record produces an error and nothing else; the stamp-step checks stay for what only the under-lock bytes can show. promoteReadingItem already validates before minting.
- iss-2609012037125129Sibling of GHSA-fh9j-8xmg-m33f (CWE-59, CWE-400), found on the sweep and not fixed there: glossary readTerm (internal/core/glossary/index.go) loads every term file the index walk finds through a bare os.ReadFile — no O_NOFOLLOW, no O_NONBLOCK, no regular-file check, no byte cap. The glossary store is committed and travels with a clone, so a committed FIFO at a term name hangs every verb that builds the index, and a committed symlink reads an out-of-tree file as a term. The fix is the same one-line routing through fsutil.ReadGuarded that the issue and reading families now use, plus a byte cap chosen for the term family (the glossary has no cap constant of its own yet, which is the one decision that kept this out of the advisory fix) and a test with a FIFO and a symlinked leaf in the term store. Already-captured siblings are iss-2608301203521317 (lint scanRecordStores) and iss-2608211914592726 (the residual lint sweep).
- iss-2609012037127981Sibling of GHSA-fh9j-8xmg-m33f (CWE-59, CWE-400), found on the sweep and not fixed there: checkReceiptGate (internal/core/lint/lint.go) reads each review receipt under .abcd/work/reviews/<sha>/<gate>.json and the release-gate manifest through a bare os.ReadFile — no O_NOFOLLOW, no O_NONBLOCK, no regular-file check, no byte cap. The reviews store is committed and travels with a clone, so a committed FIFO at a receipt path hangs abcd lint (and make preflight through it), and a committed symlink is judged as if it were a receipt. The fix is the routing through fsutil.ReadGuarded that lint's readingoutstanding.go already uses for the reading family, with a cap for the receipt shape, and a test with a FIFO and a symlinked receipt. Distinct from iss-2609011423385217 (the manifest's stale pinned inputs) and from the record-store sweep records iss-2608301203521317 and iss-2608211914592726, which do not name the reviews store.
- iss-2609012037130181The orphan-draft error Promote returns after a failed stamp (internal/core/capture/promote.go) names the repair as abcd capture promote <iss-N> --intent <itd-N>, without --grounds. The issue route requires --grounds — the CLI refuses with exit 2 (requires --grounds ... nothing written) before it reaches the stamp, and core's requireGrounds refuses the same way — so the documented repair fails on its own text for every orphan, not only the one the advisory produced. TestPromoteStampFailureReportsOrphanAndLinkRepairs passes Grounds to the repair call the message never mentions, which is why it never noticed. The remedy must print a command that runs as printed: the same --intent plus the promotion's own grounds, quoted for a shell, and a test that extracts the remedy from the error and runs it. The reading-item route is unaffected: it refuses grounds, so its remedy is correct without them.
- iss-2609012037137250Sibling of GHSA-865x-5m7q-qm79 (CWE-59), found on the sweep and not fixed there: intent ensureRealDir (internal/core/intent/lifecycle.go) and spec ensureDir (internal/core/spec/store.go) refuse a symlinked LEAF directory and then os.MkdirAll the path, so a committed symlink at an ancestor (.abcd, .abcd/development, or intents/ and specs/ themselves) redirects the store create and every subsequent write — including the draft that capture promote mints through intent.CreateDraft — outside the checkout. Both functions carry a NOTE naming this as a low-severity follow-up under the trusted-worktree model; that model exists only in those comments and a research note, not in an ADR, and the same class is already ruled in scope for memory (ad2f1a8e), ahoy (81f81f67) and now the issue ledger. The fix is the per-segment Lstat walk from repoRoot that memory.memoryDir and the capture ledger use, one level at a time with os.Mkdir, with a test per store that symlinks .abcd/development out of tree and asserts a refusal and an empty target. Record-store containment as a structural rule is iss-2608301308367566; this record names the two create sites that rule would close.
- iss-2609012037143368The capture package's ledger writes are absolute-path operations — createPlaceholder through syscall.Open, the .iss-alloc.lock flock path, fsutil.WriteFileAtomicPreserveMode for the commit and the stamps, os.Mkdir for the directories — each guarded by its own Lstat or O_NOFOLLOW check. The GHSA-865x fix adds a per-segment ancestor walk, which closes the committed-symlink case but leaves the lstat-to-mkdir window a local racer could use, the same window memory.memoryDir accepts. The durable closure is os.Root: fsutil already carries CreateExclusiveIn, WriteFileAtomicInRoot and ReadGuardedInRoot for exactly this class, and a store opened once as a root cannot be redirected between a check and a write. Converting the capture store to it is a package-wide refactor of every write site and the lock path, not a one-site fix, and it is the shape a structural record-store containment rule (iss-2608301308367566) would want every store to take. Recorded as the follow-up the advisory fix does not attempt.
- iss-2609012037425074GHSA-4fmm-95pf-32c6 (CWE-150): on an empty store, Ask returns RenderNoMatches(req.Question) with the question raw, while RenderCitedMatches sanitises it, and both return paths put req.Question raw into AskResult.Question (the --json field), so ESC, C1, bidi-override and zero-width runes in the argv reach stdout (reproduced at v0.7.0: two raw ESC bytes and a raw U+202E on stdout). The fix must sanitise the question once in Ask through termsafe.Sanitize and feed that one value to both renders and the JSON field, pinned by a test that plants ESC and U+202E and proves neither survives in the answer or the question field.
- iss-2609012037430191GHSA-xj89-cc2c-wgwr (CWE-313): memory lint (memoryLinter.run is source classes + licence + quotation) imports no scanner, so a page whose frontmatter or body already holds a PAT or a home path yields zero findings and a clean exit, and fileBackSource deep-copies citation and licence from every matched page onto the file-back page, so a contaminated store propagates itself on ask --file-back (reproduced at v0.7.0: lint --json reports one MS001 info and blockers 0 over a page carrying a PAT in citation.title, recall and the body). The fix must add a blocker-severity MR001 finding built from the store redactor (BlockingResidual over the scan plus the literal-home backstop) over every stored page, .sources_index.json and each text kept-original under sources/ — report, never mutate, per adr-13 — carrying the kind and the line but never the span in the message or the report files, emitting a blocker MR001 naming the store when the scanner is degraded rather than aborting, and the file-back clone must land redacted through the frontmatter walk.
- iss-2609012037432966GHSA-x46m-mw9h-5jwj (CWE-312): WritePages redacts only PageWrite.Body; the frontmatter is dumped verbatim by renderWrites, so host-supplied recall, contradicts, citation scalars, sources[].licence and weighting_note land in the committed store unscanned, and the core-copied licence (DetectLicence from an SPDX line or a License: header), the redirect-controlled origin and title (materialFromFetched FinalURL, query string included) and every registry placement (the MergeIngest fresh entry and its fill-if-empty origin, backlinkOtherHashes, the ask --file-back event) reach .sources_index.json, contradictions.md and the ingest --json and ask --json results raw (reproduced at v0.7.0: a PAT in an SPDX header is returned in licence and stored three times in the page and once in the registry). Strict superset of iss-2608291941064448, which names host frontmatter through WritePages only. The fix must walk every string leaf a write introduces — the page frontmatter in WritePages and the registry leaves the merge adds, never the cached ones, so a dirty cached citation cannot lock a re-ingest out — through the store redactor with the same fail-closed discipline as the body (redact, sweep the home, refuse only a BlockingResidual), redact licence, citation and title at the source in Ingest so the returned result matches what was written, and build the redactor on the registry-only fast path too, where today none is built.
- iss-2609012037433158GHSA-35fj-9w6f-7h62 (CWE-319, CWE-311): isURL admits http as well as https and acquireSource fetches either, and the CheckRedirect of defaultFetch re-checks only the redirect count and the SSRF host guard, so a hop from https to plaintext http is followed — whereas update.go newUpdater refuses a redirect that left https. A man-in-the-middle on a plaintext source can rewrite its text and plant a License: header the store copies into provenance. The fix must refuse a non-https source in acquireSource before any fetcher runs, with a refusal that names the scheme, pin the scheme per hop in the redirect policy the way abcd update does, and move the http:// test fixtures (TestIngestRefusesSSRFTargets, TestIngestEncodesHiddenRunesInFetchedOrigin) to https:// so the SSRF guard stays the thing under test rather than passing on the scheme refusal.
- iss-2609012037438844cli.go scrubPaths — the error surface cli.Run prints for every verb — redacts the cwd, the home and the paths embedded in a PathError but applies no termsafe.Sanitize, so an error message that echoes an operand (acquireSource fetch failed for %s with the raw URL, and every other verb whose error text quotes user or repository content) can carry ESC, C1 and bidi runes to stderr raw. Repo-wide, all verbs; found while fixing GHSA-4fmm-95pf-32c6 and deliberately not fixed there. A fix would sanitise once at the print site and pin it with an ESC-bearing operand.
- iss-2609012037440084The docs cite refresh fetcher in cite/fetch.go re-guards the host per redirect hop through urlguard.CheckHostWith but pins no scheme, so an https link that redirects to plaintext http is followed — the same shape GHSA-35fj-9w6f-7h62 closes in memory ingest. It fetches documented links for liveness and stores no content, so it sits outside that advisory and is recorded here instead of fixed. A fix would refuse a hop whose URL scheme is not https before the host guard, as update.go and memory ingest do.
- iss-2609012037443635GHSA-35fj-9w6f-7h62, the admission alternative not taken: memory ingest now admits https sources only, with no escape — the posture of abcd update and of invariant 12 in the brief. The advisory proposed an additive --allow-http flag instead (https by default, explicit opt-in for a consumer that needs a plaintext source such as an internal mirror or a local test server), wired on the CLI, commands/memory.md and the reference page. Left open as the fork: a consumer that needs plaintext has no route today; adding one is additive, and needs a decision on whether the flag also relaxes the per-hop scheme pin or only the admission.
- iss-2609012039102035GHSA-qc3w-8pv5-crc3 (CWE-312, advisory severity low): the origin remote URL is stored verbatim, credentials included. `internal/core/ahoy/store.go:originURL` returns `git remote get-url origin` trimmed and `deriveIdentity` places it in `RepoIdentity.Github`; `apply.go:stepHistory` persists it into `~/.abcd/history/<sha>/meta.json` and `registerRepo` into `~/.abcd/history/index.json` (new files 0644 through `fsutil.WriteFileAtomicPreserveMode`), and `abcd ahoy --json`, `abcd ahoy dry-run` and `abcd ahoy doctor --json` echo it. A remote of the form `https://user:token@github.com/owner/repo.git` therefore lands a credential at rest in two files and on stdout. Reproduced at v0.7.0 with a placeholder token. The fix must scrub userinfo at the one derivation site (`originURL`) so nothing downstream ever sees it — index.json, meta.json and the three JSON surfaces inherit the scrub, and `registerRepo`'s refresh self-heals a legacy credentialed entry on the next install — proven by a test that installs into an isolated home with a placeholder credential and finds it in neither file. Sibling readers: `remote.go:resolveGitHubRepo` shares `originURL` and today refuses a credentialed URL as "not a github.com URL"; after the scrub it accepts it, which is benign. `internal/adapter/scanner/identity.go:ProbeIdentity` keeps only the owner segment; not a sink.
- iss-2609012039102703GHSA-mchq-gm34-3j34 (CWE-754, advisory severity low): `ahoy install` rebuilds an unparseable `.abcd/config.json` that `stepConfigValues` refused to touch. `internal/core/ahoy/apply.go:stepVersionStamp` discards `readConfig`'s error, treats the nil map as empty and republishes a meta-only file through `writeConfig`; `detect.go:detectVersion` discards the same error, so a malformed file raises `install_meta.missing`, which `--yes` arms. `stepConfigValues` refuses correctly (`loadPersistedInstallConfig` ok=false) but silently, so the run ends "partial" with `config.*_missing` remaining and no note naming the malformed file, and `stepVisibility` is skipped so the .gitignore fence is never reconciled. Reproduced at v0.7.0 with a merge-conflicted config: `repo.visibility` (the disclosure fence) and `scan.native_secret_scanning` (the remote-apply opt-out) were gone afterwards. The fix must establish that a config that cannot be parsed is never rewritten by any install step, that detection raises one non-resolvable `config.malformed` diagnostic instead of arming the stamp, and that a partial install says why in its notes — the regression test drives a merge-conflicted config through `install --yes` and asserts the file is byte-identical afterwards. Distinct from iss-127 (concurrent config RMW).
- iss-2609012039102770GHSA-4q78-ccfv-f374 (CWE-345, advisory severity low): the owned PATH-copy verification is self-referential under an env-supplied CLAUDE_PLUGIN_DATA. `internal/core/ahoy/data_dir.go:pluginDataDir` is `os.Getenv("CLAUDE_PLUGIN_DATA")` and nothing else; `owned_copy.go:cacheRecordedSHA` reads `binary_sha256` from a `binary-meta` beside the artefact under that same directory; `apply.go:installOwnedEntry` hashes the artefact, compares it to that record, writes the bytes 0755 as the owned PATH entry and records provenance in `~/.abcd/path-entry`. The bootstrap's manifest authentication (`hooks/bootstrap.sh`, cache_trust=manifest, iss-2608210934566228) covers only the cache-to-plugin-root promotion; the cache-to-PATH promotion re-verifies against the co-located record only, which an attacker who writes both satisfies trivially — adr-46 decision 3 states exactly this principle for the bootstrap. Reproduced at v0.7.0: with CLAUDE_PLUGIN_DATA and ABCD_PLUGIN_ROOT pointed at attacker-chosen directories, `ahoy install --yes --adopt` installed a one-byte file as `~/.local/bin/abcd`, recorded its hash and the fake plugin root in path-entry, and `classifyBinTarget` then vouched for it as an owned copy.
- iss-2609012039103376GHSA-m8pg-chhv-hxvq (CWE-200, advisory severity low): `ahoy doctor --json` leaks absolute home paths in the `history.path_stale` gap. `internal/core/ahoy/apply.go:auditGaps` composes the gap's Detail from two raw absolute paths — `entry.Path` from `~/.abcd/history/index.json` and `filepath.Abs(cwd)` — while every other path-bearing gap in the package (`detectPathSymlink`, `detectShadowedEntry`, `detectBinDirOnPath`) routes through `displayPath` (`fsutil.RedactHome`) precisely so a gap pasted into an issue carries no username. Text-mode doctor prints counts only; `--json` encodes the whole DoctorReport raw. Reproduced at v0.7.0 (8f68ffb3): register a repo, move it, `ahoy doctor --json` prints both paths in full. The fix must establish that both paths render through `displayPath` and that doctor's JSON output carries no home prefix; a foreign machine's home in `entry.Path` (a different username in a cross-machine registry) is not this advisory's scope.
- iss-2609012039107700GHSA-gx3m-3224-qqcv (CWE-426, advisory severity medium): the hook shims' PATH fallback executes an unverified `abcd` as the guard and rules loader. In `hooks/hooks.json`, UserPromptSubmit, PreToolUse and PreCompact carry `if [ -z "$g" ] && command -v abcd; then g=abcd; fi` and SessionEnd `exec abcd hook session-end` when the plugin-root binary is missing; PreToolUse's fence passes exit 0/1/2 through, so a foreign binary exiting 0 approves every shell command. SessionStart has no PATH rung and fails closed. Reproduced at v0.7.0 with the shipped PreToolUse command, a failing bootstrap and a hijack directory first on PATH: the planted binary received `guard hook` plus the tool input and its exit 0 was accepted as armed. The rung was introduced by iss-254 (20968bdf, v0.5.1), is pinned as desired behaviour by `internal/surface/cli/hooks_selfprovision_test.go:TestBinaryHooksFallBackToAPathBinary`, and is a documented contract (docs/how-to/install.md: "the plugin root first, then an abcd on PATH … the install one-liner restores it"; brief 04-surfaces/01-ahoy.md section 9; brief 05-internals/03-configuration.md). The record contradicts itself: the 2026-08-01 decisions [dcn-2608010000000005](../../decisions/dcn-2608010000000005-itd-105-spc-21-implementation-the-plugin.md) and [dcn-2608010000000007](../../decisions/dcn-2608010000000007-itd-105-spc-21-hook-ordering-assumption.md) (itd-105 / spc-21) state "Rejected: a PATH fallback in the hook commands (spc-21 forbids it)" and "A PATH fallback is forbidden by the intent's Decisions and is NOT added"; iss-254 later added it with no DECISIONS entry reversing that.
- iss-2609012039108437Sibling of GHSA-mchq-gm34-3j34 found during its assessment: `stepMarker` and `detectMarkerDrift` discard `readConfig`'s error the same way `stepVersionStamp` and `detectVersion` do, and plant marker blocks ignoring the user's `docs.target`. `internal/core/ahoy/apply.go:stepMarker` falls back to `docsTargetDefault` ("both") when the persisted config is unreadable, and `detect.go:detectMarkerDrift` raises `marker.missing` for the default targets, which arms that step. In the merge-conflict reproduction at v0.7.0 `install --yes` wrote a marker block into BOTH CLAUDE.md and AGENTS.md although the repo had chosen one target — a write into two user-facing files the user never asked for. The fix must establish that a malformed config plants no marker and raises no marker gap; the same `config.malformed` diagnostic covers it, and `detectConfigValues` stops reporting three misleading `config.*_missing` gaps for a file that is present but unparseable. Handled correctly already, no change: `remote.go:nativeScanningOptedOut` (fail-closed), `vintage.go:recordedSetupVersion`, `attribution_hook.go:attributionOptedIn`, `apply.go:loadPersistedInstallConfig`.
- iss-2609012039114437GHSA-h2gm-w3hm-8xpq ledger marker: the advisory (git check-ignore probes executing a repo-local core.fsmonitor) was fixed before this run by 15a31ea7104a82b5af999ab7ee3a28dac9a0a4a5 "fix(gitutil): pin core.fsmonitor off on check-ignore probes" (plus 742e2f44 allow-listing the test in the hermetic-git gate; first tag v0.6.7). On main, `internal/gitutil/gitignore.go:CheckIgnored` routes through `isolatedGit` (core.hooksPath=/dev/null, core.fsmonitor=false), `internal/core/launch/bundle.go:checkIgnoredStrict` passes the same two pins explicitly with `--no-index` and `gitutil.IsolatedEnv()`, and `internal/gitutil/fsmonitor_exec_test.go:TestCheckIgnoredDoesNotExecuteRepoLocalFsmonitor` passes. The existing resolved record iss-2608270735420161 describes the fix but names no GHSA id and carries no resolved_by stamp; this record binds the advisory to its fixing commit and is not a second defect.
- iss-2609012039114508Observation from the lane LA assessment (GHSA-4q78 reproduction): `ahoy install --yes` with missing config values still emitted an interactive value prompt ("visibility (private/public) []:") on stdout, then proceeded as partial when stdin was empty. `--yes` approves categories, not values, so the partial outcome may be by design, but a prompt landing on stdout under a non-interactive flag with no TTY is worth a look: a scripted install reads it as output, and the prompt is the one line in the run that is not a receipt. Not fixed in this run.
- iss-2609012039116200Sub-finding of GHSA-4q78-ccfv-f374 that does not need the design decision: `ahoy install` uses any CLAUDE_PLUGIN_DATA value as the verified cache, including one that is relative, lies inside the repository being installed, or is world-writable. `internal/core/ahoy/data_dir.go:pluginDataDir` returns the env value unexamined and `owned_copy.go:ownedCopySourceReady` plus `apply.go:installOwnedEntry` copy from it. The harness's persistent per-plugin data directory (spc-35) is always absolute, never inside a project checkout, and never world-writable, so refusing those shapes is a strict hardening of the current contract: a relative value resolves against the checkout the verb runs in, an in-checkout value blesses committed bytes as the owned PATH binary, and a world-writable cache lets any local user swap both artefact and record. The fix must establish that such a data dir is ignored with a note naming why, that install then degrades to the existing loud pinned-symlink path exactly as when no cache exists, and that a harness-shaped data dir still installs the owned copy; the display-only readers of the same variable (`vintage.go:readPinnedTag`, the skew notice) make no trust decision and are unchanged.
- iss-2609012039117381Sub-finding of GHSA-gx3m-3224-qqcv that does not need the design decision: the hook shims' PATH rung accepts an `abcd` that `command -v` resolves from inside the working tree or from a world-writable directory. With a dot or empty PATH entry — or a PATH entry naming a directory under the checkout — `command -v abcd` in `hooks/hooks.json` (UserPromptSubmit, PreToolUse, PreCompact, SessionEnd) returns a file the checkout controls, so a hostile clone carrying an executable `abcd` becomes the guard and rules loader for a session whose plugin-root binary is missing; a world-writable PATH directory hands the same role to any local user. The documented contract (docs/how-to/install.md: plugin root first, then an abcd on PATH, the one-liner installs into `~/.local/bin`) never places the binary in either location, so refusing both keeps the documented rescue intact. The fix must establish, for all four events, that a PATH abcd whose directory is under the shim's working directory or is world-writable is not executed, that the shim degrades to its existing loud line (PreToolUse: UNGUARDED, exit 1) plus one line saying the PATH binary was ignored and why, and that an abcd in an ordinary PATH directory still serves as the fallback. SessionStart is unchanged (no PATH rung). The full owned-only rung stays with the parent record.
- iss-2609012039118971Observation from the lane LA assessment: the two 0.6.7 security fixes 81f81f67 (GHSA-xrf8-4432-gw2f) and 15a31ea7 (GHSA-h2gm-w3hm-8xpq) were committed without `Resolves:` trailers and their records (iss-2608270735428527, iss-2608270735420161) moved to resolved/ without `resolved_by` stamps, so the RS001-RS003 gates either did not exist or did not fire on the security-release-2026-08-27 integration branch. Worth checking whether the other records from that pass share the gap, and whether the gates run on every integration branch today. Not fixed in this run; the two advisories are bound to their fixing commits by their own ledger markers instead.
- iss-2609012039119927GHSA-xrf8-4432-gw2f ledger marker: the advisory (ahoy install writes escaping the working tree through a committed .abcd ancestor symlink) was fixed before this run by 81f81f67df7132067cc04fedda9609224fd052a0 "fix(ahoy): contain install writes against a committed .abcd ancestor symlink" (first tag v0.6.7). On main, `internal/core/ahoy/apply.go:Install` refuses up front via `abcdDirHazard` (a symlink or non-directory .abcd is `Status: "refused"`), `store.go:writeRepoJSON` and `writeConfig` resolve through `os.OpenRoot(cwd)` plus `fsutil.WriteFileAtomicPreserveModeInRoot`, and `internal/core/ahoy/symlink_escape_test.go:TestInstallRefusesAbcdDirSymlinkEscape` passes. The existing resolved record iss-2608270735428527 describes the fix but names no GHSA id and carries no resolved_by stamp, so the advisory was not findable from the ledger by id; this record binds the two and is not a second defect.
- iss-2609012039210402An override `{"PII": {"rules": []}}` passes `Validate` (internal/core/rules/rules.go) and injects a heading-only `## PII` block — suppression wearing the domain's name, which the agent reads as a domain that says nothing; a custom domain declared with recall but no rules does the same. Reproduced at v0.7.0 (a 43-byte block, exit 0). The documented way to silence a domain is `{"state": "dormant"}`; a domain whose merged rules are empty should not render at all, and the loader should say which domain it dropped and name the dormant remedy, in line with the empty-rule-body refusal (iss-2608261550497978). Sibling of GHSA-22f8-qf5r-gjgq.
- iss-2609012039211929GHSA-vvqc-3mv2-5p49 (CWE-15, CWE-426): the rules-loader root resolver `rulesRoot` (internal/surface/cli/cli.go) walks every ancestor of cwd and takes the first one holding a `.abcd` directory, consulting the git toplevel only as a fallback, so a `.abcd/rules.json` or `.abcd/guard.json` planted above the working tree — a world-readable `/tmp/.abcd`, or the user-scope `~/.abcd` for any session under the home directory — governs the injected rules, the refresh backstop and the shell guard of every session in a repository that has no `.abcd` of its own; a planted `{"disabled":true}` guard.json is a successful load that disarms the guard. Reproduced at v0.7.0 (8f68ffb3): `hook prompt-router` run from a fresh inner git repository injected the ancestor plant, and `guard hook` reported the registry switched off. The fix must bound the resolution at the git working tree — toplevel first, the nearest `.abcd` inside the tree wins, a tree with none resolves to its toplevel, and a non-git cwd resolves to itself with no walk — so an ancestor plant is unreachable from any repository; `banlistRoot`, `LoadBackstop` and both guard loaders share the resolver and are fixed by the same change. Behaviour changes to state out loud: a non-git directory no longer walks to the home directory; a nested repository or submodule resolves its own toplevel. Advisory severity medium.
- iss-2609012039215212GHSA-22f8-qf5r-gjgq (CWE-451, CWE-1427): a `.abcd/rules.json` override replaces a bundled domain's rules wholesale (`mergeDomain`, internal/core/rules/rules.go) and nothing downstream records where the words came from — `ResolvedDomain` carries no origin, `renderDomain` emits name and bullets only, the prompt-router diagnostic prints names, and `abcd rules --json` marshals the same origin-less shape — so a hostile or compromised checkout injects attacker-chosen text under `## PII` and the tool's own `# abcd rules` header, byte-indistinguishable from a bundled default in every consumer-visible surface. Reproduced at v0.7.0. The fix must derive provenance at merge time with no rules.json schema change: a `source` field on `ResolvedDomain` valued `bundled` or `repo` (leaving room for `user`, spc-23 AC6), the rendered heading `## NAME (repo override)` for a repo-sourced domain so the marker lands in the agent's context, in `abcd rules` and inside the dedup signature, the source per injected name on the hook's stderr diagnostic, and the field in `rules --json`. The marker moves `Signature` for overridden domains only: a one-time re-injection on the first post-upgrade prompt. Named as out of scope: the guard registry merge (internal/core/guard/config.go) has the same provenance-less shape for `.abcd/guard.json` overrides, but its surface is a block/allow decision, not injected prose. Siblings captured separately: `"rules": []` injecting a heading-only block, and a stop-word recall keyword firing on ordinary prose. iss-174 (an override withholds bundled upgrades) stays open and distinct. Advisory severity medium.
- iss-2609012039220931A custom domain with `"recall": ["the"]` in `.abcd/rules.json` fires on ordinary English prose (reproduced at v0.7.0: it injected on "update the roadmap"), so a repository can make any domain — and any override text — inject on nearly every prompt. Recall matching (`termHit`, internal/core/rules/rules.go) is word-bounded and stemmed but has no notion of a keyword too common to be a signal. Whether to refuse or warn on stop-word recall terms, and against which list, is a policy question rather than a mechanical fix; captured so the decision has a marker. Sibling of GHSA-22f8-qf5r-gjgq: the provenance marker that fix adds makes such a domain visible as a repo override but does not stop it firing.
- iss-2609012039227456Lab finding C6 (lab-260831131349-976575f, base sha 976575f9): `sanitizeRuleBody` (internal/core/rules/rules.go) indents a continuation line only when it begins with `#`, so every other continuation line of a multi-line rule body renders flush-left and un-bulleted — a multi-line rule reads as a bullet followed by loose paragraphs, a continuation beginning with `- ` forges a sibling rule bullet, and the `#` case gets a single space. Reproduced at v0.7.0 with `abcd rules`. The code comment states the threat model backwards ("only a continuation line would sit flush-left"): every continuation line does, because `Validate` accepts a bare newline and the normaliser turns CR, LS and PS into one. The fix indents every continuation line two spaces (the markdown list-item continuation), keeps the sanitiser a fixed point, and defends the line-start contract the host-side parser splits on (`## ` flush-left); no bundled default carries a newline, so only multi-line repo overrides re-inject once.
- iss-2609012039228906Lab finding C2 (lab-260831131349-976575f): the generated `abcd-sources` block in the per-machine private banlist store is written by two writers with different ideas of the file's format. abcd scaffolds the store with the keyed declaration on line 1 (the private stub in internal/core/ahoy/banlist_scaffold.go and the header in internal/core/banlist/private.go); the user-scope sources sync script — invoked from commands/consult.md and not part of this repository — then appends bare one-field pattern lines between its fences, which the keyed parser correctly refuses by line number (the fail-safe held, and the bare `abcd banlist` render already reports the format and the malformed line numbers). The lab's reading that one writer leaves both the declaration and the bare lines was inaccurate: two writers, one file. The fix is in the sync script (emit KEY-tab-PATTERN lines, or the declaration itself), outside this repository; the only in-repo touch point is a caveat in commands/consult.md. Cross-link: iss-2608220150157507 is the same writer's other defect (unanchored short patterns) and stays open. Store entries are never quoted here — shapes only.
- iss-2609012040003576GHSA-5wx3-2c86-fjpx (draft advisory, severity medium; CWE-636, Not Failing Securely): the wired PreToolUse guard hook fails open on two tokenizer error states that every shell an agent runs under executes. `tokenize` (internal/core/guard/tokenize.go) returns ErrUnparsableCommand for a backslash as the last byte of the line and for a here-document body that never reaches its delimiter line, and `newGuardHookCommand` (internal/surface/cli/guard.go) maps every Check error to exit 1 'NOT CHECKED … runs UNGUARDED', so `git push --force origin main \` and `git push --force origin main <<EOF` followed by a newline run without a verdict — bash 3.2 and 5.3, zsh and dash all execute both (the trailing backslash is dropped by bash 3.2/zsh, kept as a literal word by bash 5.3/dash; the empty heredoc body is recovered silently). A third shape shares the root cause: spaced arithmetic `echo $(( x << y ))` on one line and a hazard on the next is misread as a heredoc, because the `<<` branch tests only the byte immediately after the delimiter word for a paren and `followedByParen` sees the space, so the hazard line is swallowed as body and the same error returns. The sibling `shellInspect` (internal/core/guard/payload.go) maps the inner tokenizer's error to a warn, so `sh -c 'git push --force origin main \'` is a loud-warn allow through the same states. The fix must give the two bash-executable states a VERDICT in core rather than an error: arm 1 parses a trailing backslash as bash 3.2 does (dropped — the reading under which the hazard runs, so the fail-safe one) and yields a precise Tier-1 verdict; arm 2 turns an unterminated heredoc body into a segment flag that Check folds into a synthetic fail-closed block (the 2dbb0ca2 brace-group precedent: an error would route to the hook's fail-open), never a remap of the hook's error path, because the unterminated-quote class no shell runs must stay the loud fail-open of spc-16 / iss-269; prerequisite in the same change, the `<<` branch skips blanks before the paren test so `$(( x << y ))` classifies as arithmetic. The hook then blocks both spellings with the entry that names them, `echo hello \` allows, `rm -rf "unterminated` still fails open loud, and the repo corpus holds.
- iss-2609012040008545GHSA-3w99-pgv4-8g55 (draft advisory, severity low; CWE-184, Incomplete List of Disallowed Inputs): a hazard whose argv bash rewrites by glob expansion is an allow. `tokenize` (internal/core/guard/tokenize.go) has no glob branch — `*`, `?` and `[...]` fall to the default word branch and quotes are stripped as they are read, so nothing records that a metacharacter was unquoted — and `matchSegment` (internal/core/guard/match.go) compares the command name, operands 0/1 and every flag alternative literally. So `git pus? --force origin main`, `git push --forc? origin main`, `g?t push --force origin main`, `git push --for[c]e origin main`, `git push --force* origin main` (which expands to --force-with-lease, a member of the entry's own flag group) and the same spellings inside `sh -c` / `eval` payloads all allow, while a file named push, --force or git in the working directory makes bash run the hazard. Tier 2 cannot reach either shape: a flag is never a speculative start and a globbed command name resolves to a name no entry knows. The fix must record per token that it carried an unquoted, unescaped glob metacharacter, and at the positions an entry constrains — command name, subcommand/subcommand2, flag and flag-value alternatives — treat a literal the glob CAN produce (path.Match, decidable from the string with no filesystem read and no cwd) as produced, the fail-closed reading: the guard cannot see the post-cd directory and a file named for the hazard is the cheapest condition. Unconstrained positions are untouched, so `ls *`, `git add *.md`, the quoted and backslash-escaped spellings and the repo corpus stay allow; a segment behind the zsh `noglob` wrapper skips the compare. Siblings named as out of scope: the `wrappers` lookup in commandOf (`sud? rm -rf *` reaches Tier 2's warn, acceptable); the `isShellFamily`, execStringVerbs and singleStringLaunchers lookups (a globbed interpreter name keeps its payload one opaque token, a silent allow of iss-315's shape); `pathArgMatches` (a path glob needs a directory tree named for it in cwd); the `--flag=value` and short-cluster forms of a globbed flag and extended globs (extglob, `**`), which path.Match does not model — the simple compare is a floor; `set -f` as a separate segment (over-block direction, rare); tilde, $VAR and $(…), which need state outside the string and are adr-42's documented residual.
- iss-2609012040016236GHSA-m2r8-fx7r-rq34 (draft advisory, severity medium; CWE-184, Incomplete List of Disallowed Inputs): the guard allows a git hazard whose subcommand git rewrites from in-process config the matcher steps over. `operands` (internal/core/guard/match.go) advances past the value of every flag in an entry's value_flags without reading it, and every bundled git entry lists `-c` and `--config-env` there (gh-299); `commandOf` steps `NAME=VALUE` prefixes the same way. So the alias body is the token stepped over and the attacker-chosen name is what reaches operand 0: `git -c alias.p='push --force' p origin main`, `FORCE_ALIAS='push --force' git --config-env alias.p=FORCE_ALIAS p origin main`, `GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=alias.p GIT_CONFIG_VALUE_0='push --force' git p origin main`, the unlisted sibling `GIT_CONFIG_PARAMETERS="'alias.p=push --force'" git p origin main` (verified live on git 2.52), and the bang-form `git -c alias.p='!<shell command>' p` are all silent allows while git runs the rewritten command. The fix must add a core pre-pass in Check that, for a segment whose command is git, collects the in-segment alias declarations from those four sources and, when operand 0 names one, appends a synthetic segment with the alias expanded (the original global flags, the body's tokens, the arguments after operand 0) so Tier 1 matches it with the existing entries; a bang-form body is handed to shellInspect exactly as an exec-string payload; nested aliases are followed a bounded number of hops. What the string cannot decide: `GIT_CONFIG_GLOBAL=file`, `GIT_CONFIG_SYSTEM=file`, `-c include.path=file` and includeIf deliver the alias body in a FILE, the same class as adr-42's permanently-invisible residual (make targets, shell functions, aliases) — the directive is visible, so each raises a loud synthetic warn (`git-config-rewrite-unread`, also raised for a `--config-env` whose variable is not assigned in the segment), measured against the corpus warn ceiling, which carries zero such lines. Hiding-alias regression decided on the side of fewer moving parts: git ignores an alias that names a builtin, so `git -c alias.push='push --force' push origin main` is a harmless push that the rewrite over-blocks; that over-block is accepted as the fail-safe direction and pinned as a known false positive, rather than shipping a probe-synced 146-name builtin table. `git -c alias.st=status st` allows under the rewrite because its expansion is benign. Unswept family, out of this advisory's scope: the same stepped-over value running a command on a benign subcommand — `-c core.pager=<cmd>`, core.editor, core.sshCommand, credential.helper=!…, diff.external, filter.*.clean — which no entry names; and the registry has no bare `rm -rf /` entry, so the advisory's bang-form example inspects cleanly and allows on the registry's terms (adr-42 decision 5), the mechanism being what this fixes.
- iss-2609012040019014Lab finding lab-260831162806-976575f, probe p5b-live-session-retest: the PreToolUse guard payload carries only tool_input.command, and a destructive command moved into the tool's workdir slips the match. (1) Contract fact: `guardHookInput` (internal/surface/cli/guard.go) reads cwd, tool_name and tool_input.command, and cwd is used only for rulesRoot; a host whose shell tool has a second execution-shaping input (opencode's `workdir`; any host passing a per-call cwd or env) lets a model move meaning out of the string the guard reads. (2) Evidence: the lab's plugin-guard.log records 18:36:58 allow exit 0 for `rm -rf *`, then 18:37:40 block exit 2 for `cd scratch && rm -rf *` — the model had rewritten the chain into workdir=scratch plus `rm -rf *`. (3) The bypassed entry is rm-rf-after-cd-chain, whose why is that a FAILED cd leaves the delete running wherever the shell already was; bare `rm -rf *` is not a registry hazard by design (its successor is an absolute-path delete as its own command). A host-honoured workdir is a different mechanism from a shell cd: whether the failed-cd hazard exists at all depends on what the host does when workdir does not exist — fail the tool call (no hazard) or fall back to the session directory (the hazard) — and the probe evidence does not answer that, so it must be probed on that host before either branch is chosen. (4) No shipped surface carries the field today: hooks/hooks.json wires the Bash matcher only, and the shipped host's Bash tool input has command, timeout, description, run_in_background; the opencode adapter is lab-tier (itd-22 lineage), nothing of it in the tree. (5) The fork, for the maintainer: (A) extend the guard contract — guard.Check in core gains a context carrying the host's workdir/cwd and entries may constrain it; the naive form where the hook prepends `cd <workdir> && ` before Check is WRONG and must not be the implementation, because it fires the cd-chain entry on every workdir'd recursive delete, whose failed-cd hazard the host-managed chdir does not have; versus (B) document the reach — add to the guard brief chapter's 'what an allow still does not see' and to adr-42's scope that the guard reads the command string, a host input that changes where or as whom it runs is outside the read, and a host adapter is responsible for folding such inputs into the string it submits or into a documented field. adr-42 decision 1 (mistake filter; the execution-layer boundary belongs to the host, adr-25) leans toward B, but A is a core API change the ADR does not settle. (6) Severity minor, category observation; stays open until the maintainer picks.
- iss-2609012043432648The status render lists the ingest stage through a plain path rather than through os.Root. Describe (internal/core/reading/status.go) calls os.ReadDir on repoRoot joined with IngestStageDir, so a hostile clone that force-adds .abcd/.work.local as a symlink pointing elsewhere can echo directory names that match the run-id grammar into the status render's orphaned_ingests (and, the same way, staged_runs — the pre-existing StagedRuns read has the same shape). Read-only: nothing is written or deleted through this path, and the write and delete side of the verb (the sweep, rollbackRun) is Root-contained and skips symlinks. Recorded so the read side is known to sit outside the containment the write side has.
- iss-2609012043437282The bare reading status render calls every ingest stage directory an orphan, and promises a rollback that a committed run will never get. Describe (internal/core/reading/status.go) lists IngestStageDir and reports every well-formed run-id directory under orphaned_ingests, described as a run with no commit marker whose reading records the next validating ingest will roll back. But a stage also survives when the commit path's RemoveAll fails AFTER run.json has landed (the Degraded branch at the end of write in ingest.go): that run is complete, and the sweep's rollbackRun already tells the two apart by probing ReadingsRecordDir/<id>/run.json and leaving a committed run's records alone. So for that case the CLI interrupted line (renderReadingStatus in internal/surface/cli/reading.go) and the orphaned_ingests paragraph on commands/reading.md state something false: the records are not for a run that never happened and will not be rolled back; only the stage will be cleared. Both reviewers found it independently. The fix must make Describe probe run.json and report the two cases apart — an orphan whose records will be rolled back, versus a committed run whose leftover stage will merely be cleared — and make the CLI render and the plugin page say the right thing for each.
- iss-2609012043439946A transient I/O failure while loading a definition becomes a permanent refusal of the run. In ingest (internal/core/reading/ingest.go), once the run's identity is proven, a LoadDefinition error is routed through refuse and recorded as refusal.json — by design, so a refused run has something durable to find it by (iss-2608311518250688). The consequence: an EACCES on the definition file, the size cap, or a refused symlink — conditions that clear on retry — produce a durable refusal that refuseARerun then treats as the run's outcome, so the same run id cannot be retried; recovery is re-assembling under a new run id. Recorded as a consequence of a deliberate choice, not as a defect; a later change could distinguish a definition that does not resolve from one that could not be read.
- iss-2609012043443066Deferring the orphan sweep to the commit path lengthens the window in which an orphan's reading records can be dispositioned before they are deleted. The sweep now runs only when a later ingest validates (iss-2608311517509690), so an orphaned run's reading records sit in the committed ledger for longer, and during that window capture's disposition verb can act on one of them. A later sweep then removes the item record by its id grammar and leaves the disposition record dangling, pointing at an item that no longer exists. The dangling case existed before the move — any orphan could be dispositioned between its crash and the next invocation — but the move widens it from the next invocation to the next one that validates. A future change could have the sweep refuse, or report, an orphan whose records already carry a disposition.
- iss-2609012047551175ids_entering_closed in scripts/check-issue-resolution.sh accepts a rename whose SOURCE is already a terminal folder: it keys on the destination alone, so a record that moves resolved/ to wontfix/, or is reslugged within resolved/, counts as ENTERING a terminal folder. Two topologies let a stale trailer pass silently: main has since moved the record from resolved/ to wontfix/ (the branch's Resolves trailer is satisfied by a move it did not make), and main has reslugged the record inside resolved/ (the rename's destination is terminal, the id is extracted from the new basename, and the trailer is satisfied by a rename). Pre-existing, untouched by the hygiene branch; found by the ruthless review of it. The honest test is that the rename's source is NOT a terminal folder, or that the record was open at the base.
- iss-2609012047552618record_path in scripts/check-issue-resolution.sh reads git ls-tree --name-only, which C-quotes a path holding a non-ASCII byte (a record such as iss-999-é.md lists as "…/iss-999-\303\251.md", quotes included), so status_of yields a quoted path whose first component is a quoted-string prefix rather than open, resolved or wontfix, and the RS001 diagnosis added for the stale-branch shape silently regresses to the generic 'does not enter' text for exactly the records whose slug carries an accent. Found by the ruthless review of the hygiene branch. The fix is to list with -c core.quotePath=false (or -z) and to add a case with a non-ASCII slug to check-issue-resolution-cases.sh. <!-- record-lint: illustrative -->
- iss-2609012047566360The placer probe in RS001's stale-branch diagnosis (scripts/check-issue-resolution.sh) names the last base-side commit that touched the record's terminal path after divergence, as evidence that the base placed the record there after the branch forked. Any touch qualifies, so a body edit of a record that was already terminal at the merge base reports 'placed there on main's side by <sha> … rebase' when the honest verdict is 'terminal before this branch diverged; drop the trailer'. The probe should key on the commit that ADDED or renamed the path into the terminal folder (--diff-filter=AR) or compare the merge base's tree, not on any touch. Separately, the base-side commit subject is interpolated into the stderr message unsanitised; a subject carrying terminal control sequences would reach the terminal through the gate's output. Found by the ruthless review of the hygiene branch; left open as a follow-up.
- iss-2609012111150528itd-130's Decisions section records that 'the persistent-data-dir alternative is rejected, not deferred' (grilled 2026-08-20), and one day later itd-132/spc-35 adopted exactly that shape as the download cache with a copied PATH file, superseding spc-21's re-fetch criterion. itd-130's text was never revised, so the shipped record now carries a decision its successor reversed without a typed link between them. Surfaced by the itd-130 fidelity audit (receipt rcp-264f7b144576) as a diverged item. The fix is a record change, not code: itd-132 should carry a typed 'reverses' link to the itd-130 decision, or itd-130's Decisions should note the supersession with the date, and the reversal is a human's to confirm.
- iss-2609012111159045A PATH copy installed by the README one-liner (install -m 0755 into ~/.local/bin) writes no ~/.abcd/path-entry provenance record. The bootstrap refreshes only a registered copy that still matches its recorded hash, so a one-liner copy is never refreshed on plugin update; ahoy classifies it foreign; RefreshPathEntryDigest 'refreshes provenance, never creates it'; and abcd update can only vouch for it while its release manifest is still published. itd-132's press release promises 'the abcd command on PATH keeps working across any number of updates' as 'a regular file abcd owns and refreshes', but its ac-4 Given is ahoy install, so the one-liner route is outside what was delivered (audit receipt rcp-acde3e9ce729, diverged and missing items). Directions, none adopted: the one-liner registers the entry (a post-install 'abcd ahoy adopt', or the binary self-registering on first run of an unregistered regular-file PATH copy after proving it against the release manifest); or abcd update creates the record when it proves a file; or the docs stop promising refresh for that route. Part of the ease-of-update design work.
- iss-2609012111160075itd-132 ac-5 promises that every promotion of a cached artefact re-verifies against its recorded binary_sha256 and 'refuses loudly' on a mismatch. Two branches discard silently instead: the migration-seed mismatch is ignored by spec design (spc-35 line 145) with no notice, and the bootstrap's PATH-refresh branch skips a copy whose hash no longer matches the recorded provenance with no notice and no test covering that branch. Both are refusals in effect, neither is loud, and a user whose PATH copy quietly stopped being refreshed has no signal until abcd update or ahoy tells them it is foreign. Surfaced by the itd-132 fidelity audit (receipt rcp-acde3e9ce729). Loud-staging says a stage that no-ops must say so.
- iss-2609012111162089Three gaps the itd-130 fidelity audit (receipt rcp-264f7b144576) found against spc-32. (1) spc-32 line 61 promised that on a shadowed entry the verb proceeds on the owned entry and reports the shadow; delivered dispatch targets only the first PATH occupant (ResolveUpdateTarget), so the 'update completes on a shadowed entry' path is unreachable, and when the first occupant is an unprovenanced regular file Plan drops LaterOwned so the refusal never mentions the shadowed working install. (2) The non-TTY silence criterion (ac-9) gates progress on stderr's TTY-ness rather than stdout's as written, and no test pins silence when piped (spc-32 line 93 promised one). (3) No test covers a failure after the download starts: mid-stream truncation is file-free only because minio/selfupdate buffers the body, and a copy failure into the .new file has no unlink path (spc-32 line 87 promised the cleanup test); the CA canary-read assertion at spc-32 line 78 is also absent (tests assert the env is unset instead).
- iss-2609012111167476Two itd-132 criteria are met with a narrower reading than their words. ac-1 says provisioning a fresh plugin root from the cache involves 'no network fetch'; delivered is no artefact fetch: the online equal-tag path still resolves releases/latest once and fetches checksums.txt to authenticate the cache (adr-46 decision 3), and only the offline path is network-free. ac-3 says a steady-state hook costs 'one file test and no network'; SessionStart always runs bootstrap.sh, whose cache-mode fast path adds a .binary-meta stat, and the cache-mode steady state of a cache-provisioned root has no direct zero-network test. Both are deliberate designs recorded in adr-46; the criteria's wording is what lags. Surfaced by the itd-132 fidelity audit (receipt rcp-acde3e9ce729). Fix is a record edit or a test, not a code change.
- iss-2609012111168716pluginDataDir reads CLAUDE_PLUGIN_DATA from the environment, which the harness exports only to hook processes. The bootstrap's success notice and docs/how-to/install.md direct the user to run '<plugin-root>/abcd ahoy install' from their terminal, where that variable is unset, so ahoy install finds no cache and degrades (loudly) to the spc-21 pinned symlink into the plugin root, the exact shape spc-35 replaced because it dangles after the next plugin update. Every install that follows the documented instruction therefore lands the legacy shape. Surfaced by the itd-132 fidelity audit (receipt rcp-acde3e9ce729) against ac-4. Directions, none adopted: ahoy install resolves the data dir from recorded provisioning metadata (the bootstrap knows the path and could stamp it into .binary-meta or path-entry) rather than the environment; or the notice tells the user to run it via the hook path; or the docs state the degradation.
- iss-2609012111168872itd-130's press release says 'now the next line is abcd update' and that the eight schema-too-new error sites 'now have a verb they can name'. Delivered: version --check still prints only 'update available: X -> Y' with no next step, and the schema-too-new sites (for example lifeboat/embark.go and release/ingest.go) still say 'upgrade abcd' without naming the verb. The verb exists; the surfaces that motivated it were not re-pointed. Surfaced by the itd-130 fidelity audit (receipt rcp-264f7b144576) as a diverged item. Fix is one string per site plus a test that greps the tree for 'upgrade abcd' outside the update verb's own remedy text.
- iss-2609012202237613Every auto-merge pull request opened tonight (#571, #572, #574) sat BEHIND with queue entry null until a hand-run update-branch, while #570 and #573 entered the queue only because they happened to be up to date at the moment they were armed. Cause: main-protection combines the merge queue (grouping ALLGREEN, merge method MERGE, mirrored 2026-08-19) with strict_required_status_checks_policy true. Auto-merge enqueues a pull request only when its merge state is CLEAN, and under the strict policy a pull request behind main is never CLEAN, so it cannot enter the queue whose whole purpose is to test it combined with the current base. Every merge from the queue moves main and knocks the next un-queued pull request BEHIND again, so a batch of parallel PRs needs one manual update per merge. iss-172 records the invariant that strict is never relaxed because it is what gates the merged result against a duplicate record id minted by two checkouts; that reasoning predates the queue, and the queue now gates exactly that merged result (the group commit on top of main runs every required check before anything lands), so strict adds no gate the queue does not already hold and costs the queue its entry. itd-115 promises the queue removes this toil. Directions, for the maintainer to rule: (1) set strict false in the live ruleset and the mirror, keeping the queue as the gate, and record the ruling against iss-172's invariant; (2) keep strict and automate iss-172 rung 1, an update-branch loop after arming auto-merge, which is what tonight's session runs by hand.
- iss-2609012206053814Ruled 2026-09-01 ([dcn-2609010000000007](../../decisions/dcn-2609010000000007-adrs-take-timestamp-ids-through-the-same.md)): ADRs take timestamp ids through the same recordid seam as issues, because two branches minted 0055 and 0056 on the same day for different decisions. Implementation owed: a verb that mints adr-<timestamp> and writes the ADR skeleton under decisions/adrs with a filename ordered by the stamp; record-lint and the wiki-link resolver admit both the ordinal shape (0001-0058, kept as is) and the timestamp shape; the ADR index and site export sort ordinals first then stamps; adr-45's rollout note names this as the deferred family. Companion to the intent/spec adoption tracked by iss-2608210737260468.
- iss-2609012245352480The record uses several of its own words in more than one sense, and a product thinker cannot tell them apart from the brief alone. 'Phase' names a roadmap phase (an ordered stretch of work ending in a milestone, phases/phase-N-slug.md) and also the brief's plumbing phases that a roadmap phase bundles (phases/README.md, 'which intents and which brief plumbing-phases this phase bundles'); tonight two different documents both claimed the number 7 and two more the number 8. 'Plan' names the intent verb (abcd intent plan, the maintainer's sign-off that mints a spec) and also the roadmap as a build plan, and a session's own plan. 'Roadmap' holds phases and rfcs but the dashboard reads the spec store. 'Record' means the whole development record and also one file in a family. 'Surface' means a verb's front door and also the brief's surface chapters. 'Closed loop', 'ledger', 'construal' and 'reading position' appear with no first-use definition outside the chapter that coins them. Ask: one glossary entry per term in the brief's glossary (or a glossary chapter if none exists), each with the senses it carries and the one spelling used for each sense, referenced from phases/README.md and the intent surface page; the site export links terms to it. Surfaced at the 2026-09-01 interview when the maintainer could not follow questions that used these words unexplained.
- iss-2609012259571458The supply-regime check has a flag mode in code but no seam that can select it, so the design's degradation path cannot be taken
- 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-2609012259585189Nothing reports the proportion of intents that carry a mechanism claim alongside the entailment reading's findings
- iss-2609012259585969The readings companion design document counts five disposition states over a four-row table and still describes a two-operand invocation
- iss-2609012259586524The glossary carries fifteen product terms and none of the ledger's own vocabulary, so the widening reading reads against terms that do not name its object
- iss-2609012259587904The assembler passes the shipped intents at the widening position, which the readings companion's widening object does not list
- iss-2609012313465609Measured on 2026-09-01 with thirteen auto-merge pull requests in flight: each one pays two full CI cycles before it lands, and the macOS check job alone takes about 13 minutes (ubuntu 9). Cycle one: the pull request is armed, main moves, the strict up-to-date policy makes it BEHIND, the keep-current script updates the branch, and the full CI re-runs on the updated head before the pull request is CLEAN enough to enter the merge queue. Cycle two: the merge queue runs the full CI again on the merge group. Every merge moves main and knocks the not-yet-queued pull requests back to cycle one, so a batch of thirteen cost roughly twenty-six 13-minute cycles serialised in ALLGREEN groups, and a one-line record change waited an hour. The maintainer asks how to speed the gates up, for example by running them locally first. Directions, none adopted: (1) local-first is already built and not wired on every account: make preflight is the pre-push gate and .githooks/pre-push runs it, but core.hooksPath is unset on at least one active account, so nothing runs before a push; wire it at ahoy install (an owned ConfigChange) and record which accounts have it; note that a local pass shortens nothing on the forge, it only stops red pushes. (2) Run the full matrix once, in the queue: on the pull_request event run the fast lane only (format, record gates, ubuntu build and test) and keep the macOS leg, the race lane and the smoke harness for the merge_group event, which already runs everything; the CI classifier that stands macOS down for docs-only changes shows the seam exists. (3) Cache the Go build and test cache across runs (actions/setup-go cache keyed on go.sum) and check whether the macOS job's 13 minutes is test time or cold-build time. (4) Let the queue batch: min_entries_to_merge_wait_minutes is 0, so each pull request tends to get its own group; a short wait lets several share one CI run. (5) The strict policy is the multiplier and was kept on 2026-09-01 (iss-2609012202237613); revisit only with the duplicate-id gate argument answered.related itd-2610261025516272
- iss-2609020113012227Refines iss-2608230943088357, which main resolved for the two LOUD shapes (an unknown flag, an unknown command) by naming the stale binary in the refusal. This record carries the third shape, which is SILENT and which that fix cannot reach: the verb exists, is served by the old plugin root, and answers confidently. Observed 2026-09-01 immediately after the v0.7.0 release; the mechanism is that plugin roots are keyed by the commit they were installed from, so a hash-pinned path baked into a skill page is designed to expire, and the old root stays on disk ready to answer. The section that follows is the observation as recorded on the day.
- iss-2609020127210042The PEM block consumer redacts the common renderings of a key body but not every one, and one armour form is not detected at all. scanner.pemBodyLineRe accepts an optional gutter then a single base64 run, so a body rendered as log-prefixed lines (a timestamp/level prefix), as CSV cells, as one element per XML tag, with a trailing hash comment, as a source-string concatenation, as a JSON array on one line, or with double-escaped backslash-n separators is not body-shaped, the block ends at that line and the rest is stored verbatim; the tail of a block longer than maxPEMBodyLines survives by the same route. The RFC4716 armour (four dashes, BEGIN SSH2 ENCRYPTED PRIVATE KEY) does not match the bundled pem_private_key pattern at all, so no block is ever opened for it. Evidence: scanner.pemBodyLineRe and maxPEMBodyLines in internal/adapter/scanner/pem.go, DefaultPatterns pem_private_key in patterns.go. A fix must either widen the body-shape rule over these renderings or arm an entropy rule for a headerless base64 run (iss-96), and add the RFC4716 armour to the header pattern.
- iss-2609020127281995ideate writes caller free text into a committed tier with no scanner call — the fifth committed-tier writer the store-before-commit sweep missed. internal/core/ideate/record.go renders the verdict payload and writes it with fsutil.CreateExclusiveIn into .abcd/development/research/, and nothing in internal/core/ideate imports the scanner, so a secret or an identity pasted into the verdict text lands in the durable record in clear while capture, memory, history and intent all route their text through sc.ScanText plus scanner.Redact first. Evidence: internal/core/ideate/record.go (the CreateExclusiveIn call and render), and the absence of any scanner reference in the package. The fix is to route the rendered record through the same shared redactor before the exclusive create, with the stage-two residual check the other stores apply.
- iss-2609020128539293ProbeIdentity misses the identity scope the environment sets, so a CI or direnv persona is committed in clear. The probe unions every scope git config --get-all reports, but GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, GIT_COMMITTER_NAME and GIT_COMMITTER_EMAIL are an identity source git config never lists: they outrank every config file when a commit is written, and CI runners, direnv profiles and rebase wrappers set them routinely. An identity that authors the caller's commits but is absent from the matcher set is stored verbatim by every write-time redactor (capture, memory, history, intent), which is the same class the three GHSA identity advisories reported for a repo-local persona. Evidence: scanner.ProbeIdentity in internal/adapter/scanner/identity.go reads only git config. The fix is to fold those four environment values into the Other* sets, read once in ProbeIdentity and subject to the same guards the config values are, proved by a test that sets them in-process and asserts the address is redacted.
- iss-2609020154404742prioritise and openIDSet (internal/core/capture/workflow.go) build the blocked_by projection from scanLedger's ISSUES alone and drop its Skipped roster, so an open record the guarded reader refused — a FIFO, a body over the read cap, a symlinked leaf — is invisible to the predicate. A dependent whose blocked_by names that record renders with an empty blocked_by_open and sorts ahead of genuinely unblocked work in both list and the status board, while its own blocked_by still names the blocker: the board understates the blocking, in the direction that invites work nobody can start. Both call sites are affected — List's openIDSet(ir) and Status's inline idSet(open). The fix must establish that a record skipped from open/ still counts as open for the projection, resolving the unreadable case toward still-blocking, with a test that plants an unreadable blocker and asserts the dependent still reports it blocking in list and in status.
- iss-2609020154474224The orphan-draft report in Promote (internal/core/capture/promote.go) delimits its remedy with backticks — complete the link with (backtick)abcd capture promote ...(backtick) — and the remedy now carries the promotion's own grounds, which are free prose. Grounds containing a backtick therefore close the delimiter early, so a reader (or a test, or any tool) copying the text between the backticks gets a truncated command; the remedy itself is well formed and runs when copied whole. The fix must establish a delimiter the argument cannot close, so what sits between the delimiters is always the whole remedy.
- iss-2609020215079051The ci.yml check job carries timeout-minutes: 15 while its macOS leg takes fourteen minutes on a quiet pull-request run (run for PR 589: started 01:28:58Z, completed 01:43:12Z). In the merge-group run for the same PR the macOS leg was cancelled at fifteen minutes inside the race lane, the merge queue removed the entry, and auto-merge was disarmed, with no code at fault. A job budget one minute above the observed quiet-run duration is a wall-clock assertion on a shared runner, the same class as iss-2608292246210181 and the bootstrap self-check site: every queue entry inherits a coin flip. The fix is headroom proportionate to the measured duration, and the durable remedy is the class remedy those records already name.
- iss-2609020219198779The rules-root bound from GHSA-vvqc-3mv2-5p49 does not close the user-scope ~/.abcd when the home directory is itself a git working tree (dotfiles-in-home). ResolveRoot bounds the walk at the toplevel, and for a session in a non-repo directory beneath a version-controlled home that toplevel IS the home, so the home-scope rules.json and guard.json still govern the session: injected rules, the kill switch and the guard registry all come from a file outside any project. Cross-UID /tmp is NOT closed either, contrary to what this record first said: git refuses on ownership and the .git-marker fallback then resolves the planted tree's OWN root, which is precisely what a foreign-uid `git init` in a shared directory wants — that residual is recorded separately as iss-2609020259564193 and needs an ownership policy. What is closed is the one-command plant: a bare `.git` file or an empty `.git` directory no longer bounds the fallback, because the marker must now look like a repository (a `.git` directory carrying HEAD, or a `.git` file beginning "gitdir: "). A version-controlled home and a foreign-uid repository both remain open. Evidence: ResolveRoot in internal/core/rules/root.go. The fix needs a decision first — whether a home-directory toplevel is a legitimate configuration scope (spc-23 plans a user layer that would make it one) or must be excluded outright — so nothing is changed here; the doc comment now states the exact scope and names this record.
- iss-2609020219265817sanitizeRuleBody indents every continuation line of a rule body by two spaces, which defuses the line-start contract the host-side parser splits on but not CommonMark: a two-space-indented heading line inside a list item still renders as a heading INSIDE that item. A repo-overridden domain can therefore put an unmarked heading in front of any reader that renders the injected block as markdown, wearing no repo-override label of its own. The line-start contract holds and this is already stronger than the pre-fix behaviour, which indented nothing at all; closing the CommonMark half needs a decision on whether rule bodies get escaped, fenced, or left as the parser contract defines them. Evidence: sanitizeRuleBody in internal/core/rules/rules.go.
- iss-2609020224230967captureRoot (`internal/surface/cli/cli.go:3794`) is the same collapse the rules
- iss-2609020231145566The armed gitleaks path detects and verifies at different scopes, so a benign recurrence of one fragment refuses every capture for good. toFindings locates the WHOLE reported value in the transcript and emits one finding per line that value crosses, but history.unsealedAugmented verifies each FRAGMENT by presence anywhere in the redacted text: a transcript that also quotes a standalone PEM end-of-key marker line, outside any key, keeps that line unsealed (detection never emitted a finding for it) while verification finds it, so Capture returns RedactionResidualError on every drain, the session is never stored, and its unredacted .raw copy stays staged indefinitely. Evidence: internal/adapter/gitleaks/gitleaks.go toFindings (the whole-needle strings.Index loop and its per-fragment split) and internal/core/history/history.go unsealedAugmented (the strings.Contains-anywhere check). The fix must give detection and verification one scope, so that any byte sequence verification looks for is a sequence detection located and sealed, while keeping the fail-closed contract TestAugmentUnlocatableReportFailsClosed pins.
- iss-2609020238535054memory ingest writes a URL credential into the committed store: materialFromFetched sets both the page origin and the page title from the fetched final URL verbatim, so basic-auth userinfo (user:pass@) and credential-shaped query keys survive into the page frontmatter's source.citation, into .sources_index.json (origin and consumers.memory.citation) and into the IngestResult.Citation the --json render prints. redactText cannot see an opaque basic-auth password, so the scanner backstop does not catch it. The six 'fetch failed for %s' sites in acquireSource, defaultFetch and readFetchedResponse echo the raw source the same way, as do the byte-cap refusal and the redirect-count refusal. CWE-522/CWE-532. The fix must clear the userinfo and drop the credential-shaped query keys (token, api_key, apikey, access_token, password, secret; case-insensitive) where the final URL becomes the stored origin and title, and route every fetch-failure message through the redacting renderer.
- iss-2609020239008775the memory store's write-time leaf walk judges values only, so a secret can enter as a map KEY. storeRedactor.redactLeaves sanitises every string leaf a write introduces but never looks at the keys it walks, and its comment asserts 'Keys are schema-fixed and never walked' — false for the page source: block, where validateSourceBlock rejects no unknown key and checkBlockKey admits any identifier-shaped key, a token like ghp_ followed by alphanumerics included. A host distiller's --pages-json frontmatter can therefore carry a credential as a YAML key straight into a committed page, and only the MR001 residue lint catches it, on read, after the write has already happened. The fix must judge an introduced key with the same scanner its values go through (refuse, never rename) and correct the comment.
- iss-2609020239068243the memory lint's degraded-scanner finding carries a per-repo pattern name into report.md unsanitised. Lint builds an MR001 message from openStoreRedactor's error, whose text includes the pattern name read from .abcd/config/pii.json, and renderLintReportMD writes that message into the local-tier report.md with no termsafe pass; the CLI render sanitises, the file render does not. A hostile or careless pattern name therefore reaches a file the operator opens in a pager. Recorded from a security review of the memory-store lane; not fixed there, and the file report is local-tier rather than committed, so the exposure is one terminal read.
- iss-2609020259564193The rules-root fallback still accepts a foreign-uid repository planted in a shared ancestor. ResolveRoot falls back to gitutil.RepoShapedRoot when git will not answer, and now requires that marker to look like a repository (a .git directory carrying HEAD, or a .git file beginning "gitdir: "), which closes the one-command plant but NOT a real repository: 'git init' in a shared temp directory owned by another uid makes git refuse on ownership under abcd's isolated environment (GIT_CONFIG_GLOBAL=/dev/null discards safe.directory), and that refusal is the SAME signal in the attack and in the motivating case a legitimate foreign-uid checkout or container bind mount presents. A session whose working directory is a plain directory beneath such a plant therefore resolves the planted tree as its root and reads that tree's .abcd/rules.json and .abcd/guard.json: injected rules, the loader kill switch and the hazard registry all come from a directory anyone can write. Evidence: ResolveRoot and plausibleRepository in internal/core/rules/root.go. The fix needs an ownership policy decided first (the run takes no design decisions): whether the fallback must refuse a marker root whose owner is not the caller, and what a shared CI checkout, a container bind mount and a multi-user host then do, or whether the git-refused fallback should be narrowed to a root the caller owns and fail closed otherwise. Nothing is changed here; the resolver's doc comment states the residual and names this record.
- iss-2609020319494139Tests that build a throwaway git repository through gittest.Env and their own git init still let git spawn detached background maintenance (gc --auto, maintenance.auto), which races the test's cleanup and its own tree walks: the merge queue dropped PR 590 twice on this class within one hour — TestTagAndExplicitKeyShapesAreRecognised (internal/core/reading/assemble_test.go:1241) failed on 'TempDir RemoveAll cleanup: .git/objects: directory not empty', and TestAssembleDryRunWritesNothing (internal/surface/cli/reading_surface_test.go:218) failed on 'lstat .git/objects/maintenance.lock: no such file or directory' on the macOS leg. iss-252 closed this for gittest.NewRepo by writing gc.auto=0, gc.autodetach=false and maintenance.auto=false into the fixture repo's local config, but a test that inits its own repository under gittest.Env gets none of that, and gitutil's isolated environment deliberately scrubs the parent's GIT_CONFIG_COUNT injection without supplying its own. The lifeboat package works around it with a TestMain and an allowlist exemption from the hermetic-git rule. The class remedy is to carry the three async-disable keys in the isolated environment itself, so every isolated git call, abcd's own subprocesses included, runs without detached maintenance and every fixture inherits it.
- iss-2609020321100138A memory page FILENAME is never judged by the store redactor, so a secret-shaped slug reaches the committed tree as a filename, in index.md and log.md, and now also as the registry back-link. slugRe admits [A-Za-z0-9_-] and pageNameRe admits <type>_<domain>_<slug>.md, so a host distiller returning slug ghp_<40 chars> writes topic_auth_ghp_....md verbatim; redactLeaves judged only leaf VALUES and KEYS, and excluding the registry back-links (the pruneOrphans data-loss fix) removed the accidental partial coverage the registry rewrite gave. Evidence: validatePageFilename in internal/core/memory/writer.go and DistilledPage.Filename in schema.go; reproduced on this branch (filename, index.md and .sources_index.json all carry the token). The fix must judge the filename at the write boundary and REFUSE rather than rewrite, as judgeKey does for a map key. It needs a decision first: storeRedactor.residue uses BlockingResidual, which treats a warn-severity network span as blocking, and an ordinary slug such as [redacted-hostname] matches net_device_hostname — so the filename rule must run at a narrower bar (hard_fail secrets only) or an ordinary page would be refused.
- iss-2609020347585681A here-document body whose redirection line ends in a list operator reaches command position instead of being read as data, so an apostrophe in an ordinary document becomes ErrUnparsableCommand and the pre-tool-use hook fails OPEN and runs the whole line unguarded (CWE-636, the GHSA-5wx3-2c86-fjpx fail-open class, pre-existing at v0.7.0). Evidence symbol: tokenize's newline branch in internal/core/guard/tokenize.go, which withheld skipHeredocBodies while lastList was set. bash collects here-document bodies at the end of the PHYSICAL line, not at the end of the command list: probed on bash 3.2, `cat <<EOF &&` / `don't` / `EOF` / `echo ok` runs with the body as data and prints ok. The fix must start the body on the line after the redirection regardless of a trailing `&&`, `||` or `|`, and must leave ErrUnparsableCommand for an unterminated quote in COMMAND text only, which no shell runs either.
- iss-2609020348030423A here-document whose delimiter line arrives immediately, with a stray delimiter at the end of the input, swallows the real commands between them as document body — a SILENT allow of a hazard bash runs, not a loud one (CWE-184, sibling of GHSA-5wx3-2c86-fjpx; pre-existing at v0.7.0). Evidence symbols: skipHeredocBodies and tokenize's newline branch in internal/core/guard/tokenize.go. Because the body was deferred while the redirection line ended in a list operator, the scan for the terminator started AFTER the early delimiter line and matched the stray one at the end, so `cat <<EOF &&` / `EOF` / `<hazard>` / `EOF` reported allow while bash runs the hazard (probed on bash 3.2: the hazard line runs, then bash reports `EOF: command not found`). The fix must consume the body from the line immediately after the redirection, so the first delimiter line ends the document and every line after it reaches command position and is matched.
- iss-2609020348038749Two allow-direction inconsistencies between the git in-process alias pre-pass and the rest of the guard matcher, surfaced by the security review of the shell-guard advisory branch. (1) expandGitAliases in internal/core/guard/gitconfig.go compared the command word with `git` literally, while matchSegment compares a globbed command word as the pattern it is, so a glob-spelled git built no alias rewrite and the declared alias went unread. (2) A bang-prefixed alias body is handed to shellInspect and then to expandPayloads, but the resulting segments never go back through expandGitAliases, so an alias declared inside a bang body is not resolved and its rewrite is never checked. Half (1) is closed in the same change that records this, pinned by TestGlobSpelledGitReachesTheAliasPrePass; half (2) stays open because re-entering the pre-pass needs a recursion depth budget and a repeat guard of its own, which is a shape to choose rather than a line to change. Both are allow-direction: the guard says nothing where the matcher's own reading elsewhere would have said something.
- iss-2609020352438590Both containment checks that decide whether abcd runs a foreign binary or reads a foreign cache are weaker than the prose around them claims, in two shared ways. (1) The hook shims' PATH rung (hooks/hooks.json, all four PATH-resolving events) compares the candidate binary's directory against the shim's own `pwd -P`, not against the root of the repository the session is working on, so `<repo>/vendor/bin/abcd` is refused from `<repo>` and accepted from `<repo>/sub` — the same hostile clone, a different working directory. (2) Both that rung and dataDirHazard in internal/core/ahoy/data_dir.go judge only the containing directory's mode, so a world-writable file (0777) inside an ordinary 0755 directory passes every check; on a system where the directory's owner is not the only writer of its contents, the binary that is executed is still anyone's to replace. A fix must establish that containment is measured against the repository root the shim is protecting (git rev-parse --show-toplevel, or the harness's project dir), and that the trust test covers the artefact's own mode and ownership, not just its parent's.
- iss-2609020450405136guard check and guard hook disagree on a candidate whose last line opens a here-document. tokenize resolves a pending here-document only when it crosses a newline, so a candidate that ends at the redirection (`cat <<EOF`, no trailing newline) drops the pending document silently and reads allow, while the same command with its newline intact takes the fail-closed heredoc-unterminated block. guard check trims the trailing newline off stdin (guardCandidate, internal/surface/cli/guard.go), so the two front doors return different verdicts for the same command: the hook blocks, check clears. Evidence symbol: tokenize's final flushSegment, which returns with pending non-empty. The fix must give a here-document still pending at the END OF INPUT the same verdict as one whose delimiter line never came, so both front doors answer identically whether or not the candidate ends in a newline.
- iss-2609020450498573Every `!`-alias body expandGitAliases inspects is offset into the SAME chain range, so two bang bodies on one command line read across each other's cd chain. The bodies are collected in `bang` and offset once after the loop by chainMax+1; each body's own tokenize numbers its chains from 0, so body A's chain 0 and body B's chain 0 land on the same number. An after_cd entry then reads a cd in one body as preceding an rm in another: `git -c alias.a='!cd /tmp' a && git -c alias.b='!rm -rf .' b` blocks via rm-rf-after-cd-chain, while its sh -c twin `sh -c 'cd /tmp' && sh -c 'rm -rf .'` allows, because expandPayloads keeps a RUNNING chainMax and gives each payload its own range. Over-block only, so no hazard escapes; the reading is still wrong. Evidence symbol: expandGitAliases' post-loop `offset := chainMax + 1` in internal/core/guard/gitconfig.go. The fix must give each bang body its own disjoint chain range, as expandPayloads already does for each payload.
- iss-2609020529185438markerRe is a byte pattern, not a grammar: the intent audit's review marker (an HTML comment naming a state and a receipt id) is matched by a regex over the record's raw bytes, so the ledger's notion of review state is whatever the bytes look like rather than what a markdown reader would parse. It is now line-anchored and whole-line, and termsafe breaks the comment delimiters in every field the ingest writes, so a marker can no longer be forged from a verdict payload. What remains is that the pattern still cannot tell a fenced code block, a quoted example in the brief, or an indented literal from a live marker: a marker-shaped line at column zero inside a fence counts. A durable fix parses the Audit Notes section as markdown, or moves the state out of a comment into frontmatter the record schema owns. Evidence symbol: markerRe in internal/core/intent/audit.go, read by existingMarker, markerState and upsertReviewBlock.
- iss-2609020539188868Three markdown renderers re-escape or re-wrap a value termsafe already cleaned, which is the class the intent audit's renderEvidence just had fixed. termsafe's guarantees hold over the exact string CleanProse returned; a caller that adds its own delimiters is parsing a different string than the cleaner reasoned about. memory.RenderIndex and memory.RenderContradictions (internal/core/memory/schema.go, the two backtick-wrapped format strings) wrap a cleaned page filename in their own backticks, so a filename carrying a backtick shifts code-span parity in the committed .abcd/memory/index.md and contradictions.md and can move a sheltered angle bracket out of its span; memory.Ask's match render has the same shape over a value cleaned only by Sanitize; lifeboat's synthesis_review severity bracket and press-release subhead emphasis are the weaker form (neither delimiter affects span parity, and the artefact is not a committed record), and synthesis_review renders f.ID through Sanitize alone, never CleanProse, so it can still carry an HTML comment opener or link syntax; lifeboat's synthesis_principles writes a cleaned principle as a bare paragraph with no leading-marker escape. Out of scope for the code-span fix that found them (a different package, a different caller, and none is a defect that change introduced). What the fix DID close for all of them is the same-line embedding half: no cleaned field can carry an unpaired backtick run any more, so two cleaned values on one line cannot re-pair. The fix must establish that no renderer alters a cleaned value's bytes, and that every untrusted field on a committed markdown line goes through CleanProse rather than Sanitize alone.
- iss-2609020543544634A here-document delimiter that is not letter-led fell to the arithmetic-shift branch, so the DOCUMENT was tokenized as commands and one apostrophe in the body raised ErrUnparsableCommand — which the pre-tool-use hook maps to fail-OPEN, leaving any hazard on a later line to run unguarded. bash accepts a WORD after <<: 'cat <<20', 'cat <<$D' and the '<<20' of 'let mask=1<<20' are all here-documents (the shell tokenizes the redirection before the let builtin sees arithmetic), and each of those spellings reached exit 2 / NOT CHECKED on v0.7.0. Evidence symbol: isDelimStart (internal/core/guard/tokenize.go), consulted at the '<<' branch of tokenize. It also falsified the claim both front doors make — that a quote inside a here-document body is document text and never unparsable. The fix must read the conservative superset of delimiter words (letter, digit, underscore, $-led) so the body is data, with the enclosing arithmetic context left as the sole shift discriminator.
- iss-2609020544031234bash's deprecated $[ … ] arithmetic form is not modelled as an arithmetic context, so a '<<' inside it is read as a here-document redirection: 'echo $[ 1 << EOF ]' followed by any command blocks under heredoc-unterminated on both this branch and v0.7.0, where bash evaluates 1<<0 and runs on. Widening isDelimStart to digits and $-led words (the fix for the fail-open sibling) widens this residual from EOF-shaped operands to every operand, so '$[ 1 << 20 ]' now over-blocks too. Evidence symbol: inArithmetic / the parens stack (internal/core/guard/tokenize.go), which recognises $(( and (( and nothing else. The direction is fail-CLOSED and loud, and the form has been deprecated since bash 2.0, so this is recorded rather than fixed: the fix is a third frame kind on the parens stack ($[ opens, ] closes) and a decision about whether the guard should track a construct bash itself discourages.
- iss-2609020626100041ADR owed: the comparative channel admits two fields of one widening run's items from the readings family at one position, a positional exception to the prior-run exhaust
- iss-2609020626111484ADR owed: the principles family becomes a declared record store with typed frontmatter, a record-architecture decision on the pattern of adr-30, and the lifeboat principles contract moves with it
- 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
- iss-2609020626118168Ruling owed: whether every rewrite of the construal must carry a reframe record, which refines adr-55 and reaches rewrites no reading occasioned
- iss-2609020630232658scrubRemoteUserinfo and the history.credential_at_rest detector decide that a userinfo carries a password by a literal colon, but git percent-decodes userinfo, so a remote such as ssh://user%3Apw@host/owner/repo.git under a non-http scheme is neither scrubbed at the derivation site nor detected at rest: the encoded password is stored verbatim in index.json and meta.json and the heal never fires. Reachability is thin (no credential helper is known to write this form) so this is a coverage hole in the new detector rather than a demonstrated leak; the fix is to percent-decode the userinfo before the colon test, for every scheme.
- iss-2609020630242279readPinnedTag in internal/core/ahoy/vintage.go still reads CLAUDE_PLUGIN_DATA/cache/binary-meta without dataDirHazard, the one reader of that variable the owned-copy hardening did not route through the check. An environment-chosen relative, in-repo or world-writable data directory therefore supplies release_tag to currentVintage, which feeds staleBinaryRefusal, so a wrong vintage claim can suppress the stale-binary refusal that gates install logic. No write is demonstrated; the consequence is a wrong vintage claim. The fix is the same dataDirHazard gate at this reader, or a documented statement that the vintage line is display-only if that is decided.
- iss-2609020716236446The register rule (the GRILL domain in .abcd/rules.json and the itd-200 mode) tells an agent to address a product thinker in outcomes and choices and a technical facilitator in mechanism and ids, but it says nothing about ASSUMED KNOWLEDGE, and that is where explanations still miss. Observed during the 2026-09-02 design interview: a fork about repository ownership was first explained in terms of git's safe.directory, dubious-ownership refusals and the isolated git environment; the product thinker cannot be assumed to know git at all, while the technical facilitator can, and the same split holds for a merge queue, a worktree, a hook, an environment variable, a checksum, a symlink. The rule should carry an explicit knowledge floor per register: the product thinker knows the product's outcomes and the ordinary vocabulary of software use, not version control, shells, file permissions or CI; the technical facilitator knows those and the repo's record ids. An explanation for the product thinker names no tool and no mechanism the floor excludes, and where a concept is unavoidable it is introduced in one sentence in product terms (a notebook of pages, a lock, a name) before it is used. Worth deciding whether the floor is a list in the rule text, a glossary the rule points at, or both.
- iss-2609020716560392ci.yml's concurrency group cancels an in-progress run for every ref except the default branch, and a merge-queue ref (gh-readonly-queue/main/pr-N-<sha>) is never the default branch, so a merge-group run is cancellable; GitHub's queue treats a cancelled required check as a failure, removes the entry and disarms auto-merge with no notice on the pull request. One PR was removed four times in one night (twice on the 15-minute job budget, twice on a cleanup flake), each time silently. Fix shape: exempt the queue refs from cancel-in-progress (attribution.yml already keys on run_id), and consider disabling the ruleset's 'only merge non-failing pull requests' so one flake waits for the group behind it instead of ejecting; a comment on the PR when the queue removes it would make the remaining drops loud.
- iss-2609020716561070The main ruleset requires a pull request to be up to date with its base before its checks count, and the merge queue already provides that guarantee by building each entry on top of the queue ahead of it; keeping both means every merge invalidates every open branch, so an autonomous run had to run scripts/pr-keep-current.sh after each of eleven merges and a peer session's overnight merges churned every branch this run held. GitHub's own guidance says the queue removes the need for the up-to-date requirement. Worth deciding whether the strict requirement still earns its place (iss-172 argued it gates a duplicate record id, which the timestamp mint since made moot).
- iss-2609020716570699Nothing tells an agent that a record it is about to fix has been claimed or resolved by another session until the resolution gate refuses the push. In one night a peer session re-fixed two issues a paused branch also fixed, and two of its open PRs duplicate merged work. The claim signal that worked in every published multi-agent run is the repository itself: a claim written into the open record (claimed_by: account and harness, branch) and pushed alone through the queue before any fix starts, so a losing race is a push rejection; plus a duplicate-guard required check that fails a PR whose Resolves trailer names a record already resolved on origin/main; plus capture resolve refusing a record that is already terminal on the fetched origin/main. Folder membership is already the status signal, so the claim extends the one canonical primitive rather than adding a lock file that rots. Refines iss-2608220750029993.related itd-2609091034175565 · related itd-2609091416295622 · related itd-2609091416304128
- iss-2609020716571275abcd capture's --source enum has no value for a security advisory (an external reviewer's finding on the forge) nor for a handover item (a NEXT.md or lab finding another session left for filing); the autonomous run used review-followup and agent-observation and stated the real origin in each body. Either the enum gains security-advisory and handover, or the surface page documents the mapping so every future run chooses the same values.
- iss-2609020716572828The security-reviewer agent ran for over three and a half hours on the ahoy branch with no report, while a fresh copy of the same review given an explicit budget of about twenty-five tool calls reported in eight minutes and found the same class. Review prompts should carry a budget and a report-what-you-have instruction, and the orchestrator should time-box a review rather than wait; the run's BRIEF for lane agents already says validation runs in the foreground because a backgrounded gate never wakes the agent that started it, and the same harness shape applies here.
- iss-2609020716579024A resolution note that names the tests proving a limb is trusted by every later reader, and one was false: the transcript lane's note named three tests for the drain-side removal guard and none of them exercised it (the ruthless review reverted the guard and the suite stayed green). A reviewer or a lint could check the claim mechanically: every TestX a resolution names must exist, and a mutation of the described limb should fail at least one of them. The cheap rung is record-lint verifying that each named test exists; the mutation check is a review discipline until it earns a tool.
- iss-2609020721142452Worktrees for parallel lanes are created one directory above the repository (../abcd-wt-<lane>, ../abcd-f185, ../abcd-integration), which litters the parent directory with a dozen sibling checkouts named by convention only, leaves them behind when a session dies (21 spent worktrees, 1.4G, were removed by hand on 2026-09-01), and gives nothing a stable place to look for them. Assessment of where they should go: (1) inside the repository under .abcd/.work.local/worktrees/ keeps them with their owner and gitignored, but a worktree inside the main working tree is walked by every tree scan (the payload gate, name-guard, docs-lint), which already flakes during worktree creation (iss-2608261331317889) and would slow every gate; (2) under the user-level home, ~/.abcd/worktrees/<root-sha>/<branch-slug>/, keyed the way the history store already keys a repository by its root commit, keeps them out of every scan, survives a session, and gives an abcd verb a place to list, prune and reattach them; (3) the git default (anywhere) is the status quo. Option 2 fits the existing home layout and the one-canonical-primitive rule (the root-sha keying exists), and it makes the concurrent-sessions convention in AGENTS.md checkable: a session lists its peers' worktrees by reading one directory. It needs: a verb or documented one-liner (abcd worktree add <lane> / list / prune), the AGENTS.md convention updated, the lane brief updated, and a prune rule for worktrees whose branch is merged.
- iss-2609020721396212Intent and spec titles have no length ceiling, and several run to a full sentence that carries the description rather than a name (the longest today are well over a hundred characters), so a roster, a status board, a changelog line and the record export on the website all show a paragraph where a title belongs, and the id-plus-slug filename derived from the title is truncated at a fixed width that cuts mid-word. Two changes: a threshold on the title at mint time (intent new, spec new, capture promote), refused with the excess named and the description offered as the place for the rest, with a size stated in the record schema and enforced by record-lint for hand-written records; and the website's record export truncating an existing over-long title at the display layer with an ellipsis and the full text on hover or on the record page, so the records already in the corpus do not have to be rewritten to render. The ceiling itself is a decision (a fixed character count, or a word count); the site truncation is not.
- iss-2609020734198139The v0.7.1 brief-surface crosscheck (Direction A, tier full, over the sixteen first surface chapters) found four false claims in the design record, none in a user-facing page. 01-ahoy.md line 225 says every non-SessionStart shim attempts hooks/bootstrap.sh when the plugin-root binary is missing; hooks.json wires bootstrap into UserPromptSubmit, SessionStart, PreToolUse and PreCompact but not SessionEnd, which resolves the plugin root, then a vouched PATH abcd, then fails loudly, so a machine with no plugin-root binary never stages its transcript at exit and the chapter says otherwise. 01-ahoy.md line 28 lists status among the sub-verbs that ship on the CLI; abcd ahoy status exits 2, status being a plugin-side alias for the bare render, and the chapter's own sub-verb table omits it. 07-memory.md line 3 disambiguates spc-38 and spc-39 by saying the store's ids stop well short of spc-38; the store now runs to spc-70 and both ids name unrelated specs, so a dozen bare references on the page point at the wrong records. 07-memory.md line 116 enumerates launch --dry-run's gates as five, omitting semantic-receipts, which 04-launch.md documents. Each is a one-line correction; the receipt for the v0.7.1 cut defers them to this record.
- iss-2609020735520603The v0.7.1 brief-surface crosscheck (Direction A over chapters 17 to 31 and Direction B over the five surfaces, tier full) found thirty-four discrepancies, every one in prose no lint rule reads: 02-constraints/04-naming.md (4), 05-internals/01-agents.md (1), 03-configuration.md (5), 05-prompt-quality.md (4), 08-skills.md (1), 06-delivery/01-build-sequence.md (5), 02-verification-matrix.md (7), 04-surfaces/23-reading.md (2), plus four against the CLI verb tree; the eight assigned 04-surfaces chapters gated by surface_coverage were clean but for reading. The consequential ones: 23-reading.md line 128 claims every regime signature ships enforced when all four are observed (ingest_regime.go and its test record the change; the brief sentence was never updated), an overstated safety property on a shipped release; 06-delivery/02-verification-matrix.md line 55 says never a capture promote CLI sub-verb while the verb ships and 04-surfaces/README.md documents it; the disembark invocation is written as 'disembark <source-repo> to <dest>' in seven places across four chapters where the real shape is 'disembark pack <repo> <dest>' with no 'to'; an internal/adapter/{oracle,history,spec,run,scanner} plus internal/registry layout is asserted in two chapters and does not exist; 06-delivery/01-build-sequence.md line 38 attributes abcd init and abcd config get|set to the shipped install milestone and neither exists; the operator-internal verb count disagrees between 08-skills.md (five) and 04-surfaces/README.md (three, correct). The full list with claim and reality per item is the crosscheck output kept with the v0.7.1 receipts. Worth deciding whether the un-gated chapters join the surface_coverage rule's scope rather than being corrected by hand again.
- iss-2609020735528927The SessionEnd hook shim in hooks/hooks.json does not self-provision: UserPromptSubmit, PreToolUse and PreCompact each carry the bootstrap.sh attempt with the .bootstrap.attempt throttle when the plugin-root binary is missing, and SessionEnd tests the plugin-root binary, falls to the vouched PATH abcd, then fails loudly. On a plugin root with no binary, four events attempt provisioning and SessionEnd silently loses the session transcript, which is the one event whose loss cannot be recovered on the next session. Both 01-ahoy.md (line 225) and 05-internals/03-configuration.md (line 374) document the four non-SessionStart shims as self-provisioning, so the brief describes the intended shape and the shim is the defect. Found by the v0.7.1 brief-surface crosscheck (Direction B, hook entrypoints).
- iss-2609020746547554The status board's next moves for an open issue (abcd <iss-N>, /abcd iss-N, internal/core/record/record.go) print two remedies a user copies and runs, and both refuse: 'abcd capture promote <iss-N>' and 'abcd capture resolve <iss-N> "<note>" --impact <...>' exit 2 with 'requires --grounds' because grounds have been mandatory on both routes since v0.7.0 (88b3da87). The wontfix remedy is correct as printed. The same class was fixed for the orphan-draft remedy in promote.go but this render was missed, and README's first-run section points readers at the board. Found by the v0.7.1 docs-currency pass as its one blocker.
- iss-2609020747254212Three brief pages say an intent reaches shipped/ via '/abcd:intent ship <itd-N>': 01-product/04-scope.md line 44, 06-delivery/02-verification-matrix.md line 42 and 03-out-of-scope.md line 120. No such verb exists; abcd intent offers audit, link, new, plan and ready, and the route that ships an intent is 'abcd spec close <spc-N>', which commands/intent.md documents as CLI-only. The verification matrix is a page whose whole job is to be checkable, and it qualifies the v0.7.1 line that the brief describes the binary that shipped. Found by the v0.7.1 docs-currency pass; deferred from the receipt to this record.
- iss-2609020833531987docs/reference/writing-style.md gained a Structure-table row for harness_leak at v0.7.1 but its Escapes section (lines 81 to 90) still lists the docs-lint allow families as present_tense, punctuation, spelling, harness and names, and says the other machine-enforced rules have no line escape; harness_leak is in neither list, and it does take a line escape under a different token: checkHarnessLeak skips a line carrying abcd-lint:allow (or the pre-spc-29 abcd-audit:allow) and does not honour the docs-lint allow comment, and a fenced block is never flagged. A reader applies the wrong escape token or believes none exists. One sentence after line 88 closes it. Found by the v0.7.1 docs-currency pass on the release content commit; deferred from the receipt to this record.
- iss-2609020843067458The ingest verb's terminal help still claims a refusal deletes nothing, and gives the orphan sweep one outcome where the code has two. iss-2608311518199679 named three false sentences in the same Long field and its fix reaches two of them; the durability sentence reads "written or deleted" without the qualification that makes it true, and the sweep sentence carries the committed-tier delete without the case in which there is none. A refusal after the run's identity is proven calls rollbackThisRun on every path, which removes the never-committed reading records of an earlier attempt at the same run id from the committed ledger — so "leaves its refusal record and nothing else" describes a verb that makes no delete, and the verb makes one. rollbackRun returns without touching anything when the run's commit marker is present, and sweepOrphanStages clears the stage regardless, so a sweep over a leftover stage rolls nothing back and the help promises a rollback that does not come. The neighbouring "before that point nothing is written anywhere" is false of the stage root and its lock, which are created before the payload is read; the claim is about the durable tier. Because docs/reference/cli/commands.md is generated from the Long field, each of these is wrong at the terminal and on the reference page at once.
- iss-2609020848468450On the refusal path the ingest result's pending_stages is set from the orphan list gathered before the refusal and is never recomputed after rollbackThisRun runs, so it can name the refused run's own stage as pending although that stage was just cleared. The disclosure the surface renders is then wrong by one entry in exactly the case it exists to describe. Found while pinning the ingest help's sentences (iss-2609020843067458). Fix: recompute or filter the pending list after the run's own rollback, and pin it with the same end-to-end refusal test that now proves the record set.
- iss-2609020906544088Found while readying Phase 8: the generated CLI reference (docs/reference/cli/commands.md), the surface_coverage record-lint rule and the brief-to-surface crosscheck gate were all shipped under issue ids with no intent record, and itd-60 and itd-85 each shipped substantial code while sitting in drafts/ (itd-60's deterministic docs lint is live as abcd docs lint; itd-85's delivery is on main). Phase 8's expectation is that the record is the shipped state, and these are shipped capabilities the record does not name as intents, so a product thinker reading the brief and the intents together still cannot see them as delivered. Directions, none adopted: file a shipped intent per capability by hand with an audit note saying it was delivered before the ceremony existed; or list them in the Phase 8 file as pre-ceremony deliveries and leave the intents as is; or resolve the gap through the doc-fidelity gate itself once it exists, since it will name every surface the brief describes without an intent.
- iss-2609020922150364The glossary now names every sense of the record's colliding terms (iss-2609012245352480), but the site export reads no glossary: internal/core/site carries no reference to it, so a rendered page shows 'phase', 'plan' or 'surface' as plain words and a reader on the site cannot reach the entry that disambiguates them. The record's ask was that the site links terms to the glossary; that half is Go work and stays open here. Directions, none adopted: the site renderer wraps the first occurrence of each glossary term on a page in a link to its entry; or every rendered page carries a glossary sidebar listing the terms it uses; or the glossary is exported as its own page set and chapters link by hand.
- iss-2609021152026246make preflight runs record-lint without -agent-diff, so the agent_contract sub-check that asks whether a changed agent prompt bumped its prompt_version and wrote its agents/CHANGELOG.md entry is a no-op locally and arms only in CI, which passes -agent-diff. PR 606 passed a green local preflight three times and was refused in the merge queue for exactly that check: agents/cold-reading-widening.md changed with prompt_version still 0.1.0. Same shape as iss-2608311632382737 (preflight blind to the eval lanes, fixed by PR 607): a gate the push relies on that the local run cannot see. Fix: preflight passes -agent-diff origin/main...HEAD (or the merge-base) to record-lint, and the gate-roster test that pins preflight's contents asserts it.
- iss-2609021153261145The blindness core's fourth condition says items come back unordered and unweighted where the companion's section 2 says items are returned in the order they arise in the object
- iss-2609021153264023The assembler admits only the brief's product and constraints chapters where the design documents name the brief's current text as a reading's object
- iss-2609021153269181The ingest verb refuses an output carrying no items, where the framework's clean-run contingency records a null result as a run with an empty item set
- iss-2609021457186209spc-2609021003136831 section 'The six refusals' states that none of the six shapes appears in a committed record the include table admits, so the refusals refuse nothing on this corpus today. That measurement is wrong. Shape 2, the displaced frontmatter block, is carried by 21 committed glossary records under .abcd/development/brief/glossary/ (core/*.md, interview/*.md and _template.md), each opening with the attribution comment 'Adapted from mattpocock/skills (MIT). See README Acknowledgements.' as an HTML comment on line 0 and its frontmatter delimiter on line 1. The refusal is correct on the merits: frontmatter.Fields requires the delimiter at line 0, so those records' frontmatter keys are invisible to the assembler's redactor while every manifest asserts the key exclusions over them, which is the brief invariant 16 violation iss-2608301237456350 names. The consequence is that once itd-194 ships, reading assemble refuses at every assembling position over this repository's own corpus, and the ac-5 eval TestTheFixtureLeakIsAbsentUnderEveryCommittedPreset, which assembles a clone of HEAD, cannot pass. The two spec requirements are not simultaneously satisfiable while those records stand. Measured remedy, verified on a scratch copy: moving the attribution comment to the line after the frontmatter block's closing delimiter in those 21 files makes the whole corpus assemble with no refusal and leaves record-lint with no new finding. Whether to repair the records, narrow shape 2's HTML-comment clause, or do something else is a corpus decision this spec does not authorise, so it is captured rather than taken.
- iss-2609021748300398The entailment assembly hands every draft and planned intent in the repository — 147 projected intents on this tree — where the design 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. The readings companion's section 6.2 makes drafts and planned intents admissible at the entailment position, and admissible is a permission rather than a scope; the assembler reads it as the scope because a record row is admitted whole when the object set names none of its records, so the drafts and planned rows are never narrowed by the entry's record list the way the shipped row is. The committed entailment entry therefore hands material the object set does not name, and no committed fact says which drafts and planned intents a run is about.
- iss-2609021815529020The human step of answering a run's items has no surface beyond the disposition command: a worksheet that walks the researcher through every outstanding item one reading at a time, offers the four states as the design allows them per position with the refusals built in (grounds required on every state but held, an exit condition on held, no default and nothing meaning already covered), loads the outstanding items from a markdown export of the reading records and returns one uniquely named answer file that a session records through the disposition command, was prototyped outside the record for the opening run. Whether it becomes a planned intent, and whether the site renders the outstanding items of every open run as a read-only page, is a maintainer decision after the first run shows what the form needs.
- iss-2609021815563506intent.SetPromotedFrom returns a populated Intent beside a non-nil ErrBackEdgeTaken, deliberately and documented, and the promote route depends on that value to report the kept back-edge, but the primitive's own test discards the return, so the stated contract is asserted only indirectly through the capture result's BackEdgeKept field. The fidelity verdict for itd-2609020625400169 records this as its one missing item; a primitive-level assertion closes it.
- iss-2609021816004079The committed preset file's one entry per position is keyed default, a name the implementer chose when the two-operand invocation retired the cold and warm tokens: neither adr-2609021016286571 nor spc-2609021004075744 names the surviving key, and the divergence register, which by its own terms lists every point the materials chose where the documents are open, carries no entry for it. The key is inert at the invocation (a file holding other than one preset is refused), so nothing depends on the word, but the record now carries a name the decision record did not decide. A register entry or a ruling settles it.
- iss-2609021816039081The readings companion's section 4.3 says what a disposition's grounds must contain varies by state (a rejection names the purpose protected, an admission or a decline states why) and that the variation is a lint rule rather than four fields. Nothing enforces it: the disposition command refuses only a blank or whitespace-only grounds field, and no lint reads the grounds against the state. Held by protocol today; the readiness statement for Phase A records it as not held by mechanism.
- iss-2609021833302981The comparative assembly cannot follow the widening ingest that supplies its candidates: reading ingest writes the widening run's reading records into the committed ledger, where they are uncommitted by construction, and the comparative position's candidate row reaches that store, so the dirty gate refuses the next assembly naming those very records; committing them closes the other end, because the derivation selects a widening run whose own target commit equals the target and the commit has just moved HEAD off it. Both gates are stated in commands/reading.md (Assemble one reading's input: refuses unless HEAD resolves to the target and no included path is uncommitted; The comparative position derives its candidate set from the record: the one committed widening run at the target) and the derivation rule is adr-2609021016272867, so which of the two gives is a design decision the record has not made. Found by rehearsing the opening-run loop on a fixture: the comparative position is reachable only over a widening run whose records were already committed at HEAD, which no run of the loop produces.
- iss-2609021857343626ruling owed on the reading of 'at the target' in adr-2609021016272867 for the comparative derivation; the implementation accepts a widening run whose target is an ancestor of the comparative's target when only the readings store changed between them, so the run's own records can be committed between ingest and the next reading; the alternative is an assembly whose target may differ from HEAD at the comparative position, which reads no tree; the maintainer chooses and the register gains the entry
- iss-2609021950351082The comparative dirty gate does not cover the disposition and admission families, so an uncommitted fate silently selects a different candidate run. refuseDirtyIncludedPaths in internal/core/reading/assemble.go names LintConfigPath and PresetConfigPath by hand but not the two ledger families the comparative derivation reads from the filesystem: capture.ItemFate walks the dispositions and admissions directories to decide whether a widening run is still pre-admission. Commit a disposition on a candidate, delete it in the working tree alone, and the assembly admits the run and mints a manifest whose named commit still carries the disposition — a re-run at that commit would derive a different candidate set. Expected: at the comparative position any dirty path under either family is included, so the gate refuses and names it.
- iss-2609021954509554The markup-shape refusal reads the whole document instead of the unfenced body, so a fenced HTML example refuses every assembly. verifyRedaction in internal/core/reading/project.go calls markupShapeOf over strings.Join(lines) and ignores the fence mask it already computed, unlike rawHTMLHeading and the indented-ATX and excluded-key scans beside it, which all take the mask. A code block showing an HTML attribute whose value opens on the line after its equals sign is an EXAMPLE, not markup the bundle carries; any admitted markdown document holding one refuses the run at every position. Expected: the shape scan reads the unfenced body, with fenced lines blanked rather than dropped so a line number still names the document's own line, and the same shape outside a fence still refuses.
- iss-2609022002241168Agent-supplied verdict and refusal fields reach committed records unredacted, in two sibling ingests. In internal/core/intent/audit.go the ingested block renders verifier.id, verifier.version, policy.rubric_hash, policy.prompt_hash and every input_attestations[] kind, ref and digest through orDash/oneLine alone: no privacy redaction and no shape validation, though iss-2608300924205748's resolution claims identifiers, enum values and hashes are validated shapes. Nothing validates them; a real attestation ref is free prose (a commit range with a parenthetical), so an absolute home path in a ref or a hostname in a verifier id lands in the shipped intent's Audit Notes verbatim. In internal/core/reading/ingest_regime.go a refused comparative item's free-text criterion is echoed into RunRecord.RefusedItems and lands in the durable run.json and refusal.json unredacted, while an ACCEPTED item's body is redacted on write by the same ingest. Expected: every payload-derived string bound for a durable record is redacted before it is neutralised, and what has a declared shape is validated instead.
- iss-2609022252265901The regime operator-surface guard (TestNoOperatorSurfaceSetsARegime) walks every tracked JSON under .abcd/ from the git index and treats each key as a configuration key an operator could write. The readings record family is not configuration: abcd reading ingest writes .abcd/development/readings/RUNID/run.json and refusal.json from the agent definition, and each carries the regime the design requires the definition to stamp and the output contract to carry, so both fail the guard the moment a real run is committed. No run record had been committed before Iteration 2's opening readings, so the over-reach was latent and passed every prior preflight. A record family a verb writes from a definition is not an operator surface, and the walk reaches into one.
- iss-2609061432214212abcd launch cannot set up the release flow for a managed repo that is not a plugin. Observed adopting abcd in a managed Go macOS app (own tag-driven release workflow building on a macOS runner with minisign, no CHANGELOG.md, no .claude-plugin/plugin.json): 'abcd launch --dry-run' fails with 'include config not found: .abcd/config/launch-payload.json'; 'abcd changelog' and 'abcd launch ship' fail reading .claude-plugin/plugin.json; 'abcd launch scaffold' writes the generic ubuntu Go template (verify/build/publish) that replaces the repo's own release workflow, and nothing creates the pieces the flow presupposes: CHANGELOG.md with its empty [Unreleased] anchor, the launch payload include config, a version location for a non-plugin artefact, and (where detectors are configured) the release-gate manifest and receipts directory. Needed: an adoption step (ahoy install or launch scaffold --init) that lays these down for a managed repo, a way to declare a non-plugin version location and payload, and a template extension point for platform-specific build/publish steps so scaffold parity does not fight a macOS build. Until then a managed repo has to hand-port the template.related itd-2609150819432059
- iss-2609061438431625A Claude session URL reached three commit messages and two PR bodies of a managed public repo and nothing in the abcd guard stack stopped it — not acceptable. The lint policy text says a live session URL or a tool attribution footer is refused wherever it is committed, but privacy-hygiene only scans tracked files; the committed pre-commit name guard checks the private banlist (empty by default) and never the commit message; there is no commit-msg hook, and nothing looks at the text handed to the GitHub CLI for pull requests or issues. The harness's own attribution instruction (a Claude-Session trailer on every commit and PR) is exactly the pattern the policy names, so the guard must catch it mechanically: a commit-msg hook (and pre-merge-commit) that rejects claude.ai/code/session links and known AI attribution footers; a public banned-token family for those patterns so CI enforces it on every pushed commit message in the PR range, not only on files; and guard coverage of the GitHub CLI's pull-request and issue text. Recovery is expensive — a merged commit message can only be removed by rewriting a protected branch — so this has to fail before the commit exists.
- iss-2609061503374089The plugin-provisioned binary (v0.7.1, plugin root e3696dc524e3) has no decide verb, but the plugin ships the /abcd:decide skill, which tells a plugin user to run '<plugin-root>/abcd decide' and reports an unknown-command refusal. Observed on 2026-09-06 in a managed repo when minting its first ADR; the source-checkout build has the verb. Either the plugin payload lags the skill it documents, or the skill should state the minimum binary version and the ahoy status should report the gap. Same session also found the intent skill referring to .abcd/config/identity.json and to research/notes/, neither of which ahoy install scaffolds in a fresh managed repo.
- iss-2609061504302157The capture-time scanner redacts an ordinary word when the local account name happens to be that word. On a machine whose account name is a common three-letter abbreviation for development, a capture containing the phrase 'the source checkout's <that word> build' came back with the word replaced by [redacted-user] and redacted: 1 in the JSON. The private-names layer is doing what it was told, but a banned name that is also a dictionary word or a conventional abbreviation needs a word-boundary and context rule, or at least a diagnostic naming which layer and which entry fired, so the author can tell a real leak from a false positive without reopening the file.
- iss-2609061525437969The AI-assistance disclosure convention covers commits only: the COMMITTING rule requires an Assisted-by trailer on AI-assisted commits, but says nothing about pull-request descriptions or issue text, and nothing checks either. In a managed repo two PRs went out with the trailer on every commit and none on the PR body, which the maintainer read as an oversight. Extend the convention to PR descriptions (and issue text written by an agent), teach the guard's GitHub-CLI coverage to require the trailer there, and make the same guard refuse session links and other tool footers — the two halves of one disclosure rule: say a tool assisted, never link the session.
- iss-2609081917287384The transcript store captures only the top-level session transcript; every sub-agent transcript is missed, which is 77 percent of recorded work by volume. The SessionEnd hook reads the single transcript_path handed to it by the host and never enumerates anything, and hooks.json registers no sub-agent event. Sub-agent transcripts are written by the harness to a sibling directory per session rather than inlined into the parent, so no parent transcript contains them: across all 68 session transcripts on this machine the sidechain marker appears zero times, while 968 sub-agent transcript files hold 673 MB against the parents' 206 MB. What the parent retains per sub-agent is only the launch prompt and the returned report; in one sampled case that is two lines standing in for 399, losing every tool call the agent made. The harness ships a SubagentStop hook event whose payload carries agent_transcript_path, agent_id and agent_type alongside the parent session_id, so the capture path can be closed without depending on the undocumented on-disk layout. Storing the result needs a lineage decision the Record schema cannot currently express: it has no parent, agent or type field, and source_kind is closed to native and specstory-import, so the only representable form is overloading session_id with a composite. This store already holds 105 such hand-made composite records, and because Read matches session_id by exact string they are unreachable from a show of their parent session and their agent type is discarded. The loss was time-bounded until now: the harness deletes transcripts on a rolling retention sweep, so material aged out before anything captured it.related itd-2609090559376002
- iss-2609081940398387checkSVGAttr claims an allowlist of drawing attributes but behaves as a denylist: it refuses on* names and scheme-checks href / xlink:href / src, then returns nil for every other attribute, including style and class. Inlined SVG bytes are concatenated verbatim into the published page by assetPipe.render, so those attributes become live markup: inline CSS on the root svg element beats the .svgasset svg and .card .icon svg rules (neither is !important), and a child can position:fixed to the viewport. The same gate already refuses a style ELEMENT (TestAssetsRefuseExecutableSVG); the attribute is untested. No script execution follows: the CSP is script-src self. This is a missed control on the inlining gate, not markup injection in the Markdown renderer. Fix: hold inlined SVG attributes to a closed set covering what the committed drawings actually carry (geometry, paint, id, clip-path, marker-*, refX/refY, aria-*), refusing style and class, with the existing href/src fragment and raster checks kept first; do not sketch an allowlist that omits an attribute process-loop.svg already uses. Detector: extend TestAssetsRefuseExecutableSVG with style= and class= payloads that render must refuse, naming the file, while a committed drawing still inlines. Reported as GitHub issue 621 against ec7f40d6.
- iss-2609081940475662manifest.validate holds home.hero.page and home.chapters[].page to fsutil.ValidRelPath only, and that function accepts .git/config; loadPage then composes whatever the named file holds into index.html through ReadGuardedInRoot, which contains the read to the repo root but does not constrain the selection. The image pipeline documents and tests this exact threat (assetRootPrefix, TestAssetsRefuseAnythingOutsideTheAssetRoot) and positioning already refuses .git surfaces (iss-150), but the site composer did not copy the gate. identity.file and policy.file are not whole-file page sources (heading extract, one-bullet quote). A gitignored .env cannot merge because CI has no file and site-render goes red, and persist-credentials: false keeps the CI .git/config token-free, so the live exposure is bounded; the missing gate is not. .abcd/site.json is not in CODEOWNERS. Fix: refuse page sources under .git/ (case-folded, as the positioning denylist does) and restrict hero.page and chapters[].page to docs/ or site-src/, keeping identity.file and policy.file on their legitimate locations while applying the .git refusal; add .abcd/site.json to CODEOWNERS. Detector: LoadManifest with home.hero.page set to .git/config, to .env, and to a path outside docs//site-src/ must each fail validation, while the committed manifest still loads. Twin of iss-150. Reported as GitHub issue 622 against ec7f40d6.
- iss-2609081940550352LoadAuthorship puts every non-None Assisted-by value into ByModel and registers its colon-prefix as a vendor, then routes any shortlog author whose name equals a vendor key into the Bots and tools row. A conformant trailer whose vendor token is an existing single-token git author name therefore moves that human author whole shortlog count into Bots on /contributors/. The match is exact and case-sensitive. A second, free-form Assisted-by line also publishes as a bar label, because scripts/check-attribution.sh is a presence check (grep -Eq TRAILER_RE) rather than an every-line-conforms check, and underAttributionEscape skips banned tokens on empty data-src spans. Display only, and the trailer stays review-visible. The vendors[au.Name] clause must not simply be dropped: TestAuthorshipSeparatesToolsFromPeople pins the pre-policy tool-author case it implements (iss-2608220150157501). Fix: demote to Bots on a structural machine-identity signal (a [bot] suffix, or a vendor-name match AND a noreply/bot address) so a vendor prefix cannot reclassify a human while Claude at a noreply address and the fixture Assistant author stay in Bots; chart only trailer-shaped values (the attribution grammar including the optional 1m suffix) and clip or drop free-form extras rather than publishing them as labels. Detector: a fixture author named like a human of record, plus an Assisted-by trailer whose vendor is that same name, stays in Humans; TestAuthorshipSeparatesToolsFromPeople still puts Assistant and depbot[bot] in Bots; a free-form extra trailer does not appear as a ByModel label. Reported as GitHub issue 623 against ec7f40d6.
- iss-2609081941073604auditIsMet says in its comment that it reads the Audit Notes rollup, but the body greps every raw line of the intent file for the substring Acceptance rollup:, fenced blocks and frontmatter included, and parses the count with fmt.Sscanf %d, which accepts negatives. A fenced NOT_MET -1 can therefore cancel a real NOT_MET 1 whenever MET is already above zero, featuring an intent whose acceptance is not met. A lone negative does not feature (notMet == -1), newestMetIntent still requires the shipped/ bucket and a written press release, and site check does not re-grade the rollup. strings.Cut is a substring match, not a section walker; the same package already skips fences when splitting headings (Sections). Fix: scan only the Audit Notes section, fence-aware, reusing Sections, and refuse n < 0. Refusing negatives alone is not enough: a fenced Acceptance rollup: MET 1 with no NOT_MET part can still flip a concerns-only rollup that already has notMet == 0. Detector: an intent whose real rollup is NOT_MET 1 plus a fenced Acceptance rollup: NOT_MET -1 must not be featured, while the same intent carrying only the honest NOT_MET 0 / MET 1 rollup in Audit Notes still is, given the other newestMetIntent conditions. Independent of the releaseOf substring match. Reported as GitHub issue 625 against ec7f40d6.
- iss-2609081941074556releaseOf stamps the homepage feature block by strings.Contains of the record id against each CHANGELOG line, with no word boundary, walking newest dated section first. A short id therefore inherits a longer one: on ec7f40d6 releaseOf(itd-9) returns 0.4.1 off the itd-93 credit and releaseOf(itd-1) returns 0.7.1 off itd-130, and a future superstring landing in a newer section restamps the featured id. site check does not validate the stamp. The same package already carries bodyHandleRe. Fix: match the record id at a word boundary (reuse bodyHandleRe, or split the line into tokens); newest-section-first can stay. Detector: a changelog whose newer dated section mentions itd-1990 must not stamp featured itd-199, while a line naming itd-199 as its own id still matches. Independent of the Audit Notes rollup scanner. Reported as GitHub issue 624 against ec7f40d6. <!-- record-lint: illustrative -->
- iss-2609081951416843Setup discovery (ahoy) could probe OpenRouter reachability and, when reachable, offer it to the user as an opt-in code-review oracle — once the OpenAI-compatible api oracle adapter ships, OpenRouter is provider config (baseURL https://openrouter.ai/api/v1 + key), and the offer is an ahoy-time question, never an auto-selected backend.
- iss-2609081953452204The pre-push format gate documented in AGENTS.md is a bare gofmt -l ., which reads whatever Go toolchain the developer has rather than the one CI pins. go.mod declares go 1.26.7 and every CI leg pins go-version 1.26.7, but gofmt from go 1.27 re-indents a multi-value return whose operands are composite literals, so on a 1.27 machine gofmt -l . reports internal/core/ahoy/remote.go against an unmodified checkout of main. The failure is a trap rather than a nuisance: the developer is told the tree is unformatted, reformats the file to satisfy the documented gate, and pushes a file that CI's own gofmt then reports as unformatted in the other direction. Neither direction is detectable from the gate's output, which names a file and says nothing about which toolchain judged it. Fix candidates, none chosen here: pin the gate to the go.mod toolchain (go run mvdan.cc/gofumpt or go1.26.7 gofmt via the toolchain directive), have the Makefile compare the running gofmt's version against go.mod and refuse loudly on a mismatch rather than emitting a filename, or move the format gate into make preflight where the toolchain is already asserted. Detector: on a machine whose default gofmt is newer than the go.mod toolchain, the format gate over an unmodified checkout must either pass or refuse by naming the version skew, never name a file. Surfaced while clearing the site-composer bug-fix branch, where the finding cost two subagents a detour each.
- iss-2609082001204831The attribution gate refuses an AI git identity by name and by vendor address (AI_IDENT_NAME_RE, AI_IDENT_MAIL_RE), which closes the route AGENTS.md cares about: the contributor graph is built from commit authorship, so an AI author puts a tool in the graph and a squash merge then re-appends it as a co-author. Two holes let four commits through anyway. First, the commits arm walks every NON-MERGE commit in the range, so a merge commit's identity is never read; commit 23f0a891 is authored and committed as Claude at a vendor noreply address and stands in main's history today, arriving from an autonomous bug-hunt round whose routine ran with the tool's own git identity. Second, a machine identity that is not an AI vendor matches neither list: three dependabot[bot] commits author dependency bumps directly. The maintainer's rule is that a commit is authored by a human and machine assistance is disclosed by the Assisted-by trailer alone, so the gate's shape is right and its coverage is not. The rule to enforce is refuse-machines-allow-humans, not an allowlist of one name: the repository takes outside contributions through .abcd/work/intake.md and carries one such commit already, and an allowlist would refuse the next one. Fix: read the identity of every commit in the range including merges, and refuse a machine author on a structural signal — the [bot] name suffix the forge stamps, the vendor noreply addresses already enumerated, and the forge bot address shape — while leaving any human author to pass. Detector: a range containing a merge commit authored by an AI identity must fail the gate, a range containing a bot-suffixed author must fail it, a range whose commits are authored by two different humans must pass, and the repository's own history from the gate's introduction forward must still pass. Note the consequence to state in the fix, not to solve here: dependabot pull requests will stop being mergeable as authored, so a dependency bump has to be landed by a human.
- iss-2609090636110810AGENTS.md contradicts the decisions store on how ADR ids are minted, and the stale surface is the one agents read first. The root conventions file states that ADRs keep a hand-numbered filename ordinal and are the one record family where minting from two checkouts still needs a word first. The decide verb's own help says the opposite: the id is a timestamp-numeric stamp allocated through the shared record-id seam, so two branches deciding on the same day cannot collide, with the hand-numbered records grandfathered and every reader admitting both. The contradiction is not inert. In this session it caused a decision to be deferred that was safe to mint, on a coordination risk that adr-45 had already removed, and the deferral was written into a handover note as fact before it was checked. An agent reads the conventions file at the top of every session and reaches the verb's help only if it doubts what it just read.
- iss-2609090642031172The interactive install collects scan_deep through resolveValue with the choice set true|false and then compares the returned string to true, so every other answer becomes false and the deep secret scanner is switched OFF. stdinPrompter.Prompt returns the typed line verbatim and nothing re-checks it against the choices it was handed, so a user who answers yes, y, or Yes to a question about scanning for secrets gets the opposite of what they asked for, with no diagnostic. The three neighbouring slots in the same function abandon the install on exactly this typo rather than persisting it: docs_target and oracle_backend validate through inSet and return a partial install with the comment never persist a typo, and the asymmetry is the defect. The override path applyScanDeepOverride is guarded, so the reachable route is the interactive and collect-missing one, and the gate is narrow: Visibility private, trufflehog on PATH, ScanDeep unset. A silent security downgrade is worse than a refused install, which is the judgement the neighbours already encode. Fix: re-check the answer against the choice set as the neighbours do and return a partial install on anything else, so an unparseable answer never resolves to a weaker scan than the one the operator asked for; consider whether a boolean slot should accept the ordinary spellings of yes and no before it refuses. Detector: resolveValue answering yes for scan_deep must not yield a disabled deep scan, and must take the same partial-install route the docs_target and oracle_backend typo cases take, with the existing false answer still disabling it deliberately. Found while re-scoping iss-33, whose body had recorded this half as fixed; it is not.
- iss-2609090642035097The write boundary now refuses a memory page whose filename carries a hard-fail secret, but a store written before that change is not repaired and the read side cannot report it. The MR001 lint scans stored text and the registry bytes, and a token embedded in a page name such as topic_auth_ghp_ is hidden from it by the same missing word boundary the write-side fix had to work around: underscore is a word character, so an anchored token pattern finds no boundary after the type and domain prefix and the span never matches. A legacy dirty filename therefore sits in the committed tree, in index.md, in log.md and in the registry back-link, and no instrument reports it. The write-side fix deliberately left this alone to keep its commit to one record. Fix: give the read-side scan the same component-wise treatment the write side uses, splitting a page name into its type, domain and slug parts before matching rather than relying on a boundary the naming grammar cannot provide. Detector: a store seeded with a page whose name embeds a token must be reported by the read-side lint, and an ordinary store must stay clean. Surfaced by the fix for iss-2609020321100138.
- iss-2609090715154147The convention is that a decision record is never amended in place: when a decision changes, a new record is minted and the old one is marked superseded by it, so the decision history stays legible and a reader of the old record is pointed forward rather than misled. Nothing in the tree states it. The typed-link vocabulary is recorded in .abcd/development/principles/decompose-before-filing.md as supersedes / reverses / duplicates / refines, and adr-58 and adr-2609021016286571 demonstrate the shape in practice, but the rule that amendment is not an option is carried only by example, so an agent or a contributor reaching for the smaller edit has nothing to read that refuses it. The gap surfaced when a relocation of the transcript corpus made adr-29's stated location wrong and the question of amend-versus-supersede had to be asked rather than looked up. Fix: state the rule where the conventions live, in the AGENTS.md decisions section or as a principle under .abcd/development/principles/, naming the two typed links and the one edit a superseded record does receive, and say why: an amended record erases the fact that the decision changed, which is the thing the record family exists to preserve. Detector: the conventions text names the rule and a docs test or record-lint rule refuses a decisions section that omits it, or at minimum the rule is present where a contributor reading AGENTS.md would meet it before editing a record.
- iss-2609090722466403A staged raw transcript can live indefinitely, and the store's own comment says it cannot. Staging is the one place abcd holds unredacted transcript text on purpose, and its contract is that a staged file survives only until the next session starts. That holds only for a repository someone opens again. The drain runs from the session-start hook of the repository the staged file belongs to, so a repository that is finished with, or merely quiet, keeps its raw transcripts forever. On this machine right now there are four staged files totalling about thirteen megabytes of unredacted transcript, the oldest fourteen days old, and the per-repo status verb reports nothing from any other repository, so standing in one checkout cannot reveal a pile in another. A drain failure compounds it: the staged file is deliberately left in place, correctly, because deleting the only copy would be worse, but nothing ever retires it, so the population of permanently raw files only grows. Three things would close it: a drain that can run while a session is live rather than only at its start, a maximum staged age after which a file is redacted or deleted with a notice, and a cross-repository notice at session start so the pile in the repository nobody is standing in is still visible.
- iss-2609090723023943Ingest resolves a transcript's owning repository from that file's own recorded working directory, which orphans sub-agents whose parent session is perfectly resolvable. A sub-agent that ran in an isolated worktree records that worktree as its working directory, and the harness removes the worktree when the agent stops, so the directory is already gone by the time anything reads the transcript. On this machine that is 51 worktree-isolated sub-agents whose parent transcript still exists and resolves cleanly, plus 191 more whose shared working directory has gone, plus 6 whose directory merely differs from the parent's. Every one of those files carries the parent session id, so ownership is derivable from the session even when the file's own directory is not. Resolving per file is the right rule for a main thread and the wrong authority for a sub-agent. The resolution should try the session first, through the parent transcript's working directory or any store already holding a record for that session id, and fall back to the file's own directory, so that orphan means the session cannot be placed rather than the file cannot. The same assumption reaches the capture hook, which resolves the payload's working directory the way the session-end hook does: when that directory is a removed worktree the detection fails and the hook exits zero having captured nothing, which loses exactly the implementation-lane agents whose work is most worth keeping.
- iss-2609090723027424Summing the token usage reported in a transcript over-counts it, because the harness repeats one response's usage on every content-block line it writes. A single assistant response is written as several lines, each carrying the same message id and the same usage object, so a naive sum multiplies that response's cost by its block count. Measured on one sub-agent transcript here the naive total was 26.7 million against 15.0 million de-duplicated by message id, a factor of 1.77; measured across ten transcripts the same comparison gave 132,336 against 25,046, a factor of 5.28. The factor varies with how many blocks a response happens to have, so it cannot be corrected after the fact by a constant. Any telemetry derived from these transcripts must state the rule that one usage counts once per message id, and must be tested against a fixture containing a multi-block response with a known total. Without that rule a telemetry file is not merely imprecise, it is confidently wrong by a factor that changes between sessions, which is worse than absent for the comparison across runs that such a file exists to support.
- iss-2609090828371674The shared file lock's backoff cap limits staging to roughly ten writers a second, so a burst of simultaneous sub-agent completions loses transcripts. The lock helper backs off exponentially to a hundred-millisecond ceiling, so the rate a contended lock admits is set by that ceiling and not by how short the critical section is. Measured here, sixteen simultaneous stages take 2.12 seconds, consistently across three runs. Extrapolating the same rate, a burst past roughly forty to fifty simultaneous completions begins exceeding the five-second staging lock timeout, and a stage that times out is refused: the transcript it carried is not written anywhere, which is the loss the capture work exists to prevent. Sessions that fan out widely are exactly the sessions whose delegated reasoning is most worth keeping, so the ceiling bites hardest where the value is highest. The condition is pre-existing in the locking helper rather than introduced by sub-agent capture, but nothing reached the lock concurrently before, so it was unreachable in practice until now. The remedies are design-shaped and should be chosen rather than assumed: raise the timeout, lower the backoff ceiling, sharded locks keyed per agent, or a lock-free append with reconciliation at drain.
- iss-2609090932441377Raising the single-line PEM opener bar from sixteen characters to forty removed coverage that the previous bar had. An open block, one carrying no END marker, whose visible body is a single line between sixteen and thirty-nine characters followed by any non-body line is no longer redacted, where it was before. The reachable shape is a real one rather than a contrived one: a private key re-wrapped to a narrow column by a mail client or a terminal, or truncated by a log rotation, leaves a header and one short line, and MIIEowIBAAKCAQEA, the canonical opening bytes of a DER-encoded RSA key, then survives verbatim. The failure is silent in the worst way, because the stage-two rescan through BlockingResidual reports no findings and the header pattern still fires, so the store records that a PEM secret was handled while a fragment of the key remains in the text. The argument the change rested on, that no canonically rendered body line falls under forty characters because RFC 7468 mandates sixty-four and OpenSSH writes seventy, is true only of an untruncated and un-rewrapped block, and a truncated or narrow-rewrapped paste is precisely the shape a transcript redactor exists to catch. Three independent adversarial reviews found this, one grading it critical. The fix must restore the lost shape without restoring the defect the raised bar was closing, which was a mentioned header opening a block on any sixteen-character word: the pair rule already distinguishes a wrapped body from prose, so the single-line path needs a discriminator that is not width alone. Detector: a header followed by one body line of thirty-two base64 characters and then a prose line must redact that body line, the two-consecutive-narrow-lines case must keep redacting, and the mentioned-header-plus-fenced-identifier case must still be left untouched.
- iss-2609090934372160A real_name whose literal is a short single token is dropped by the byte scan as chance noise, so a banned name in binary metadata is not a finding there while the same name in text is. byteScanPolicy carries byteScanLongLiteral at eight, and the threshold counts bytes rather than runes, so a four-rune CJK name passes as long while a seven-byte Latin one does not. The consequence is a name in a PDF Author field or an EXIF artist tag reaching a published payload unreported. Decoding containers does not touch this: a decoded region is scanned with the same byte rules, so a short name inside a zip entry is dropped exactly as in raw bytes. The threshold exists to hold down a false-positive rate on binary bytes, where a short Latin token appears by chance, so simply lowering it trades one defect for another. Closing it needs an anchored context that makes a match meaningful rather than incidental, a PDF Author key or an EXIF artist tag read structurally, or an accepted false-positive rate stated as a decision. Detector: a banned short single-token name placed in a PDF Author field must be reported by the payload scan, and a byte-identical run over binary content carrying the same token incidentally must not flood the report. Split out of iss-2608291832160371, whose container half shipped separately; this half was never addressed by it.
- iss-2609090947359464discoverRepoRoot is the unhardened twin of the rules-root resolver that was hardened in the same batch. Its git call is properly isolated, and its own comment explains why: an inherited GIT_WORK_TREE or GIT_DIR would redirect discovery at a different tree. The fallback beneath that call has neither guard the sibling grew. Where git will not answer, the loop walks upward accepting any directory whose git entry merely exists, with no shape check of the kind plausibleRepository performs and no ownership check of the kind foreignOwnerRefusal performs, so an empty directory named for the marker in a shared ancestor, or a real repository another uid laid there, would bound the ledger root exactly as it bounded the rules root before that fix.
- iss-2609090951276167The attribution gate states its rule as refuse machines and allow humans, and implements the machine half structurally rather than nominally: a name ending in the forge-stamped bot suffix, a mailbox carrying that suffix, or one vendor domain. Its comment claims a second automation lands in the right place with no edit here, which holds only for automations the forge itself stamps. An identity such as semantic-release-bot with a forge no-reply address matches neither the AI name list nor the AI mail list, neither machine pattern, and not the author-only no-reply rule, so it is judged a human and the gate exits clean; verified by reading the four patterns against that identity. Self-hosted release automation, CI bots committing under a plain configured name, and any forge whose suffix is not the one hard-coded here all land the same way, and this gate is the only thing standing between them and the contributor graph the rule exists to protect. It matters because the rule was written after a bot walked past the nominal list, and the structural replacement inherits the same enumeration in a different alphabet. Fix direction: widen the structural signal beyond one forge suffix, whether by treating a trailing bot or automation token in the name or local part as machine-shaped, by keeping an automation mailbox list beside it, or by requiring a positive human signal, and say in the comment which shapes remain out of reach. Detector: a commit authored as semantic-release-bot with a forge no-reply address must be refused as a machine, while an outside human contributor with a forge privacy address still passes.
- iss-2609090951277880auditIsMet was narrowed to read the Audit Notes section fence-aware and to refuse a negative count, but it still walks EVERY section whose title is Audit Notes and accumulates the met and not-met counts across all of them, with no first-wins rule and no refusal of a duplicate title. An intent record carrying an honest concerns-only rollup plus a second section with the same title, at any heading level, holding a rollup that reads MET 1 therefore ends with met above zero and not-met still zero, and is lifted onto the homepage feature block: exactly the outcome the fence-awareness was added to prevent, reached by duplication instead of by fencing. Verified by reading the accumulation loop, where the title comparison is an equality test inside a loop over all sections and nothing breaks after the first match. It matters because the record body is the input the site trusts for the one testimonial the homepage carries, and a forged section is no harder to write than a forged fenced line was. Fix direction: read the FIRST Audit Notes section only and treat a second one as malformed, the same way a negative count is already treated as malformed. Detector: an intent whose honest Audit Notes rollup is concerns-only, plus a second section titled Audit Notes carrying a passing rollup, must not be featured, while the same intent with one honest passing rollup still is. Residual of iss-2609081941073604.
- iss-2609090951279243The site manifest now holds its two whole-file page sources to a closed allowlist of the documentation and site-source roots, on the stated ground that a denylist of the git directory and the environment file leaves the gitignored local tier, the private record and every file a future contributor adds still reachable. The quote-type path fields did not get that treatment: identity.file, ui_strings, the deferred feature quote paths, the contributors policy file and the unresolved-reference baseline each pass the relative-path check and then only the git-directory refusal, so a committed manifest naming a dotenv file or a path under the gitignored local tier loads without complaint. The policy file is the one that renders: when its part is anything other than first-bullet, policyQuote renders the ENTIRE matched section of the named file, not one bullet, into the published contributors page, so a manifest pointing it at a local scratch file with a matching heading publishes that file verbatim to the public site. Verified by reading the five call sites and policyQuote. It matters because the manifest travels with a clone and the site is public, so the weaker gate is the one an unreviewed manifest edit reaches first, and the closed set was adopted next door precisely because a denylist cannot anticipate the next reachable file. Fix direction: put every path field the build reads through the same closed page-root set the whole-file sources use, or state per field why a wider set is safe there. Detector: a manifest whose contributors policy file names a path outside the page roots must be refused at load, while the committed manifest still loads.
- iss-2609090951280114releaseOf now compares whole handles found by the package handle pattern rather than testing a substring, which stops a digit continuation such as itd-1990 from being read as a credit for itd-199. That pattern ends in a word boundary, and a hyphen is not a word character, so a hyphen-suffixed compound still yields the short handle as a match: run over the line renamed branch fix/itd-199-cleanup the pattern returns itd-199, and because the walk takes the newest dated section first, such a mention in a newer section out-stamps the real credit in an older one. Verified by running the shipped pattern over that line and over itd-1990, which correctly returns only the long handle. Dormant today, since the committed changelog carries no such compound token and nothing is mis-stamped now, and recorded because branch names, file stems and run ids of exactly that shape are ordinary changelog prose and the failure would be silent on the day one lands. Fix direction: require the character after the handle to be neither a word character nor a hyphen, or compare against the record ids the export already knows rather than against any handle-shaped token. Detector: a newer changelog section mentioning a hyphen-suffixed compound built on a handle must not stamp that handle, while a line naming the handle as itself still does. Residual of iss-2609081941074556. <!-- record-lint: illustrative -->
- iss-2609090951282192The memory write boundary refuses a page filename carrying a hard-fail span, and the ruling that ordered it asked for a bar narrow enough that an ordinary slug is not refused: secrets only. The delivered bar selects on the scanner hard-fail severity, and the scanner puts three kinds there rather than one, a secret pattern, a banned real name, and the caller's own local machine account name. The function comment says so plainly, so the width is disclosed rather than hidden, but it is wider than the ruling. The consequence is a refusal the author cannot act on: on a machine whose account name is an ordinary word, an ordinary page whose slug carries that word at a hyphen boundary is refused at ingest with a message telling the author to repair the slug at the source, when what matched was the machine account rather than anything in the page. That collision is already recorded against another surface as iss-2608291444328326, where the same rule turned the release payload gate red on a pristine tree until the home directory was pointed at an alias. It matters because a memory write is the one path here with no workaround: the page cannot be written under the name the distiller chose, and the remedy the message names is not the remedy. Fix direction: hold the filename to the secret patterns alone, as the ruling asked, or keep the identity kinds and make the refusal name which kind matched so an author can tell a collision from a leak. Detector: with the caller account name set to an ordinary word, an ordinary page whose slug contains that word must still write, while a page name carrying a token body is still refused.
- iss-2609090951283654The user-scope declaration reader now exists twice, hand-kept: trustedRootDeclared in the rules resolver and localDeclared in the transcript-store locator run the same five checks in the same order, an lstat for a regular file, a refusal of group or world write, a requirement that the caller own it, a read through the guarded reader under a byte cap, and a comparison of each absolute entry against the target in both its written and its symlink-resolved spelling under the platform fold. Each also carries its own ignored-declaration renderer and its own verbatim copy of resolveOrClean. They have already diverged in one place: the rules copy owns a local ownership seam so a test can force a foreign uid, and the history copy calls the canonical lookup directly, so the refusal branch is provable in one package and not in the other. It matters because this is a trust boundary whose next hardening, a caller-owned parent requirement or a same-file re-check between the ownership stat and the read, will land in whichever copy the fixer happens to be looking at, and the omission compiles green in both. Fix direction: lift the reader into one primitive taking the declaration location and the value to match and returning the verdict plus the ignored-declaration reason, and have both packages call it. Detector: a change to the declaration reader checks must be visible to both callers through one definition, so a test that removes a check fails in both packages.
- iss-2609090951287096The format gate resolves the pinned toolchain by capturing the go environment query for the toolchain root with stderr merged into stdout, so on the first run on a machine that does not yet have the declared toolchain cached, the download progress line is prepended to the captured value. The executable test on the resulting path then fails and the target refuses, saying the toolchain could not be resolved and the fetch needs network, while the fetch has in fact just succeeded. Reproduced with an uncached toolchain in an isolated module cache: the captured value comes back as two lines, the first the download notice and the second the real root, and the executable test on that value is false. A second run succeeds because the toolchain is now cached, so the gate self-heals, but the failure lands on the run that matters most, on a new machine or a fresh CI image, and it diagnoses the opposite of what happened. It matters because this loud refusal was chosen deliberately over a silent fallback, and a loud refusal naming the wrong cause spends the trust that choice was buying. Fix direction: capture stdout alone and leave stderr for the diagnostic, or take the last line of the captured value, and make the refusal distinguish a fetch that failed from one that merely printed. Detector: with the pinned toolchain absent from the module cache, the format gate must resolve it and run, not refuse.
- iss-2609090951287232The same review that made the audit rollup reader fence-aware left the changelog credit matcher reading raw lines: releaseOf splits the changelog on newlines, tracks the dated headings, and asks whether each line credits the handle, with no fence state at all. A handle mentioned inside a fenced block, a shell example, a sample record or a quoted diff, therefore counts as a credit, and because the walk takes the newest dated section first, a fenced mention in a newer section stamps the featured record with that section version instead of the one that actually shipped it. Verified by reading the loop: the only per-line branch is the dated-heading test, and the same package already carries the fence-aware section walker the rollup reader was moved onto in the same change. It matters because the version stamp is the homepage claim about when a promise was delivered, and the failure is silent, rendering a plausible wrong version rather than nothing. Fix direction: give the changelog walk the same fence tracking the rollup reader has, or read the changelog through the shared section walker rather than by hand. Detector: a handle appearing only inside a fenced block in a newer changelog section must not stamp that section version, while a prose credit in an older section still does. Residual of iss-2609081941074556.
- iss-2609090951291524Every capture verb hands the caller's working directory to the core as the repo root, verbatim and unresolved: the status, list, resolve, promote, wontfix and disposition commands each build their request with the working directory, and the fast-path capture does the same, so the core takes the explicit-root branch and never consults the git-aware discovery helper that sits behind it. A verb run anywhere but the checkout root therefore addresses a ledger that is not there. Reproduced: from a package directory two levels down the status render reports open 0, resolved 0 and wontfix 0, while the identical binary run from the checkout root reports open 365, and neither run says anything is wrong. The write half is worse than a wrong answer, because the directory tree is created on demand: a capture run from a subdirectory mints a second ledger under it, writes the record there, and reports success with a path the author will not read as unusual, so the record is filed where nothing looks for it and a stray dot-abcd tree appears in a source directory. Confirmed by running the shipped binary in a plain directory that was not a repository at all, where it created the full ledger skeleton and wrote thirteen records into it. The reading verbs get this right and resolve the toplevel first, which is what makes this an omission rather than a design. One further limb is real but currently inert here: the ledger redactor builds its scanner from the root it is handed and the scanner reads the per-repo pattern override two directories down without walking up, so a capture from a subdirectory is redacted with the built-in defaults alone; this repository carries no such override today, so nothing is under-redacted now, and any managed repository that adds one is. iss-2609020224230967 is adjacent and states that the capture package does this correctly, which is true of the core helper and false of the front door that never calls it. Fix direction: resolve the checkout root once at the surface, the way the reading verbs already do, or let the core discover it by passing no root and hardening the helper that then runs. Detector: a capture verb invoked from a subdirectory must address the checkout root ledger, and must refuse rather than silently mint a new store when there is no ledger and no repository.
- iss-2609090951291799The format gate exists because two gofmt versions judge a tree differently, and it goes to some trouble to derive the toolchain version from the go directive in go.mod so that one declaration governs. The workflows then declare it again: nine setup-go steps across four workflow files pin the version as a literal string, four of them in the CI workflow and the rest in the release, site and screenshot workflows. The action already accepts a reference to the go.mod file in place of a literal, which is the form that removes the second spelling. Verified by grepping the workflow tree. It matters in exactly the direction the format gate was built for: bump the go directive and forget one of the nine, and CI compiles and tests on the old toolchain while the format gate resolves and fetches the new one, so the gate and the lane disagree about which gofmt is correct, reintroducing at the CI boundary the skew the gate refuses to allow locally. Fix direction: replace every literal pin with the go.mod file reference so the go directive is the only place the version is written. Detector: a change to the go directive in go.mod must change which toolchain every workflow job runs, with no workflow edit.
- iss-2609090951295881The ideate verdict recorder states its redaction discipline in the stage-two refusal type: a refusal that quoted the span it refused would publish the leak into the error message, and from there into a terminal and a log, so that error names the finding kinds and nothing else. The enum refusals in the same file do the opposite. Five sites, the verdict, the leg kind, the claim status, the grill relation and the kill outcome, interpolate the offending value into the message after passing it only through the terminal-escape cleaner, which strips control sequences and does not redact. Every one of those fields arrives in the host payload alongside the free-text fields the recorder does redact field by field, so a payload whose status field carries a token or a home path is refused with nothing written and that value printed verbatim to the error surface, where the session transcript and any capture outside abcd take it raw. Verified by reading the five call sites. It matters because the file argues at length that a fail-closed promise is only honest if the refusal itself carries nothing, and these five refusals are the exception nobody wrote down. Fix direction: describe the offending value rather than quoting it, since its length and whether it is empty is enough to fix a typo, or route it through the same field redactor the prose fields already use before it reaches the message. Detector: an ideate payload whose enum field carries a token-shaped value must be refused without that value appearing anywhere in the error text.
- iss-2609090951297149Both user-scope declaration readers call the exported case-folding predicate directly when comparing a declared path against the target: the rules resolver and the transcript-store locator each ask whether the filesystem folds case and then compare under that answer. Two sibling packages hold the same predicate in a package-level variable for the stated reason that substituting it is the only way a test can exercise the branch, and the path utilities package keeps one for its own redactor. Neither of these two does, so on a case-sensitive host the fold-equality branch of the declaration compare is unreachable by any test, and what it does with a case-variant spelling of a declared root is pinned nowhere. Verified by grepping the seam: it exists in the path utilities, the ahoy package and the update package, and not in rules or history. It matters because the declaration is the opt-in that re-admits a foreign-owned checkout, so a fold bug there either silently admits a root the caller never declared or silently refuses one they did, and the case-sensitive CI leg would show neither. Fix direction: hold the predicate in a package variable in both packages, exactly as the two siblings already do, and add the case-variant declaration case each seam makes possible. Detector: with the fold predicate forced on, a declaration written in a case variant of the target must be honoured, and with it forced off it must not.
- iss-2609090953184203The store redactor's filename judge misses every credential whose own prefix straddles a page-name separator. judgeFilename judges the joined filename and, separately, the type, domain and slug that pageNameRe parses out of it, the components being judged because an underscore is a word character and an anchored token pattern therefore finds no boundary after a prefix like topic_auth_. But the component split is itself on underscore, and a credential prefix ends in one, so a name whose separator falls inside the token is invisible to both passes at once. topic_ghp_ followed by thirty-six alphanumerics parses as type topic, domain ghp, slug of thirty-six: the joined form has no word boundary before ghp, the domain alone is three letters, and the slug alone carries no prefix, so nothing matches and the write is accepted. A stripe live key splits the other way into domain sk and slug live_ plus its body, and an sk-ant- key splits on an underscore inside its own body. The consequence is the defect the filename judge was added to close, left open for every spelling that straddles a separator: the token reaches the committed tree as the file's own name, in index.md, and as the registry back-link, with every write-side gate green, and the read-side MR001 lint is blind to the stored bytes for the same missing-boundary reason, so nothing downstream reports it either. Re-joining adjacent components does not close it, because slugRe admits an underscore and a token can therefore begin at an underscore inside the slug, a position no pair of parsed components starts at. Nor can the separators be normalised away, because the prefixes ghp_, sk_live_ and github_pat_ contain the very character that would be removed. The fix is to judge every position at which an anchored pattern could match if the underscore were a boundary, the joined name together with every suffix beginning after an underscore, rather than trusting a split that falls exactly where the missing word boundary is. This is a question of where the patterns are matched and not of which severities count: the bar stays scanner.SeverityHardFail, whose own width is a separate record and a separate decision. Detector: a page named topic_ghp_ plus thirty-six alphanumerics and one spelling a stripe live key across the domain and slug boundary must both be refused with the refusal naming the page and no file, index line, log event or back-link left behind, the topic_auth_ghp_ control must stay refused, and an ordinary page whose domain is a short real word such as api, git, or ghp itself must still write.
- iss-2609091009111294The ledger's human gates block the ordinary intent flow before the product thinker's language exists: intent ready refuses on scope conditions, mechanism claim and grounds, capture promote and resolve refuse without --grounds, and a lapse capture refuses without --lapsed-at. Each check should report, never refuse, until the rethink of the reading work settles what a human is asked for.
- iss-2609091037191879A release cut in progress is invisible to every other session, so a change landing on main during a cut is discovered in the changelog rather than chosen. abcd should let launch declare a cut lease that peer sessions, merges and record closes can see: a session about to merge or close a record during a lease is told which cut it would join and who is cutting, and the cutting session rules on the ordering. The convention is in AGENTS.md (concurrent sessions); this seeds the mechanical form, alongside session presence (iss-2608220750029993) and itd-33.related itd-2609151838312703
- iss-2609091046297503renderCut passed a refusal reason through the terminal sanitiser before splitting it on newlines, and the sanitiser masks a newline to a question mark, so the split found nothing to split and every multi-line reason printed as a single run-on line with question marks where its line breaks were. The reasons affected are the ones a reader most needs to act on: the surface guard's list of what narrowed since the anchor tag, the stale-intent refusal, and the findings gate's enumeration of the records blocking a cut, each of which is written as a heading plus one indented line per record and each of which arrived as one unreadable paragraph. Nothing was lost from the payload, so the JSON envelope carried the reason correctly all along and only the terminal render was affected, which is why it survived unnoticed: the machine-readable surface was right and the human one was not. The sanitiser has a sibling built for exactly this, SanitizeBlock, which neutralises a control sequence while leaving the line structure intact, so the fix is to route a multi-line reason through it and to keep the single-line sanitiser for values that are genuinely one line. Detector: a refusal whose reason carries newlines must render as that many lines with no question-mark substitution, and a single-line reason must render unchanged. Found while adding the release findings gate, whose own six-line refusal was the render that made it visible. The detector this record names is `TestRenderCutKeepsAMultiLineRefusalsLineStructure` and `TestRenderCutLeavesASingleLineRefusalUnchanged` in `internal/surface/cli/rendercut_refusal_test.go`, written on 2026-09-09 — the fix landed without one, so the record described a test that did not exist. A third, `TestRenderCutStillNeutralisesAControlSequenceInARefusal`, holds what the single-line sanitiser was there for: keeping the line structure must not also let an escape sequence through.
- iss-2609091126475539The PATH rung of every hook shim is owned-only: it runs an abcd off PATH only when ~/.abcd/path-entry records the exact path `command -v abcd` printed, and two documents promise the install verb writes that record — the install guide says "the install one-liner writes that record, and so does abcd's own install verb", and the ahoy chapter says "the install one-liners and `ahoy install` both write it". It writes it on one of its three install paths. writePathEntry has a single install-time call site, inside the owned-copy branch, and that branch is reached only when a verified cache artefact exists to copy from; without one, install degrades — loudly, and by design — to the pinned symlink, which records nothing, and --dev writes its shim with no record either. Verified by grepping the writer's call sites and by installing along each path into a sandboxed home. The failure is silent in both directions, because the symlink is classified by its destination rather than by the record: ahoy reports a healthy pinned install while every hook prints "ignoring the abcd found on PATH ... ~/.abcd/path-entry does not record it as the abcd installed here" and takes its degraded route — no rules loader, no shell guard (the PreToolUse rung reports UNGUARDED and refuses rather than approving), no transcript capture. It matters because the degraded path is documented behaviour rather than an edge case: the install guide routes readers to it twice, so a user who did exactly what the guide said holds an install the board calls healthy and the hooks refuse, with nothing on either surface connecting the two — and the remedy those surfaces offer cannot run, since an install with zero actionable gaps returns already_up_to_date without ever building an apply context, so re-running the install verb on such a machine writes nothing. Fix direction: record every entry abcd installs, through the one existing writer — the symlink under the link's own path, which is the spelling command -v yields and the shim compares, and the dev shim on the same terms, since it is a documented verb leaving a usable binary in the same user directory abcd blesses; raise a gap for an owned entry no record names, so the advertised re-run has something to act on; and drop the record when uninstall drops the entry it names, or whatever occupies that path next inherits the ownership claim. Detector: after each install path that leaves a usable abcd on PATH, ~/.abcd/path-entry must record that entry under the spelling a hook shim's `command -v abcd` prints, and no install shape may classify healthy while the shims refuse it.
- iss-2609091128354325AGENTS.md's definition of done now asserts that the format gate resolves gofmt from the toolchain go.mod declares and never falls back to the local gofmt, but two of the three places that actually run the gate still invoke a bare gofmt -l . The release workflow's verify job (.github/workflows/release.yml:105-113) reads whichever gofmt PATH resolves and, on failure, instructs gofmt -w ., the command the pinned target replaced; the scaffold template it is rendered from (internal/core/launch/scaffold/templates/release.yml.tmpl:126-134) carries the identical block, and abcd launch scaffold writes that block into every managed repo. The existing detector, TestFormatGateResolvesThroughTheDeclaredToolchain, checks ci.yml's step, the Makefile recipe and four prose surfaces and stops there, so neither workflow copy was ever in its roster. This is live in exactly the direction the gate was built for: a release cut on a runner whose PATH gofmt differs from the declared toolchain either passes a tree CI rejects or names a file nobody can reproduce, and a managed repo receives the unpinned form as its starting position with no Makefile target of ours to invoke instead. Two comments in the same class still name the retired command: .github/workflows/ci.yml:7 and .githooks/pre-push:18. Fix direction: the release verify job invokes make fmt-check the way ci.yml already does, and the bare template, which has no Makefile of ours to call, resolves gofmt out of the GOROOT of the toolchain the module declares. Detector: no shipped workflow and no scaffold template may invoke a gofmt that PATH resolves, and the roster must be derived from the tree rather than listed.
- iss-2609091128479544internal/fsutil is the declared home for directory validation, and .abcd/development/principles/one-canonical-primitive.md names that primitive in its rule list: a second copy is a flagged consolidation target, a third is forbidden. There are three ensureRealDir implementations at this tip. internal/core/lifeboat/voyage.go:115 and internal/core/history/location.go:175 are near-identical (os.Mkdir at 0o700 followed by fsutil.IsRealDir, differing only in the error each returns), and the history one was added this cycle, so it is the copy that crossed the line the principle draws. internal/core/intent/lifecycle.go:824 is the divergent variant: an Lstat symlink check followed by os.MkdirAll at 0o755, whose own doc comment records that a symlinked ANCESTOR is not caught. The third copy is therefore not mere duplication but the weakening the principle predicts: the intent variant's guarantee is strictly weaker than the other two, the difference is invisible at its five call sites, and a hardening landed in either of the other homes reaches none of them. The principle's Promotion clause asks for a check over private redefinitions of the canonical names, and internal/fsutil/canonical_test.go's TestNoNonCanonicalAtomicWritePrimitives is exactly that check for writeFileAtomic, durableWrite, isRealDir and createExclusiveIn; ensureRealDir is simply absent from its name list, which is how three copies accumulated under an armed detector. Two accepted decision records now bless the divergence rather than flag it: adr-2609090717039680:56-60 presents the local helper as a virtue and adr-2609091014087993:71-73 commits a future worktree store to a fourth copy. Fix direction: one primitive in internal/fsutil that takes the create mode as a parameter, because 0o700 for a private store under the caller's home and 0o755 for a record directory in a shared worktree are both legitimate and must not be silently unified, plus a chain form that verifies every level it creates so the intent variant's documented ancestor gap closes rather than being carried forward; and ensureRealDir joins the canonical-primitive detector's name list so a fourth copy cannot land quietly.
- iss-2609091129426411adr-2609091014087993 says two things about `AGENTS.md` that cannot both be read at face value. Among its normative clauses, in the present indicative: "`AGENTS.md`'s concurrent-sessions convention names the store as the place a session's worktree goes, and names no sibling-directory form." Among its Consequences: "The concurrent-sessions convention gains the store as the place a worktree goes, and loses any wording that reads as a sibling directory. That edit lands with the intent, because a convention naming a verb that does not exist is a phantom gate." The first states as fact what the second schedules, and when the ADR was accepted neither was true of the file: § Concurrent sessions was byte-unchanged, named no store, and treated creating a worktree inside the checkout as ordinary — the shape the ADR rejects as its alternative 2.
- iss-2609091143455568GuardFindings decides whether a finding has been answered by asking only whether its id is still under the open bucket at HEAD, so deleting the record clears the gate as effectively as resolving it. Every legitimate route leaves a trace the next reader can follow, a resolution, a wontfix, or a deferral with its reason, and the illegitimate one leaves nothing at all, which makes it both the cheapest way past the gate and the only way that destroys the finding rather than answering it. The issue-resolution gate refuses exactly this shape already, RS001 holding that a bare delete of an open record satisfies no trailer, so the two gates disagree about what counts as an answer while sitting in the same release path. The fix is to ask the question the sibling gate asks: a record present at the anchor and absent at HEAD is a deletion rather than a disposition, and the gate should refuse it and name it, since a record that entered the ledger and left it without reaching a terminal folder is the one case nobody can audit afterwards. Detector: a cut whose only change to a blocking record is its deletion must refuse, naming the record and the deletion, while a resolution, a wontfix and a deferral each continue to clear it. Found by adversarial review of the gate's own release; deferred rather than fixed in that cut because the fix belongs with the gate's own hardening and the release it would have blocked is the one that introduced it.
- iss-2609091155497399Reconstruct loads every record's full body even in the mode whose whole purpose is to not render them. The thread loader reads each record body into memory for every thread in a session before the renderer consults the mode, so the spine mode, which reduces each delegate to its opening instruction and closing turn, still pays the full memory cost of every delegate it is about to discard. It is bounded per file by the record read cap rather than unbounded, and the largest main thread observed is well under that cap, so this is a ceiling rather than a leak: a session with a few dozen verbose delegates near the cap could still hold most of a gigabyte resident before the first byte is elided. The ingest path in the same package takes the opposite approach deliberately, processing one transcript at a time and discarding the bytes after probing, because the corpus it walks is far larger than memory. The fix is to let the mode reach the loader, so a spine run decodes only the head and tail turns of a thread it will summarise. Not urgent while sessions stay at the observed fan-out, and worth doing before a session with wide delegation is reconstructed on a small machine.
- iss-2609091155525689Two accepted decision records describe the directory primitive as it stood before the consolidation, and this repository supersedes rather than amends, so each owes a correction rather than an edit. adr-2609090717039680 (the transcript corpus is a sibling store that creates itself) names ensureRealDir as a helper of internal/core/history and presents its behaviour — walks the chain top-down, os.Mkdir per level rather than MkdirAll, re-verifies every level on every resolve — as a property of that package. Every one of those behaviours still holds, and the symbol does not: it is fsutil.EnsureRealDir, called in a loop, and the package that used to own the sequence now owns only the layout. A reader following the ADR to the code finds nothing at the name it gives. adr-2609091014087993 (a tool never creates directories in user-owned project space) commits a future machine-scoped worktree store to creating itself one level at a time, never through a symlink, exactly as the transcript store does. That sentence is now satisfied by calling the canonical primitive, and it was the reading of it that would have produced a fourth copy: it describes a mechanism where it could name the thing that implements it. What is owed is one correction record covering both — the mechanism is unchanged, the home moved, and a store that wants this behaviour calls internal/fsutil rather than reproducing it. Detector: an ADR that names a package-local symbol should not survive that symbol's removal, which no gate currently checks; the record-lint rule family has no cross-reference from decision prose to Go identifiers.
- iss-2609091215552981TestPNGChunkCountBombIsBounded proves the payload scan refuses a decompression bomb, and it proves it by timing the run: it measures elapsed wall clock and fails past ten seconds. Under the race detector the same run takes fifteen times as long, so the test reports the chunk loop as unbounded at about twenty-three seconds where it takes about one and a half seconds plain, and the failure message asserts the opposite of what the result it prints shows, because the very same result carries the refusal the bound produced, naming more than the permitted number of compressed chunks. The lane this breaks is not an optional one: make preflight runs the race-enabled internal tests and CI runs them on macOS and Linux both, so the branch that added the test cannot pass its own gate on any machine, and the redness says the security control failed when the control worked. A wall-clock assertion also cannot distinguish a slow machine from a broken bound, which is the distinction the test exists to make. Fix: assert the bound rather than the duration, since the scan already reports why it refused, and keep a duration assertion only if it is scaled for the race detector or skipped under it, so the test measures the property it names. Detector: with the chunk bound removed the test must fail on the missing refusal, and with the bound in place it must pass both plain and under -race on a machine where the plain run takes one second and the instrumented run takes twenty.
- 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-2609091258115663Three range-scoped gates derive their base from the pull-request event or the push event and fall back to nothing, so on a merge-group event they skip themselves and say so. The expression is the pull request base sha or the push before sha, and the workflow's own comment beside it acknowledges that a merge-group event carries neither; the log of a real queue run shows the consequence in the gates' own words, that there is no usable base ref for this event so the range checks are skipped. The gates that go quiet are the issue-resolution range check and the decisions-append check, and the run that skips them is the one that actually gates the merge. That inverts the protection: the queue entry is the only run that sees the final base after a competing pull request merged ahead of it, which is exactly the race a range check exists to catch, and it is the run where the check does not happen. A pull request whose base was clean when it was armed can therefore merge a resolution that a competitor made terminal while it waited, and every earlier run reported green on a base that no longer existed. The event carries the field the expression needs: merge_group.base_sha names the queue entry's base, so extending the fallback chain to it closes the hole without loosening anything. Detector: a merge-group run must resolve a base ref and run the range checks, and the checks must fail a queue entry whose competitor made its record terminal first, while a pull-request run keeps resolving the base it resolves today.
- iss-2609091433422134RS001 refuses correctly on a merge-queue collision and explains it wrongly. When a competitor lands a record's resolution while this entry waits in the queue, the record is already terminal at the entry's base, so it never enters a terminal folder across the range and the trailer is refused, which is the right verdict. The message the refusal carries is the stale-branch one, saying the record already sat in the resolved folder before this branch diverged and advising that the trailer be dropped. The probe behind that wording walks the range from the head back to the base, and in the queue the base is always an ancestor of the head, so that walk is empty and the stale-branch arm is the only one selectable there; the competitor's landing is therefore reported as pre-divergence history that never happened. The cost is a wrong remedy at the worst moment: an author told the record was terminal before they branched will drop a trailer that is correct and re-push, where the real answer is that someone else resolved it while they queued and the two changes need reconciling. The gate only became reachable in the queue when the range gates started resolving a base there, so the arm has never been exercised on this shape. Fix: give the probe a branch that recognises a base that is an ancestor of the head and name the competitor's landing, so the message distinguishes a record that was already terminal when the branch was cut from one that became terminal while it waited. Detector: a queue-shaped range whose record went terminal after the branch point is refused with a message naming the landing rather than the divergence, and a genuinely pre-divergence record keeps the message it has.
- iss-2609091525588599The release gate's semantic cross-check ran at full tier against the v0.8.0 content commit and returned 246 discrepancies between the brief's surface prose and what the binary and the tree actually do. All thirty-seven checkers reported: every pinned chapter and every real surface. The classes are one hundred and thirty-eight false claims, forty-two undocumented surfaces, thirty fictional layouts, twenty-seven stale counts and nine criterion violations, and the weight sits in the chapters that count or enumerate rather than describe: the verification matrix at thirty-seven, the configuration chapter at twenty-three, the naming constraints at eighteen, prompt quality at fourteen and the build sequence at twelve. The findings are specific rather than stylistic. The ahoy chapter states that every sub-verb also ships on the CLI, where the status sub-verb does not exist there and the chapter's own machine-checked table already omits it, so the prose contradicts the table beside it; it points a reader at an ahoy-state.json shape that exists nowhere in the tree and cites a chapter that documents no such shape; it says a remote apply that changed nothing exits non-zero, where two such statuses exit clean and one of them is the idempotent re-run the same paragraph promises. The merge-hygiene block is read from the forge, emitted in the JSON envelope and written into the committed mirror, and its name appears in no markdown file in the repository. Almost none of this arrived with the release under cut: it is accumulated drift, surfaced now because a breaking release is the impact class that requires both directions over the whole chapter list, and because nothing else runs this comparison. The maintainer has ruled that the release holds until the record matches the software. Detector: the cross-check at full tier returns no discrepancy for a chapter whose claims a reader can check against the binary, and the run that gates a release is the one that says so.
- iss-2609091611458541The change that parks the ledger's human gates edits the intent and capture surface chapters, both command pages and the generated reference, and the maintainer has ruled it out of the v0.8.0 release. The brief correction this release performs therefore fixes those two chapters against behaviour that the parking will change immediately afterwards: the intent readiness report will gate on four rows rather than seven with three rendering advisory, the promote and resolve verbs will stop refusing an absent grounds entry, and a lapse capture without its instant will record none rather than refuse. Nothing is wrong with either change on its own; the cost is that the two chapters are corrected twice and the semantic cross-check that clears a release has to run again over them, because a receipt names the commit its reviewers read and cannot vouch for prose written after it. The order was chosen deliberately and with the cost stated, so this record exists to make the second pass expected rather than discovered. Whoever lands the parking should correct those two chapters and both command pages in the same change, the way a surface change is supposed to carry its own record, and should expect the release after it to want a fresh cross-check rather than the one this release earned. Detector: the chapters describing the intent readiness rows and the capture verbs' grounds requirement state what the shipped verbs do at the commit a release gate reads, and a change to either verb's refusal set arrives with its chapters in the same diff.
- iss-2609091642508005The agent-contract prompt lint ships and is armed as a blocker in the record-lint configuration, enforcing the frontmatter floor on every prompt under the agents directory and gating the diff-armed unbumped-edit check, yet the intent that promised it sits in the planned bucket and its spec sits open. The definition of done says a change that delivers a planned intent closes its spec in the same change, and that the omission is silent by construction: the release cut composes its changelog from terminal folders only, so an intent whose code is on the branch with its spec still open ships with no line and the cut exits zero doing so. That is the state here, and it means the release notes for this cut describe a repository in which this rule does not exist. The condition was found by a cross-check of the design record against the shipped surface rather than by any gate, because no gate asks whether a planned intent's work is already present: the record lint reads what the records say about each other and the release derivation reads only what reached a terminal folder, so the one question that would catch it, whether the code a planned intent describes is already merged, is asked by nothing. Fix: close the spec so the intent ships and the cut sees it, once the acceptance criteria are checked against what actually landed, which is the maintainer's call rather than an automatic move. Detector: a planned intent whose acceptance criteria are satisfied by code already on the branch is reported before a release derives its cut, so the choice to ship it or to keep it planned is made rather than defaulted.related itd-2609111003026787
- iss-2609091642508271The brief states as a requirement that a bare verb renders state and writes nothing, and seven verbs do not. Six of them, disembark and docs and embark and guard and history and ideate, render only the command framework's help on a bare call, and launch exits one. The history verb breaks the rule from both ends: its list and show sub-verbs take the shape the naming constraints forbid while the bare verb renders no state at all. The record has been corrected to say what is true rather than what was intended, so the discipline is no longer stated as satisfied, and that correction is what makes this a code observation rather than a documentation defect. It matters because the bare render is the discipline that makes a verb safe to type when you do not know what it will do, and a reader who has learnt the rule from the twelve verbs that keep it will type the other seven expecting the same. Fix direction: give each bare verb a state render, or record per verb why it has none, so the exception is a decision rather than a gap. Detector: every verb the binary registers either renders state on a bare call or is listed as an exception with its reason, and a verb added later fails until it is one or the other.
- iss-2609091647582259The memory store's bare status carries a drift field that says the index is stale and an ingest should be run. It is set on the result, it is emitted under the JSON envelope, and the human render never prints it, so the only reader who can act on the warning is the one who asked for machine output. The person who typed the bare verb to see how the store is doing is shown everything except the one line that asks them to do something. That is the loud-staging principle inverted: a degraded state that announces itself to a parser and stays quiet to a person, which is the shape the principle exists to refuse, and it is worse than silence because the board looks complete. Fix direction: print the drift line in the text render beside the counts it already shows, in the same words the JSON carries, so the two surfaces say one thing. Detector: a store whose index is stale renders the staleness on the bare human board as well as in the JSON envelope, and a store that is current renders neither.
- iss-2609091647589392The intent verb takes quoted text as a create, and guards that path twice so a mistyped sub-verb is never swallowed as a title: a near-miss is refused with a did-you-mean, and a lone bare token is refused because a one-word positional is a sub-verb by shape. Neither guard catches a far miss. The typo check decides first whether the arguments are shaped like a subcommand call, and a token followed by a record id satisfies that shape, but it then refuses only when some registered sub-verb lies within an edit distance of two. A word that is nothing like plan or ready or link or audit therefore passes: the guard has already concluded the shape is a subcommand call, finds no suggestion to offer, and returns as though the input were prose, so the words are filed as the title of a new draft intent in the durable record tier. The failure is silent and it writes. A user who types a verb this tool does not have, next to the id they meant to act on, gets a minted record whose title is their own typo, and learns nothing about the mistake; the same shape reaches every surface that reads the intents directory afterwards. Fix direction: when the arguments are already judged subcommand-shaped, refuse whether or not a suggestion exists, and offer the registered sub-verbs when none is close enough to name. The capture verb's sibling guard is the model, and its comment describes exactly this shape. Detector: an unknown first token followed by a record id refuses with exit 2 and writes nothing, whether or not it is near a real sub-verb, while genuine prose of two or more words still files a draft.
- iss-2609091648476051The reading assemble verb accepts an output directory, and both its terminal help and its plugin page use one in the worked example, writing the run somewhere other than the default run directory. A run assembled that way can never be ingested: the ingest verb resolves a run's manifest only from the default run directory under its run id, so a manifest parked anywhere else is invisible to it and the run cannot be proven. Nothing says so at assembly time, and nothing says so in the example. The shipped help is therefore teaching the one invocation that leads to a dead end, and it teaches it in the place a reader is most likely to copy from. The cost lands late: the assembly succeeds, the reading is commissioned and returned, and the failure appears at the ingest, by which point the run's output exists and has nowhere to go. Fix direction: either make the example use the default location and document the flag as a dry-run and inspection aid rather than a run location, or teach the ingest to resolve a manifest from a named directory so the flag means what the example implies. Detector: an assembly written outside the default run directory either reports at assembly time that it cannot be ingested, or is ingestable, and the worked example in the help and on the plugin page is one a reader can follow to a committed run.
- iss-2609091707224329The decide verb hands its working directory straight to the record writer without resolving the checkout root, so it mints an architecture decision record relative to wherever the shell happens to be. Run outside any repository it exits zero, reports a repo-relative path, and creates a full decisions store in a plain directory; run from a subdirectory of a real checkout it mints into a second store beneath that subdirectory rather than into the repository's own. This is the same defect the capture verbs carried until this release, and the same remedy applies: every front door resolves the checkout root before it builds a request, and refuses rather than guessing when there is no repository to address. The evidence is not hypothetical. A checker of this release's own semantic gate, running in a scratch directory, left behind an ADR store containing one record whose slug says it was written outside any repository; nothing in the verb, its help, its surface chapter or its plugin page warned that this could happen. The cost is a decision record that no gate reads, no release cut sees and no reader finds, written with every appearance of success, and the durable record family is the one where a lost entry is least recoverable because the decision it holds was never anywhere else. Fix: resolve the root the way the capture verbs now do, refuse outside a repository with nothing written, and report a store found below the checkout root rather than adding to it. Detector: decide run outside a repository refuses with exit 2 and creates nothing, decide run from a subdirectory mints into the checkout's own store, and decide run at the root is unchanged.
- iss-2609091717146700Staged transcripts for a repository that no longer exists can never be drained, so their unredacted text is permanent. The drain builds its scanner from the destination repository's root, because that repository's own redaction configuration must govern its own transcripts. When the repository's directory is gone, that root cannot be resolved and the drain has nothing to run with, so the raw bytes stay staged forever with no path to redaction. This is not hypothetical: one store on this machine holds 11.7 megabytes of unredacted staged text whose repository was deleted, which is the largest single pile in the store and the only one that no amount of ordinary use will clear. The retention work just landed addresses the case where nobody opens a repository again, by draining while a session is live and by reporting other repositories' backlogs at session start, but both remedies assume the repository still exists to be opened. The options are to let a deletion of the repository be a trigger that drains or discards first, to allow a drain under an explicitly named substitute configuration with the substitution recorded on the record, or to treat the pile as terminal and offer only discard. Whichever is chosen, the present behaviour is the worst of them: the text is kept, unredacted, with no way to act on it and nothing saying so.
- iss-2609091729516940The checkout-root defect that decide carried is a pattern the surface shares, not two instances of it. iss-2609090951291524 fixed it for the seven capture verbs and iss-2609091707224329 for decide; the same raw shape — os.Getwd() handed to a core that joins a repo-relative store path onto whatever it is given — remains at the intent, spec, ideate and memory front doors, which between them own the intent store, the spec store, the ideate verdict record and the memory substrate. Reproduced against a scratch git checkout holding one intent draft: abcd intent run from internal/core reports drafts 0, planned 0, shipped 0 while the identical binary at the root reports the draft, and abcd intent "<text>" run from the same directory mints a second store at internal/core/.abcd/development/intents/drafts and reports a repo-relative path that reads exactly like the checkout store's. Run in a plain directory that is not a repository at all it exits 0 and lays the full intent skeleton there. spec and memory show the read half of the same thing from a subdirectory. The cost is the one the two closed records already argue: a record filed where no gate, no release cut and no reader looks, written with every appearance of success, and for the intent store an intent whose spec can never be closed against it. Fix direction: the resolution is already shared and already generalised — gitutil.CheckoutRoot takes git's toplevel, refuses a repo-shaped tree git will not answer for, and refuses when nothing repo-shaped sits above, with the store's noun as its only parameter — so each remaining front door needs a resolving step of the captureLedgerRoot and decideStoreRoot shape and the strayStoreNotes call that reports what an unresolved door already deposited, not a new resolver. Detector, per family: the verb run from a subdirectory addresses the checkout's store, the verb run outside a repository refuses with exit 2 and writes nothing, the verb run at the root is unchanged, and a static pass over the surface package refuses a request built from an unresolved working directory.
- iss-2609091732329046Closing a spec moves its intent but leaves every link that named the intent's old folder pointing at nothing. The close verb reconciles the intent from planned to shipped, which is its job, and the spec body that was written while the intent was planned keeps its relative links to the planned folder. Those links resolve to nothing the moment the move completes, and the record gate refuses on them, so a close that reports success hands the next command a tree that will not lint. Three closes in one sitting produced eight dead links here and a red preflight immediately afterwards, with nothing in the close output hinting at it. The verb already knows both the old and the new path, so it is the one thing in the system positioned to fix or at least name them. Either rewrite links to the moved record in the same operation, or refuse the close while a link in the spec names the folder the intent is about to leave, or say at minimum which links the move has just invalidated. Silence is the worst of the three, because the failure surfaces later, in a different command, as a lint error that looks unrelated to the close that caused it.
- iss-2609091801075902The detector that holds the brief's account of hook self-provisioning to the shipped configuration checks that each salvaging event is named somewhere in the paragraph, which is a weaker property than the one it exists to enforce. The brief said three events self-provision where the configuration wires four, and the detector passed, because the fourth event was mentioned in that paragraph for an unrelated reason and the presence test could not tell a mention from a claim. A count is exactly the kind of statement that goes stale between a change and its record, and it is the class the release cross-check found most of, so a guard over this paragraph that cannot read a number is guarding the wrong property. The failure is quiet in the direction that matters: the guard reports the contract met while the prose misstates the shipped set, and the next reader trusts the guard rather than the sentence. Fix direction: assert the set rather than the mentions, deriving the salvaging events from the shipped configuration and requiring the paragraph to name that set and no other, so both a missing event and an invented one fail; a count stated in prose should be derived in the test rather than compared as a word. Detector: a paragraph claiming a number of self-provisioning events fails when the configuration wires a different number, and fails when it names an event the configuration does not wire, on a tree where the prose and the configuration disagree in either direction.
- iss-2609091801085579The documentation lint carries a release-gate flag that promotes an overdue citation from a warning to a blocker, and nothing runs it. The release workflow, the continuous-integration workflow, the make target and the template scaffolded into managed repositories all invoke the bare lint, and the launch verb computes its own citation preflight rather than calling the flag, so the stricter mode exists only for a person who types it. A blocker that only a human can trigger is not a gate, which is the shape the enforcement-claims-are-facts principle refuses: the flag reads as a release control and controls nothing. The cost is a citation that has aged past its threshold reaching a release with a warning nobody had to answer, while the record implies the release could not have carried it. Fix direction: either arm the flag where a release is actually gated, so the promotion happens on the path that matters, or retire it and let the launch verb's own preflight be the single citation control, saying so where the flag was documented. Detector: a release cut carrying a citation older than the threshold refuses on the path a release actually takes, or the flag does not exist.
- iss-2609091820182387The citation-currency rule already resolves a record handle and refuses a citation whose target is terminal, reading an ADR's status unioned with a declared supersession so that a half-declared supersession still counts as out of force. It deliberately reads one section of one document, and its own header gives the reason: a terminal-state citation is normal everywhere else, because a shipped intent's evidence trail, a supersession chain and a dated plan all name closed records legitimately, and only the living orientation document claims to describe what is true right now. A hand sweep after two records were superseded gives that judgement its first measurement. Of roughly forty-five citations of superseded decision records across the tree, eleven were wrong and the rest were correct provenance, so a rule applied everywhere would have been three-quarters false alarm, and the discriminator is what the citing sentence is doing rather than anything resolvable from the link. The tractable middle is to widen the same rule by document class rather than by sentence: extend its target from one file to the documents that assert the present tense by charter, which are the brief chapters, the principles, and the decision-record references carried in the frontmatter of an intent still in drafts or planned. That set is closed and declarable, it keeps the fail-closed shape the rule already has, and measured against the same sweep it would have caught ten of the eleven. The eleventh is a comment in a test file, which is out of reach for the same reason no gate reads decision prose against code identifiers. Two false alarms would survive even the narrowed form, both of the shape where a handle appears beside the word supersedes, which suggests exempting a handle within a few words of that token. Detector: a brief chapter, a principle, or a planned or draft intent's decision-record frontmatter citing a superseded record as current authority is refused, while a supersession chain, a historical plan and a resolved record naming what they found stay clean.
- iss-2609091829549814Two agents working in separate worktrees were given the same session scratch directory and both used the same conventional subdirectory name for a mutation-testing copy, so one agent's mutation script rewrote the other's copy of the tree and restored it afterwards, which the second agent had no way to notice while it ran. Nothing was lost, because the mutation was reverted within the same run and neither worktree was touched, but the window is the hazard rather than the outcome: while a mutation is applied a gate reports on code nobody wrote, and the repository's own conventions say exactly that about mutating a tree, requiring the work to happen on a scratch copy and the tree to be proven clean before anything is reported. The convention covers the copy and not the collision, because it was written for one agent at a time and says nothing about where a scratch copy goes when several are running. The correction is cheap and belongs with the convention rather than in each brief: a scratch copy is made in a private directory the agent creates for itself, never at a shared conventional path, so two agents cannot pick the same one. Worth stating alongside it that a shared scratch directory is also where two agents can read each other's intermediate output and draw conclusions from work that is not theirs. Detector: a convention names the private-directory requirement where it names the scratch-copy requirement, and an agent brief that hands out a shared scratch path is a review finding.
- iss-2609091911060345Ingest never checks that the destination's repository root and its store key name the same repository, so the seam that exists to keep one repository's transcripts out of another's corpus does not defend its own invariant. The destination is a pair: a repository root, from which the redaction scanner is built, and a root-commit key, which selects the store the records land in. Ingest refuses an empty root and shape-checks the key, and then trusts that the two describe the same repository. A caller passing a mismatched pair would redact a transcript under one repository's configuration and file it into another's corpus, which is exactly the fault the explicit-destination design was introduced to make impossible. No operator can reach it today, because the only front door derives both halves from a single detection, so this is a latent defect rather than a live one. That is also the reason to close it now rather than later: the argument for the seam is that a destination must never be inferred, and the seam currently relies on its one caller inferring both halves correctly. A second caller, in core or in a future surface, reopens the fault silently. The check is cheap: resolve the root's own root-commit and refuse when it differs from the key.
- iss-2609091911066372An exported owner-resolution helper has no callers and its logic is duplicated inline at the one place that needs it. The function resolves which store already claims a session and is exported from the history package, but nothing in the tree calls it: the ingest path reimplements the same walk inline instead. That is two copies of one rule, which is the shape this repository's one-canonical-primitive principle exists to prevent, and it is also dead scaffolding on a package boundary, which the wired-or-it-isn-t-done rule forbids. The duplication is the more expensive half: a later change to how a session's owner is resolved has two homes to find, and the inline copy is the one that actually runs, so a fix applied to the exported helper alone would appear to work and change nothing. Either make the inline site call the helper, or delete the helper and let the inline walk be the only definition. The spec already flags this as an uncertainty; it shipped unresolved.
- iss-2609091913570877The reconstruction artefact's anti-forgery fencing covers block content but not block metadata, so the forgery class it was built to close is still open. A tool call's name, a tool result's identifier and a turn's model name are formatted directly into the document outside any fence, with no guard on their contents: the only helper applied to them substitutes a dash for the empty string. A transcript carrying a line break inside any of those fields therefore emits lines of the document itself, and the lines it can emit include an agent section heading, a turn heading and a join marker, which are exactly the shapes the earlier fix set out to make unforgeable. The regression test plants its payload only in a text block, so nothing exercises the metadata path and the gap passed unnoticed. The consequence falls on the reader the artefact is written for: the guide it carries tells that reader everything inside a fence is something somebody said and everything outside one is the document, and that is not the rule the renderer implements. The fix is to sanitise every scalar interpolated outside a fence rather than to fence more, since these are single-line labels, and to extend the regression test to each of them. Until then the document states a guarantee it does not hold, which is worse than stating none.
- iss-2609091915350221The refusal that protects every capture from a degraded secret scanner is asserted by no test on any path, and the spec claimed the opposite. The guard is real and correctly placed: capture refuses outright when the scanner reports itself unavailable, rather than storing a transcript under weakened redaction. But a search across the history package's tests for that refusal, or for the scanner's own unavailability signal, returns nothing, so nothing would notice if the guard were removed, reordered behind the write, or made conditional. The spec asserted that the tests exercise it on the sub-agent path specifically rather than inferring it; the four tests it named cover lineage redaction, a surviving blocking span and a malformed scalar, and not one of them degrades a scanner. The record has been corrected to say what is true. The guard also predates this work, so this delivery inherits it rather than establishing it, which is why it was never given a detector of its own. That is the whole argument for arming it now: an unasserted guard on a fail-closed path is indistinguishable from an absent one until the day it matters, and this repository refuses to trust an unarmed detector everywhere else.
- iss-2609091915475296Reaching a session's sub-agents from the session identifier works in the core and has no operator surface, so the promise is met only through a JSON field the plugin page does not document. The store gained a listing that returns every record for a session, main thread first, and it is tested. But the show verb deliberately returns the main-thread record alone, the human render of list and show prints neither the agent identifier nor the agent type, and the only caller of the session listing outside the tests is the reconstruction path. The operator's actual route is therefore to take the machine-readable listing and filter it by hand on the session field, which works because the envelope marshals the whole record, but it is not documented on the surface page's field list and it is not what the acceptance criterion describes a person doing. By this repository's own rule that a capability is not delivered until it is reachable from both front doors, this is the first gap to close: either the human render carries the lineage columns and show grows a way to ask for a session's whole set, or the surface page documents the JSON route explicitly. Records still filed under the old composite identifier stay unreachable from the real session identifier either way; repairing those is a different piece of work and is already done.
- iss-2609091927085132`~/.abcd/path-entry` decides which binary the hook shims execute. It is read
- iss-2609091955574760The `PreToolUse` entry in `hooks/hooks.json` carries `"matcher": "Bash"`, so
- iss-2609091956001547The iss-35 brief-surface crosscheck does not converge on a clean run. Three
- iss-2609092116378524`TestHooksRunEveryShapeAhoyInstalls/dev_shim` failed the release gate's
- iss-2609100505140261`abcd intent audit <itd-N>` emits a fidelity-review request that carries no `policy.rubric_hash` and no `policy.prompt_hash`, but `abcd intent audit ingest` rejects a verdict whose `policy` hashes are empty. The two halves of the same verb disagree, and the gap lands on whoever writes the verdict.
- iss-2609100505142469The capture redactor rewrites the leading component of a reverse-DNS identifier when it happens to equal the local account name, silently corrupting technical content in a permanent record. This refines iss-2609061504302157, which reports the same root cause on an ordinary dictionary word; the dotted-identifier class is broader, and its damage is unrecoverable rather than merely noisy.
- iss-2609100505145554The `privacy-hygiene` rule flags persona-derived absolute paths, which the same conventions require examples to use, so a repo that follows the convention cannot pass the lint. In a managed repository it produced 48 findings, 33 of them errors, and every single one was benign. A later run of the same repository's lint reported between 147 and 213 privacy errors, all of the same two classes.
- iss-2609100505146979abcd has no supported operation for correcting a factual error inside a durable record, and no documented convention saying what to do instead. The record is deliberately not rewritten, which is right, but "not rewritten" and "wrong" are different states and only the first has a mechanism.related itd-2609150819439571
- iss-2609100506255436Sharpens iss-2608270559313719, which reports that abcd's release flow cannot serve a managed repo that is not a plugin. That record lists the symptoms; this one names the single line that causes most of them, and shows that abcd already solved the neighbouring problem, so the fix has a precedent inside the same file.
- iss-2609100506256173An agent walking an operator through a third-party hosting dashboard produced four successive sets of instructions, none of which matched the screen in front of them. The task — create a hosting API token, put it in two forge secrets, run a workflow — is mechanically trivial and took roughly ten exchanges, most of them the operator saying the instruction did not match what they could see.
- iss-2609100506256636abcd's own test suite leaves a dangling symlink on PATH, and `ahoy install` then refuses to complete for ever, with no supported way to clear it.
- iss-2609100506263330`ahoy install` can report success while leaving a PATH entry that a later plugin update silently breaks, and the condition that decides which happens is invisible to the operator.
- iss-2609100506265392The fidelity-review request names its delivered side as "the diff/commit range that realised spc-N (host supplies the range)", and there is no mechanism by which the host can supply it.
- iss-2609100506269348On a fresh PUBLIC repo the committed banned-names layer cannot be created, and the window in which it cannot is exactly the window in which a repo is being set up to ban a name.related itd-159 · related itd-2609151516525843
- iss-2609100507421759Nothing tells you an open issue is already fixed. The ledger goes stale silently, and the cost of finding out lands on whoever plans the next piece of work.
- iss-2609100507430423A record id can end up in two status folders at once after a merge, and nothing flags it.
- iss-2609100507431036Superseding an ADR is a five-file hand ritual and nothing checks that the two ends of the link agree.
- iss-2609100507431858No status surface says whether an open issue already carries a decision, so triage means reading every record in full.
- iss-2609100507432904The installed binary can lack verbs the repository's own records tell an author to run, and nothing says so until each verb fails on first use.
- iss-2609100507439414A managed repository's shared append-only files conflict on nearly every merge, and abcd propagates neither of the two remedies it has already adopted for itself.related itd-2609151138388536
- iss-2609100508562701An unknown sub-verb is treated as press-release text and mints a draft intent from its own name. Two independent sessions hit this in the same run, which makes it a likelihood rather than a possibility.
- iss-2609100508565741A verb's required arguments are learned from its first refusal, not from its help, because the bare help carries no worked example.
- iss-2609100508566033abcd does not name its own adjacent capabilities, so a verb that exactly answers the operator's need is found by accident or not at all. Three instances in one run, from two independent sessions.
- iss-2609100508566552Closing a spec ships its intent unconditionally, and there is no way to do one without the other.
- iss-2609100508566700The decomposition grading and the planning interview are hand-run rituals with no tool support, and running them repeatedly surfaced an ordering rule the tool could enforce.
- iss-2609100508570527`abcd capture` writes the record file and never says the record is not in git, so a ledger entry can be invisible to every branch and every gate that reads the committed tree.
- iss-2609100508570803Positive finding, recorded as evidence rather than as a defect: every record verb the run reached worked correctly from a git worktree, throughout a day of heavy parallel use.
- iss-2609100508573400`abcd ideate record` prints "the idea does not graduate" for a `reframed` verdict, which reads as "killed" to the operator receiving it.
- iss-2609100509524742A decomposition grade has no write path of its own, and the note it belongs in is a single shared file, so in a parallel run the grade cannot land at all.
- iss-2609100509531349The record verbs are sound; the failures were all at the edges, where the tool knows something and does not say it.
- iss-2609100509532185The planning interview is human-only by rule, so an autonomous run has no sanctioned way to record that the human delegated it.
- iss-2609100509533147`abcd intent` creates its draft in the checkout it runs in, with no repository or worktree target, which bites when the record store is being edited across several worktrees at once.
- iss-2609100509537730A debt nothing lists is a debt nobody pays. Every shipped intent in a managed repository carries an owed fidelity review, and no surface counts them.related itd-2609150819445595
- iss-2609100513521322`auto-release` cuts the version tag **before** the gate that could refuse the
- iss-2609100518522943An intent can be planned without an impact and only discovers it at the moment of shipping, in the landing commit. The readiness report has no row for impact, so a draft filed without one passes every readiness gate and plans cleanly, and the refusal arrives at spec close, which by this repository's own convention happens in the same change that lands the work. The operator is therefore told to go back and stamp a field on a record at the exact point they are trying to close a change they have already written and tested. Two sessions hit this independently within a day, one during an autonomous run and one while shipping an intent by hand, and both fixed it the same way, by editing the frontmatter directly rather than through a verb, because no verb stamps impact on a planned intent. Either readiness should report impact as a row alongside the criteria and the grounds, so the gap surfaces while the draft is still being written, or planning should refuse without one, or a verb should exist to stamp it afterwards. What should not persist is a required field whose absence is silent until the least convenient moment.
- iss-2609100518523501The grounds requirement is documented after the steps that need it, so a reader following the surface page in order meets the refusal before the explanation. The page presents creation and planning as a sequence and states the grounds requirement further down, among the interview steps. An agent working through it in order therefore runs the plan verb, is refused for missing grounds, and only then reaches the passage that would have told it why and how. The cost is small per encounter and it recurs for every reader who trusts the order of the page, which is every reader following it for the first time. The fix is ordering rather than content: state the requirement where the step that enforces it is described.
- iss-2609100518527863A record can cite a record id that does not exist, and for one record family an id cannot be resolved to a file mechanically at all. A session writing a spec during an autonomous run put two invented ids into it and caught them only by reading the document back afterwards; nothing in the record gates checks that an id written inside a record resolves to a record that exists. The gap is wider than a missing check. Two filename conventions coexist in the decisions family: the hand-numbered records carry a zero-padded ordinal in the filename whose value differs from the id in their own frontmatter, and the minted ones carry the timestamp id without the family prefix the id itself begins with. Neither shape lets a reader map a cited id to a file by name, so a resolver has to parse the frontmatter of every record in the family before it can answer, and an agent checking its own work by hand cannot do it reliably at all. Any check that lands has to resolve through frontmatter rather than filenames, which is also the reason the check does not exist yet.
- iss-2609100519122086Which session holds which worktree, branch or record is coordinated entirely by conversation, so every new session repeats a handshake that nothing records. A session joining work in progress has no way to ask what is already claimed: it messages the peers it can see, waits for replies, and rebuilds a picture that the sessions before it had already built and did not write down. One measured encounter cost four messages and about fifteen minutes before any work began, and the picture it produced is not durable, so the session after that pays again. The convention that a diff you did not make is a peer's work depends on knowing who the peers are and what they hold, which is precisely the thing no artefact carries. The repository already records this gap for the narrow case of detecting a peer session before mutating git state; the wider case is claim rather than presence, and the two want the same substrate. Whatever holds it should be as cheap to write as it is to read, because a coordination record nobody updates is worse than the chat it replaced.related itd-2609150819440345 · related itd-2610170634394993
- iss-2609100519128005A refused capture writes its error as JSON to standard error and leaves standard output empty, and an operator concluded from that shape that two captures had been silently lost. The conclusion was wrong and the shape that produced it is real, so both belong in the record. Tested on the published release and on the current source: an unknown category is refused with exit status one, the error is emitted as a JSON object on standard error, standard output is empty, and no record is written, verified against the ledger and a clean working tree afterwards. Nothing was lost. What the operator saw was a machine-readable invocation that produced no machine-readable output, in a pipeline that did not surface the exit status, for a flag whose accepted values are named nowhere in the help. Each of those alone is survivable and together they read as silent loss, which is why the operator re-ran the captures and reported data loss in good faith. The lesson is not that the refusal is wrong, because a refusal that writes nothing is exactly right. It is that a machine-readable mode should put its outcome where a machine-readable consumer looks, and that an error naming an invalid value while withholding the valid set turns one round trip into several and makes an operator doubt the store rather than the flag.
- iss-2609100531051385A verb's requirements are revealed one refusal at a time, so satisfying it takes as many invocations as it has required inputs. Resolving one issue took three calls. The first refusal reports only that the verb accepts two positional arguments and received one, and names none of the flags it also requires. Supplying the second positional then produces a second refusal, for the missing grounds. Reproduced here against the same binary: the argument-count refusal mentions no flag at all, and the grounds refusal arrives alone even when the other required flag is also absent, so a caller learns the requirements in series rather than at once. Each refusal in isolation is well written, and the grounds refusal in particular explains why it wants what it wants and confirms that nothing was written. The defect is the sequence. A caller who knows nothing pays one round trip per requirement, and an autonomous caller pays it every time because it has no memory of the last session's discoveries. A single refusal listing every unmet requirement would cost one round trip regardless of how much the caller already knew. This is the same family as the finding that required flags are learned from the refusal rather than the help, and the two want different fixes: that one wants a worked example in the help, this one wants the refusals aggregated.
- iss-2609100531063912Positive result: a full adversarial review loop ran end to end inside abcd's record shapes without the tooling getting in the way. Recorded because a stress that finds nothing is evidence about the tool, and it is only legible if someone writes it down. An autonomous run filed, planned and implemented one intent without the human interview, then put it through two adversarial reviews. The reviews produced eleven findings about the repository under review and none about abcd. Applying those findings needed no change to any record shape: a scope condition was reworded under its existing stamp rather than being reissued, one acceptance criterion was added, and the readiness gate stayed green across the review-driven edits. Closing the spec moved both the spec and its intent in one step with correct paths. The parts of abcd exercised hardest here, the shapes that carry a claim and the verbs that move a record between states, held under a workload they were not specifically designed for, namely a review loop with no human in it. This is the second positive finding from the same experiment, alongside the observation that every record verb worked from worktrees across 27 branches with no merge conflict in the ledger. Both bound the negative findings: what failed was consistently at the edges of the tool rather than in its centre.
- iss-2609110944498549**Maintainer ruling, 2026-09-11: `ahoy install` must not write abcd by name intorelated itd-2610031348087517
- iss-2609111002410678`CLAUDE.md` tells every session that ADRs are the one record family still
- iss-2609120441199164A code comment can claim a rule is applied everywhere while a sibling file in the same package breaks it, and nothing detects the gap. Found by a reviewer reading the comment against the code, in a managed repository, not by any scan. abcd already holds the idea this needs: the citation merge carries honesty rules, and the documentation gate refuses a change-narration claim in prose. Neither reaches a scope claim written in a Go comment, so the most load-bearing sentences in the codebase, the ones that tell the next reader an invariant holds across every call site, are exactly the ones nothing checks. The class is worth naming because this repository keeps meeting it from both ends. Its own bug-hunting playbook states the rule, that a fix is not done until every sibling site is swept and the pattern is grepped rather than the instance, and a defect on this very branch was precisely that shape: the anti-forgery work fenced a renderer's block content, left its block metadata raw, and the regression test covered only the path that was fixed, so a comment and a test together asserted a guarantee the code did not hold. A detector cannot judge whether an invariant is true, but it can find the claim: a comment asserting universality near a construct that has siblings is a place for a human to look, and listing those places is cheap where reading every comment is not.
- iss-2609120446083912Identity redaction rewrites by string rather than by byte span, so a line carrying both a real leak and a lookalike has the lookalike rewritten too. The detector was taught to leave a dotted namespace component alone, which fixed the corruption of reverse-DNS identifiers. The rewrite did not learn it. Masking for identity kinds replaces every occurrence of the matched string rather than the span the detector found, which is recorded as deliberate because an identity placeholder changes length. So where one line contains a genuine bare mention of the account name and also an identifier that merely begins with it, the first is masked correctly and the second is mangled anyway: a line reading that the crash is in a particular reverse-DNS bundle comes out with the bundle's first component replaced, even though detection refused it. The same mechanism turns an ordinary word containing the account name into a masked fragment mid-word when a real mention appears on the same line, though detection alone leaves that word intact. A whole-string replace cannot express one occurrence masked and another left, so the fix is span-based replacement for identity kinds. That is safe on offsets, because the sealing pass is length-preserving, but it reverses a recorded design choice in the single shared write-time sanitiser that history, memory, capture, ideate, intent, decide and launch all write through, and it reverses it in the fail-open direction. That is a human design decision rather than a patch, which is why it is recorded rather than done. The git-identity and real-name kinds share the mechanism and would corrupt the same way where a name collides with a namespace label.
- iss-2609120447480903ahoy install writes .githooks/pre-commit but leaves 'git config core.hooksPath .githooks' to the user, so the hook is committed but not running on the clone that just installed it. Detection knows this (hooks_path_armed=false) yet emits no gap for it. Proposal: a user-state gap that arms the clone after checking .git/hooks has no non-sample hooks the redirect would bypass, refusing with a note when it does.
- iss-2609120447482255symlink.foreign (regular file at ~/.local/bin/abcd) is reported as unresolvable with 'resolve manually' but says nothing about what the file is. Reporting size, mtime, and whether it identifies as an abcd binary (and which version) would let the user decide safely instead of inspecting by hand. The removal then needs a second full install run; a re-detect after the user clears it in the same run would save the round-trip.
- iss-2609120447482506PATH entry written as a symlink to the plugin-root binary (no verified artefact in the cache) is fragile by abcd's own note, yet bare 'ahoy' reports zero gaps afterwards. Immediately after a plugin update the symlink still pointed at the superseded root e3696dc while the live root was eda67ccc, and install_mode read 'pinned'. Detection should surface this as a gap (entry points at a non-current plugin root / not an owned copy) rather than only in a one-time install note; better still, provision the cache during install so the owned copy is written first time.
- iss-2609120447483698ahoy install: the scan_deep (true/false) prompt sits in the same stdin stream as the y/N approval prompts, so the documented 'yes | abcd ahoy install' form feeds it 'y', which is silently treated as the default (false). Either accept y/n on boolean config prompts, skip the prompt when --yes or the flag is given, or refuse an unparseable answer loudly. Observed: user chose 'approve everything', scan.deep landed as false with no warning.
- iss-2609120447486547The three required config gaps (docs.target, oracle.backend, repo.visibility) say 'ahoy install prompts for the value', but the flags --docs-target/--oracle-backend/--visibility exist and are the only reliable way to answer in a piped run. The fix_hint should name the flag; and a --yes run that still has to prompt for a free-text config value should say so up front rather than blocking on stdin.
- iss-2609120447487070ahoy --json emits "gaps": null when there are none, not []. jq '.gaps[]' fails on the healthy case, which is the case most scripts will hit. Same for any other list field that can be empty.
- iss-2609120447489045staleness reads 'unknown' on a plain plugin install of a pinned release, every run. For a plugin user that is noise, not signal: the skill text tells the agent to report staleness so a stale binary is never silent, so 'unknown' gets relayed on every healthy render. Either resolve it to 'current' when the pinned version matches the plugin manifest, or suppress it for pinned installs.
- iss-2609120447494818capture --source and --category are closed sets but neither --help nor the refusal names the valid values: 'invalid source "session-observation"' with no list. An agent relaying a capture has to guess or fall back to the default. Every closed-set refusal should print the set, as --production-mode's help text already does.
- iss-2609120450411702Upgrade path self-blocks across a plugin update: v0.7.1 wrote ~/.local/bin/abcd as a symlink into its own plugin root (e3696dc) with the note 're-run install from a session whose hooks have provisioned the cache to upgrade it to an owned copy'. After the plugin updated to v0.8.0 (eda67ccc), that re-run classified the symlink as symlink.foreign ('expected .../eda67ccc02eb/abcd'), unresolvable, 'ahoy refuses to clobber' — so the prescribed remedy is refused by its own predecessor's write, abcd on PATH stays at v0.7.1, and install_mode reads empty. Only a manual rm and a third install produced the owned copy. Fix: a symlink whose target is inside abcd's own plugin-cache directory (any root hash) is abcd's, not foreign — adopt and replace it; or have the first install never write the plugin-root symlink fallback at all, since it is guaranteed to go stale on the next update. Related: iss-2609120447482506.
- iss-2609120452071388Reported from a downstream repository using abcd, where `abcd capture` (bare,
- iss-2609120452369809Reported from a downstream repository using abcd: `abcd capture "<text>"` mints
- iss-2609120505141653`origin: researcher-authored` states that a person invoked the verb. It is
- iss-2609120511058115Nine findings about abcd's own installer are sitting in a teaching-materials
- iss-2609150805167646`abcd docs lint` reports "0 finding(s), 0 blocker(s)" in a scaffolded repository
- iss-2609151150180399The /abcd:intent skill text (Grounds section) shows the ready --grounds --json envelope carrying "redacted": 0 and asks the host to report grounds.redacted whenever it is non-zero, but GroundsResult.Redacted (internal/core/intent/grounds.go) is tagged omitempty, so the key is absent whenever the count is zero. A host following the page finds no key at all on every ordinary write (five of five in the reporting session, v0.8.0 plugin binary) and cannot tell an omitted zero from a missing field. Either the skill text says the key is omitted when zero, or the envelope carries it always; the envelope's own convention for counts elsewhere (json_empty_collections_test) should decide which.
- iss-2609151150180583docs lint: exempt_paths cannot excuse a file from links_resolve. contentExempt (internal/core/lint/lint.go, around the function at line 2675) covers only the content-authoring checks (banned_tokens, persona_registry), so a tool-mandated mirror of a root file into a subdirectory (a repo that must carry .github/copilot-instructions.md byte-identical to its root AGENTS.md, because that tool follows no pointer) raises a links_resolve blocker per relative link that resolves from the root and not from the mirror's directory, with no way to excuse it short of dropping the links. Observed on the v0.8.0 plugin binary: three blockers on one mirror. Workaround the adopter took: name companion pages as backticked paths with a shell guard checking each exists. Either let exempt_paths (or a dedicated key) excuse a path from links_resolve, or document that the link check has no exemption so authors of tool-mandated mirrors know in advance.
- iss-2609151542247232GHSA-6xpc-3w4h-frfh (draft, govulncheck GO-2026-5932) reports golang.org/x/crypto/openpgp as unmaintained and unsafe by design. Traced on main at 44261a68: the main module imports no openpgp package (go mod why: the main module does not need it; go list -deps finds zero openpgp packages), golang.org/x/crypto v0.55.0 is an indirect dependency reached only through internal/core/update via minio/selfupdate and aead.dev/minisign (blake2b), and govulncheck's symbol-level scan reports zero vulnerabilities the code calls, with the module-level notice covering only packages the binary never links. The advisory's own status field marks it a duplicate of the govulncheck candidate. Nothing in the tree uses the package, so there is nothing to replace or remove; the finding is recorded so the draft advisory can be closed against it.
- iss-2609151703088754A security record names its advisory only in its slug and prose (ghsa-gx3m-..., 'GHSA-gx3m-3224-qqcv (CWE-426...)'), so nothing can match a resolved record to the draft advisory it fixes without reading the text. The publication step the advisory-handling pilot note names as its target (the GHSAs publish after the cut) needs a typed field on the issue record, e.g. advisory: GHSA-xxxx-xxxx-xxxx, admitted by issueschema, written by capture through a flag, carried through resolve and wontfix unchanged, and read by the release workflow to publish or close the advisory. Today GHSA-gx3m-3224-qqcv is fixed in v0.8.0 (record iss-2609012039107700 resolved 2026-09-08) and still an unpublished draft, which is the gap a mechanical match would have closed. Split out of the publication intent at the 2026-09-15 routing so the field can land first on its own.
- iss-2609151847117977The home-scoped cache attestation (GHSA-4q78-ccfv-f374) binds exactly two
- iss-2609151952353626abcd docs lint walks gitignored content under a lint root. In a repository whose lint roots include a delivery folder, a shipped fetch script writes assessment data and a cached git clone of the abcd repository under that folder, which .gitignore excludes; the lint read the whole cached clone (5,391 findings, 94 blockers, all inside the ignored folder, none in the repository's own prose). exempt_paths covers the content-authoring families only, so with the folder exempted ten links_resolve blockers still fire from inside the cache, whose record files link to paths that resolve only in the abcd checkout. A gitignored path is by definition not the repository's documentation; the lint could ask git check-ignore once per root and prune ignored directories, the way the site publisher already does, and name what it pruned. Workaround the adopter took: the fetch script keeps its clone cache outside every lint root. Observed on the v0.8.0 plugin binary. Second instance of the class behind iss-2609151150180583 (exempt_paths cannot excuse links_resolve).
- iss-2609152131205316The outbound text check shipped with no record, so the release notes could not name it
- iss-2609161805447092abcd update calls a pinned install foreign when its symlink points into a superseded plugin-cache version. On this machine ~/.local/bin/abcd is the pin abcd ahoy install wrote on 2026-09-07: a symlink into the plugin cache directory of the v0.7.1 vintage (e3696dc524e3). After the plugin moved on, go run ./cmd/abcd update v0.9.0 --yes refused with 'the entry at ~/.local/bin/abcd is not something abcd owns, and abcd never clobbers a binary it does not own' and offered 'remove or rename the occupant' as the remedy. The link target is a published release binary (its digest is the darwin-arm64 line of v0.7.1's checksums.txt) inside abcd's own cache, so nothing about it is foreign: the classifier in internal/core/ahoy/update_target.go only admits a symlink into the CURRENT plugin root as owned, and a link into an older vintage falls through to foreign before the digest check the verb's help promises ever runs. The refusal's detail and remedy are both wrong for this shape; the right remedy is abcd ahoy install, which the owned-dangling case already names, and the honest detail is that the pin points at a superseded vintage. Found while finishing the v0.9.0 deploy on 2026-09-16.
- iss-2609170627427239The status-line badge's default state reads 'abcd', which says the tool is present but not that this repository is managed by it; make the managed-and-nobody-waiting badge read 'abcd-managed' in an abcd-managed repository, so the word on the row states the fact the badge exists to show, alongside the facilitator and product-thinker states.
- iss-2609170640135192A local branch whose pull request has merged is never pruned, so a checkout accumulates them until somebody sweeps by hand: this checkout held 57 on 2026-09-17, one per landed PR since early September. The sweep cannot be 'git branch --merged', because the repository allows squash and rebase merges and those leave no ancestry, so 20 of the 57 read as unmerged by ancestry and were provably merged only by patch-id or by the forge's PR state; and a branch checked out in a worktree survives the sweep until the worktree is removed. abcd knows the merge state (the resolution gates already read origin/main and the PR), so the install step or a fetch-time pass could list the merged branches and remove them on consent, never one with unmerged patches, never one a worktree holds, and never a name matching a backup pattern.
- iss-2609170709035405The status line paints everything after the badge in the terminal's plain foreground, so the repository name, the branch, the model, the context percentage and the intent and issue counts all carry the same weight and the row reads as one undifferentiated run. Give the elements two tones: a softer grey for the repository and branch names and for the itd and iss counts (the standing facts, glanced at rarely), and a darker colour for the model and the context figure (the two that change and get read). The badge keeps its own pair; the split is the one the previous hand-written status line already drew, and it must keep the rest of the row legible on the status surface's dim background.
- iss-2609170726360399abcd intent "<text>" files the quoted press release as the H1 title and leaves the Press Release section a placeholder stub. Reproduced at v0.9.0 (4ae6f221) in a scratch managed repo: abcd intent "Teams see who is waiting on whom without asking. Every session prints its owed answer." wrote a draft whose H1 is the whole quoted paragraph, whose Why This Matters section repeats it verbatim, and whose Press Release section holds only the seeded-from-quoted-text placeholder. createIntentFromText hands the text to titleLine, which collapses it into one heading line, and the slug truncates it at sixty characters, so a paragraph-length press release becomes an unreadable title and a stub narrative. Relayed from the Gropius managed-repo session gropiusllm-56 on 2026-09-17: a record-discipline reviewer there flagged every fresh draft as not press-release-first, because the one section the INTENTS rule says comes first is the one the verb leaves empty. Wanted: the quoted text seeds the Press Release section, and the title is derived from it (first sentence, or an explicit --title). The surface page only says the draft is seeded from the text, so it neither promises nor forbids either placement; a fix should say which.
- iss-2609170726457256No verb stamps impact or builds_on on an existing intent draft. --impact exists only on the filing call (abcd intent "<text>" --impact) and again at the close that ships the intent (spec close --impact); between those two points a draft that was filed without a judgement has no verb that adds one, and builds_on, a schema-known frontmatter field the readers walk, has no flag on any verb at all. Relayed from the Gropius managed-repo session gropiusllm-56 on 2026-09-17, where two sessions hand-edited the frontmatter of five drafts with sed to set both fields, which bypasses every validator the verbs carry (ParseImpact, the never-internal rule for intents, the record-id shape of a builds_on target). Confirmed against the v0.9.0 command tree: intent plan takes only --production-mode, intent link writes spec_id only, and no verb names builds_on. Sibling records: iss-126 (resolved) gave impact a home at the close, and iss-2609091256264547 (open) covers the three typed relations the schema lacks; this finding is about the one relation it has and the one judgement it accepts, neither of which a verb can write onto a draft. Intent-shaped by the itd-84 four-piece table (a capability: a draft's judged fields are settable through a verb after filing), so the routing to an intent draft is the human's to confirm; recorded here first.
- iss-2609170818061083The oracle choice is one repo-wide value in .abcd/config.json (host-delegated | native | cli | api | mcp), so every delegated step reaches a model the same way. The choice should be configurable per task: some steps want a local model (a cheap, private first pass over a transcript), some want the harness to decide, some want the harness told to use a high-end frontier model (a release gate's semantic review, an intent audit) and some a cheaper one (a slug, a summary). Alongside the backend, the same per-task configuration should say whether the harness may use sub-agents for the step at all, and how many, so a fan-out review can be bounded and a single-pass composition kept to one. Today none of this is expressible: the backend is global, and sub-agent use is whatever the command page tells the host in prose. The task classes the agent trust contract already declares (capability_scope.task_classes) are the natural key; the api adapter draft itd-2609081951381895 would be the first backend such a table could route to.related itd-2609170822093401
- iss-2609181020519987The intent surface page does not say whether abcd intent ready --grounds records on a draft. The Grounds paragraph of commands/intent.md describes the flag on the readiness gate and never states which buckets accept the write; the code (RecordGrounds) refuses only a shipped or superseded record, so a draft in drafts/ takes grounds before it is planned, and the resolved iss-2608300930057882 states that forward-only exemption in its resolution. Relayed from the Gropius managed-repo session gropiusllm-56 on 2026-09-18, which recorded grounds on a draft, found it worked, and could not tell from the page whether that was sanctioned. One sentence on the page closes it: grounds are recorded on a draft or a planned intent alike, and refused on a shipped or superseded one.
- iss-2609181121301638The fidelity review request lists the acceptance criteria but never the scope-condition identities the verdict must dispose. auditPromptBody in internal/core/intent/audit.go writes an Acceptance Criteria block numbered ac-1..ac-K and the rubric, while the verdict schema (verdictCondition, keyed on condition_id) and the intent-auditor contract require scope_conditions to cover the intent's conditions exactly, one disposition per cond-… identity; the identities reach the auditor only as HTML comments in the intent record that the request does not quote. Relayed from the Gropius managed-repo session gropiusllm-56 on 2026-09-18 after seven fidelity audits at v0.9.0: the reviewer scraped the cond comments by hand, and a miscount quarantined the verdict at ingest. Wanted: the request carries a Scope Conditions block listing each cond-… identity with its text, as it carries the criteria, so the auditor disposes exactly the set the ingest will check. The prompt body is hashed for provenance, so the block is part of the pure composition and the prompt_hash policy version moves with it.
- iss-2609181121305984The fidelity review request carries no verdict-JSON schema and names no place to read one. auditPromptBody ends with "Run the intent-auditor agent over the criteria and the delivered diff, then ingest its verdict JSON", and abcd intent audit ingest --help documents a single flag; the concrete verdict shape (verdict enum, scope_conditions with condition_id and disposition, the two sha256 provenance fields) lives only in the bundled intent-auditor agent definition. A host without that agent, or a reviewer working from the request alone, has nothing to write against and learns the shape from ingest refusals. Relayed from the Gropius managed-repo session gropiusllm-56 on 2026-09-18 after seven fidelity audits at v0.9.0. Wanted, either: the request quotes the verdict shape beside the rubric, or a read-only abcd intent audit schema verb prints it, and the ingest help points at whichever exists. Filed apart from the scope-condition identities finding because the remedies differ: that one is about which items the verdict must cover, this one about the shape it must take.
- iss-2609181121522692No lint rule checks that an intent's bucket agrees with its specs' buckets, so a mis-merge that files a new planned intent's spec into closed/ (or the intent into shipped/ with its spec still open) lands silently. Observed in the Gropius managed repo on 2026-09-18 at v0.9.0: after a pull request had moved many records planned/ to shipped/ and open/ to closed/, a git merge of a branch adding one NEW planned intent and its open spec ran rename detection against those moves and offered to place the newcomers in shipped/ and closed/. The record gates read each record on its own: spec_lifecycle refuses a status key, intent_lifecycle checks ids and frontmatter placement, and neither reads the linked record's folder, so the pair "intent planned, its spec closed" passes every gate. Relayed from session gropiusllm-56, which called it a process observation rather than an abcd defect; recorded because the detector is cheap and the shape recurs wherever bucket moves and new records meet in one merge. Wanted: a record-lint rule that refuses a planned intent any of whose specs is in closed/ when no open spec remains, and a shipped intent any of whose specs is in open/. This is the inverse of itd-2609111003026787 (the gate for an intent whose work is live while its spec stays open), which reads the tree rather than the buckets, and a sibling of iss-2608290808193471; the bucket-agreement half is mechanical and needs no reading of the code.
- iss-2609181122202952The pre-commit name guard prints its inherited-store notice three times per commit from a linked worktree. The committed .githooks/pre-commit announces the itd-150 fallback once per run, at a single site ("pre-commit: abcd name-guard: inheriting the primary checkout's <store>" on stderr), so three copies on one commit mean the hook body ran three times for that commit, which points at the dispatch (the global hooks dispatcher plus the repo hook, or a pre-merge-commit run) rather than at the notice itself. Relayed from the Gropius managed-repo session gropiusllm-56 on 2026-09-18 at v0.9.0, which called it cosmetic. Recorded because the repetition is also a measurement: if the guard runs three times, the scan costs three times what it should, and one run is the one whose refusal counts. Wanted: establish which invocations produce the three runs and either de-duplicate the dispatch or print the notice once per commit.
- iss-2609181223260994No verb writes the deferral keys a release cut reads. The principle pre-existing-is-not-a-defence names deferred_after and deferral_reason as the one sanctioned way past the release-cut guard for an open major or critical record, and changelog.GuardFindings reads them, but no capture sub-verb writes them: the ledger verbs are disposition, list, mentions, promote, resolve and wontfix, so a deferral is a hand edit of frontmatter that bypasses the validators every other transition carries (the anchor tag's shape, the reason's presence, the record being open and major). Relayed from the Gropius managed-repo session gropiusllm-56 on 2026-09-18 at v0.9.0, which wrote the two keys into six records by script in one day, across three release cuts. Wanted: abcd capture defer <iss-N> --after vX.Y.Z --reason "…", refusing a record that is not open, a tag that is not the current anchor, and an empty reason, and reporting the deferral in the same envelope shape as resolve. Note the gate that reads the keys lives in the launch verbs, which that repository cannot run (iss-2609061432214212), so the write path and the read path are missing together there; this record is the write half.
- iss-2609181223354098A push to a pull request after auto-merge is armed on a merge queue can be dropped silently, and the bundled COMMITTING rules do not say so. Reported from the Gropius managed repository on 2026-09-18 (its own ledger carries it under its own id): with auto-merge armed and the entry already queued, a later push to the branch was not what the queue merged; the repository lost two commits and re-landed them in a second pull request. The failure is the forge's, not abcd's: a queue builds its entry from the head it took at enqueue time, and a push after that either removes the entry (to be re-armed) or, when the entry is already merging, lands nothing, and the pull request's merged state looks the same either way. The lesson is portable to every managed repository whose ruleset routes through a queue, which is why the session asked for a line in the bundled COMMITTING domain: after arming auto-merge on a queue, do not push again; if a push is needed, disarm first, push, re-arm, and confirm the merged sha contains the last local commit before deleting the branch. Sibling of iss-172 (queued entries left BEHIND) and iss-2609020716561070 (the up-to-date requirement beside a queue); this one is the dropped push, which neither covers. Recorded as a process observation; the routing (a COMMITTING rule, a line in the intake runbook, or both) is the product thinker's.
- iss-2609190337466942Two cobra conventions a fresh operator tries first are unmet: abcd --version is an unknown flag, and abcd intent status <itd-N> is an unknown sub-verb. Reproduced at v0.9.0 (4ae6f221). The version verb exists (abcd version), and the record dispatcher answers the status question (abcd <itd-N> prints the bucket, the path and the next move), but neither refusal points at the form that works: --version refuses with "unknown flag" alone, and the intent refusal lists the five sub-verbs and says nothing of abcd <itd-N>. Relayed from the Gropius session gropiusllm-66 on 2026-09-19 (a forty-lane autonomous sweep), where both were the first thing tried. Wanted: accept --version as an alias of the version verb (cobra's Version field does it in one line), and have the unknown-sub-verb refusal name abcd <itd-N> when the rejected word is status or show.
- iss-2609190337545165The ingest JSON for a dead-lettered verdict carries a rollup that reads as a result. abcd intent audit ingest --verdict-json --json returns one result struct for every outcome, so a dead_letter response carries criteria, conditions and the per-verdict counters beside its reason: a lane in the Gropius sweep read "criteria: 0" beside "conditions: 11" on a quarantined verdict and took it for a rollup. The text render is right (it prints the rollup only under ingested and the DEAD_LETTER reason otherwise), the JSON is not: the counters are zero-valued members with no omitempty, and conditions is populated from the intent before the verdict is judged. Reproducible by reading the IngestResult struct in internal/core/intent/audit.go against the --json path. Relayed from session gropiusllm-66 on 2026-09-19 at v0.9.0. Wanted: the rollup members omitted (or nulled) on dead_letter and noop, so a quarantined verdict's JSON says only what happened and where the raw payload went. Separately, the same session reported the ingest refusing a digest of "sha256:unknown" while accepting an empty digest; that is the documented contract (empty where the digest is not known, otherwise sha256:<64 hex>) and the refusal says so, so it is not filed.
- iss-2609190337598356A re-emit of a fidelity review request reports already_owed and says nothing about the request it just rewrote. abcd intent audit <itd-N> on a shipped intent whose marker is OWED takes the already_owed branch of emitAuditForIntent, which rewrites the request file through writeAuditRequest and then returns with status already_owed; the status names the receipt's state, which is true, and omits the write, which is what the caller asked for. A lane in the Gropius sweep read already_owed as "nothing happened" and looked for a failure. Relayed from session gropiusllm-66 on 2026-09-19 at v0.9.0. Wanted: the result names the request path it wrote (re_emitted: true, or the path member populated) so the status and the action are both readable from the JSON.
- iss-2609190338070038The capture surface page documents the two-status-folders refusal but not the convention that avoids it: a record is resolved on the branch that carries it. commands/capture.md explains why an id in open/ and resolved/ at once is refused and how the merge artefact arises, and stops there; the rule that prevents it (never re-add a record to the default branch after a branch was cut from it; resolve it on the branch that carries it) lives only in this repository's AGENTS.md, which a managed repository does not inherit. In the Gropius sweep of 2026-09-19 (session gropiusllm-66, forty lanes) a record captured on an unmerged branch could not be resolved from another branch without producing exactly that duplicate once both landed, so lanes merged each other's branches to resolve. Wanted, either: one paragraph on the capture page stating the convention for a managed repository, or a resolve that tolerates a record absent from this checkout when told where it is (the session's --expect-on-branch), which is the ledger-visibility capability itd-2609091416295622 already weighs. This record is the documentation half.
- iss-2609190338340796The guard allows a bare git stash in a clone with more than one worktree, where the stash stack is shared. git stash is one stack per repository, not per worktree, so an agent's stash-then-lint-then-pop on a clean tree in one lane popped another lane's entry in the Gropius sweep of 2026-09-19 (session gropiusllm-66, forty lanes on one clone); the pop succeeded and the entry landed in the wrong tree with no message either lane could act on. abcd guard check "git stash pop" and "git stash" both answer allow at v0.9.0, and the hazard registry carries no stash entry. Wanted: a warn (not a block) on bare git stash and git stash pop when git worktree list reports more than one worktree, naming the shared stack and the safe successors (a stash with a message and a pop by that entry, or a scratch commit on the lane's own branch). A single-worktree clone keeps allow.
- iss-2609190338409222The LAN-hostname scan flags a possessive persona host its own suggestion calls acceptable. net_lan_hostname flags "[redacted-hostname]" while its Suggestion reads "replace with a reserved name (example.com, host.test) or a persona-derived fixture host": personaDerivedHost takes the label before the first hyphen and looks it up in personaNames, so "alice-mac.local" passes and "[redacted-hostname]" (the possessive, which is how macOS names a machine by default) does not. The author reads the suggestion, sees a persona-derived host, and cannot tell why theirs was refused. Relayed from the Gropius session gropiusllm-66 on 2026-09-19 at v0.9.0, reproduced by reading internal/adapter/scanner/network.go. Wanted, either: the skip admits a persona name in possessive form (alices, alice's), or the suggestion names the exact shape it accepts (<persona>-<noun>, no possessive).
- iss-2609200618138053Bundle a WRITING rule domain so the review-only writing-style rules reach agents in every managed repo. docs/reference/writing-style.md holds the canonical rules, but none of the eight bundled domains (COMMITTING, DOCUMENTATION, ROADMAP, ISSUES, INTENTS, LIFEBOAT, PII, OPINIONS) carries them, so an agent in a managed repo never sees them unless the repo declares a custom domain. The four review-only rules (capital after a colon, lower case after a semicolon, serial comma, no em dash inside a list item) are exactly the ones no lint catches (adr-54), so injection is the only enforcement they can have; the observed effect in TeachingPrep is repeated lowercase-after-colon in agent-written handover files and ledger text from two different agent sessions. TeachingPrep has added a repo-override WRITING domain in .abcd/rules.json as the interim; a bundled default with the same rules and a broad recall list (write, draft, prose, note, handover, readme, markdown, document, report, message, edit, style) would replace it, and the repo override should then be removed. Relation to iss-2609012039220931: a bundled domain with common-word recall is exactly the case where recall breadth is a design choice rather than an abuse, so decide the two together.
- iss-2609200830002711No verb records an interview answer onto the record it settles. The planning interview on the intent surface page resolves open questions, the mechanism claim, the scope conditions and every acceptance criterion one at a time with the human, and step 9 says "edit the draft file to the confirmed content": each answer is prose the session writes by hand into the draft, and a repository that also logs decisions writes it a second time into its decision log, two writes that drift. Only the grounds step has a verb (intent ready --grounds). Relayed from the Gropius session gropiusllm-2b on 2026-09-20, running a one-decision-at-a-time interview over held drafts and captures with the answers fanned out to sub-agent lanes: every lane appended the answer to the draft and to DECISIONS.md by hand, and nothing downstream can read the answers as data. Wanted: a write path of the shape abcd intent answer <itd-N> <question-ref> "<text>" that records the answer on the record (under the open question it settles, or as the Mechanism or a Scope Conditions bullet by target) and, where the repository keeps a decision log, appends the dated line there in the same write, so the planning verb can read what was answered and what is still owed. Intent-shaped (a capability); the routing is the product thinker's.
- iss-2609200830076665A held draft has no frontmatter state, so nothing mechanical stops a lane from planning it. A hold on an intent draft is prose (a Review or Open Questions section saying it is held and why); the intent frontmatter the loader reads carries no hold field, and abcd intent plan checks the draft's sections and the bucket, never a hold. The surface page makes plan a human sign-off act that is never run unattended, which is the convention that holds today, and a sub-agent lane that follows its own brief rather than the page has nothing in its way. Relayed from the Gropius session gropiusllm-2b on 2026-09-20, which ran five record-only lanes on held drafts with a written prohibition on planning as the only guard. Wanted: a held: <reason> frontmatter key on a draft, written by a verb and refused as free text, with plan refusing a held draft and naming the reason, and the record dispatcher (abcd <itd-N>) reporting the hold as the next move. Sibling of iss-2609170726457256 (no verb stamps judged fields on a draft): this is the state field, that one the judgement fields.
- iss-2609200830169721A managed repository is running the whole intent lifecycle through one sub-agent per record, and asks whether the pattern should become an abcd recipe. The shape, reported by the Gropius session gropiusllm-2b on 2026-09-20: a main session interviews the product thinker one decision at a time, reading the reviewer's recorded options off the draft rather than re-deriving them, records each answer as it is given, then fans out one Opus 5 sub-agent per intent or issue, each in its own worktree, which fills the draft from the answers, runs abcd intent plan, writes the spec, implements test-first, runs the security and ruthless reviewers as its own sub-agents, closes the spec in the landing pull request and arms auto-merge; record-only lanes edit exactly one record each and may not plan. The session named what abcd already gave it (quoted-text filing, capture provenance flags, intent ready --json as the gate every lane runs, the Review and Open Questions convention on a held draft) and what it lacked (recorded separately: the answer write path, the hold state, the append-lock on the decision log, the integration-branch landing, the lane worktree location). Whether abcd documents this as a recipe (a plugin page, a runbook in the brief, or a scaffolded lane brief) is the product thinker's to decide; recorded here so the decision has a record to rest on. Note that abcd's own record already plans the worktree half (itd-148) and asks the same session-per-lane question from the coordination side (itd-2609150819440345).
- iss-2609200832054807No verb moves an untracked new record into a lane worktree. A draft filed with abcd intent "<text>" in the primary checkout is an untracked file with no history, so the one legitimate copy case in a worktree-per-lane flow, handing that draft to the lane that will plan and implement it, has no write path: the lane copies the file by hand, and the copy and the original are two untracked files with the same id in two trees until one is deleted, which is the shape the sibling-worktree visibility intent (itd-2609091416295622) exists to notice. Relayed from the Gropius session gropiusllm-2b on 2026-09-20 (sub-agent-lane experiment, low priority in the session's words). Wanted, either: a record export/import pair (or a move) that carries one uncommitted record from this checkout into a named worktree and removes it here, or filing directly into a named worktree (abcd intent "<text>" --worktree <lane>), so the record has one home from its first byte. Intent-shaped; the routing is the product thinker's.
- iss-2609200951237670blocked_by can be written only at capture time, and only against a record that already exists. abcd capture --blocked-by refuses a target absent from the ledger ("not found in the issue ledger; nothing written"), which is right for a typo but leaves no path for the ordinary case: the blocker is captured after the blocked record, or in another lane, and no verb adds the link afterwards (the capture sub-verbs are disposition, list, mentions, promote, resolve and wontfix). The Gropius session gropiusllm-97 hand-wrote blocked_by into frontmatter on 2026-09-20 and found the key's shape by running strings on the binary; the shape is in fact documented (the issue-store README and the capture surface page both carry it), so the discoverability half is that neither the refusal nor the flag help points there. Wanted: a post-hoc link verb, abcd capture link <iss-N> --blocked-by <iss-M> (and its removal), validated the way capture validates the flag, so the edge is written by a verb whichever record came first; and the refusal naming where the field is documented. Sibling of iss-2609091256264547 (the three typed relations the schema lacks): this is the one relation it has and cannot write after the fact.
- iss-2609200953255336An unknown command token that happens to be a plugin page name makes an up-to-date binary call itself stale. abcd abcd <record-id> (a misreading of the plugin page /abcd:abcd, whose invocation is the bare abcd <record-id>) prints "unknown command \"abcd\"" and then "this binary predates the abcd command the plugin surface it was provisioned from documents — this PATH copy is stale; run abcd update". Reproduced at v0.9.0 (4ae6f221) with a fresh build: the token abcd triggers the line, a made-up token does not, so the unknown-command path consults the plugin surface's page list, finds a page named abcd, and infers a verb the binary lacks. The page documents the dispatcher, not a verb; the binary has it, and the diagnostic is false on a pinned, up-to-date v0.9.0 (the reporting session's abcd version: pinned, vintage v0.9.0, up to date). A false staleness claim is the shape loud-staging forbids in the other direction: it sends the operator to update a binary that needs no update. Relayed from the Gropius session gropiusllm-97 on 2026-09-20. Wanted: the page-name check excludes the plugin's own dispatcher page (or checks the binary's command tree before claiming it predates anything), and for the token abcd specifically the refusal says did you mean abcd <record-id>.
- iss-2609201954342967The bare status board lacks two rows the record dispatcher already answers for a single record: suggested next actions for the repository, and the planned intents with their spec and whether it is in flight. Ruled by the product thinker on 2026-09-20 while superseding itd-20 (the Python-era board built on [redacted-user]-sync and the logbook) by itd-121: those two pieces of itd-20 are still wanted and are captured here so the supersession loses nothing. Wanted: (1) the board ends with a short next-actions list derived the way abcd <record-id> derives one record's next move (an owed fidelity audit, an unplanned draft with all decisions recorded, a stale claim); (2) the board lists each planned intent with its spec id and an in-flight marker where the spec is open and its branch exists. Both are read-only rows on the existing board; no new verb.related itd-2610031214560142 · related itd-2610031215002409
- iss-2609202015349672spec close --help does not say that the close creates an owed fidelity-review receipt. At v0.9.0 the verb closes the spec, ships the intent when it was the last open spec, and also mints an OWED receipt (rcp-…), stamps an abcd-review: OWED marker into the intent body and writes the review request under .abcd/.work.local/reviews/; the help text names only the first two. A session in a managed repository (the Dessau pilot, gropiusllm-64, 2026-09-20) met the receipt as a surprise line in the output and called it useful and undocumented at the verb. The surface page for the intent lifecycle does describe the audit that follows the close; the help is where the verb is met. Wanted: one sentence in the close verb's Long help naming the receipt, the marker and the request path, so the caller knows the audit is now owed and where its input is.
- iss-2609202046145653history capture has no current-session mode, so a run captures its own transcripts by listing files by hand. At v0.9.0 the verb takes one transcript path, and bare abcd history capture with no file answers "--session <id> is required when reading from stdin"; nothing discovers the session that is running or the sub-agent transcripts it spawned. The Dessau pilot (session gropiusllm-64, 2026-09-20) captured its session and seven sub-agent transcripts with eight invocations after listing ~/.claude/projects/<escaped-cwd>/<session>/subagents/agent-*.jsonl by hand, which is exactly the path knowledge the store already has (list --session reaches a session and every sub-agent it spawned on the read side). Wanted: a write-side twin of that read, history capture --session <id> --all (the main thread and every sub-agent), with the current session as the default when the harness exposes its id, so a loop captures its own run in one call. Evidence for the implement verb (itd-2609201916151817), which would call it at the end of every lane.
- iss-2609202053570475Every ledger verb should name which checkout's ledger it addressed. The ledger is per worktree and says so nowhere: a capture filed in one worktree is invisible to capture resolve in another, and the verb's refusal reads "not found" with no hint that another checkout holds the record. The cheapest always-on remedy, asked for in the 2026-09-18 corroboration on iss-2609020716570699 and routed out of the peer-listing intent by its record-discipline review on 2026-09-20 as a cross-cutting change: one line from every ledger verb (capture, resolve, wontfix, promote, list, the record dispatcher, intent audit) naming the checkout root and branch whose ledger it read or wrote, on stderr in the text render and as a member in --json. Distinct from the peer listing (itd-2609091416295622), which reads other checkouts; this is the verb saying which one it is in.
- iss-2609202055103741The interview rule makes the agent offer options that are not real choices, and asks a question where only one answer is sound. The GRILL domain in .abcd/rules.json says options widen and never recommend, no starred default, the null answer always available, and every question through the interactive tool one at a time. Followed literally on 2026-09-20 during the peer-listing interview, that produced a question whose three options were one sound answer beside two the record's own principle (loud-staging) already rules out, and the product thinker answered "why these options? Isn't 1 the obvious choice here?". The rule as written confuses two things: not steering the human (right) and manufacturing alternatives so a question has three of them (wrong). Ruled by the product thinker on 2026-09-20: the rule should not offer nonsense options; if there are no sensible alternatives, do not show them; if there is a single genuine answer, record it with the reason and do not put the question to the product thinker or the technical facilitator at all. Wanted: the GRILL domain reworded to say that a question is asked only where two or more answers are each defensible on the record, that the option set is exactly those answers plus the null answer, and that a decision with one defensible answer is recorded as a decision line naming why no question was asked; the itd-201 draft (every question asked one at a time, in plain language) is where the surface rule lives and should carry the same change.
- iss-2609202058058301A confirmation question must show what is being confirmed inside the question itself; the human cannot confirm what they cannot see. During the peer-listing planning interview on 2026-09-20 the agent listed the rewritten acceptance criteria in prose and then asked, through the interactive question tool, "are these thirteen criteria yours as written?"; the product thinker answered "which criteria? I cannot see them". The prose an agent writes between tool calls does not reliably reach the human; the question tool is the surface they read. The same shape recurred twice earlier in the session (an explanation of options given in prose, the question asked without it). Ruled by the product thinker: show the options, or the text to be confirmed, before asking for confirmation, in the question itself. Wanted: the GRILL domain in .abcd/rules.json and the interview steps on the intent surface page (step 8, walking every criterion; step 3, confirming the press release) say that the material a human is asked to accept, edit or strike is quoted in the question, never referred to; and the itd-201 draft (every question asked one at a time, in plain language) carries the same rule. Sibling of iss-2609202055103741 (no nonsense options): that one is about which options are offered, this one about the human seeing what they answer.
- iss-2609210748032488The cold-reading window eval fails on every branch that grows the intent, capture or lint surfaces, and the recalibration it names is a hand-run recipe no verb performs. TestEveryCommittedEntryFitsItsDeclaredWindow (evals/coldreading_window_test.go, in the smoke lane, so in make preflight and the pre-push hook) re-measures each committed preset entry against the tokens_est it declares, and the widening and detection objects list internal/core/intent, internal/core/lint, commands/intent.md and commands/capture.md by path, so any change on the intent lifecycle moves the measurement; the declared margin is one per cent, about nine thousand tokens on a nine-hundred-thousand-token object, which one lane consumes. Measured in the pilot run of 2026-09-20: main at the pilot base 891623 (widening) and 900660 (detection); lane B alone 897023; lane B merged with lane A 900584, 584 over its declaration; lane C alone 905106 and 914143, over both. The remedy the eval names (re-measure by dry run, move the declaration to the smallest ten-thousand boundary with at least one per cent headroom, restamp measured_tokens_est, measured_bytes and measured_at, commit with the reason) has now been run by hand four times (twice on 2026-09-15, precedent fc5c7e27; twice in the pilot), each time by a fresh agent at about fifteen minutes and eighty thousand tokens. Wanted: a verb (working name: reading calibrate) that performs the stated rule for every position and prints the commit body, so a merged tip is recalibrated by one command; the smaller rung is a script under scripts/. Separately for the product thinker: whether one per cent is the right margin when a single lane's text exceeds it.
- iss-2609210748122003A hand-spelled held key with a space before the colon is honoured by every reader and reported by no lint rule. The frontmatter scanner's key regex accepts a space before the colon and the intent loader, intent plan and the record dispatcher all read such a line as a legal hold, but the record_provenance rule sees the key only after the scanner has normalised it, so a line no verb writes (the verb writes held: with no space) passes lint silently; intent unhold refuses it (the remover matches the exact spelling) and sends the caller to repair the line by hand, which is the right refusal but the only signal. Found while applying the review ruling on iss-2609200830076665's fix round. Wanted: record_provenance reports the spelling as a shape no write path produces, the way it reports the disclosure pair, or the scanner exposes the raw key spelling so the rule can see it.
- iss-2609210828122412abcd must never do this to a machine when running tests for a repo it manages. On 2026-09-21 at 08:16Z the development Mac kernel-panicked (userspace watchdog: no successful check-ins from WindowServer in 120 seconds, two induced crashes, then the panic), killing the pilot run's orchestrator session mid-gate and losing its scratchpad. The stackshot taken 25 seconds before the first WindowServer kill shows CPU starvation, not memory: eight orphaned /usr/bin/yes processes pegging eight cores for 2.3 days, two spinning zsh loops, and abcd's own reading.test and cli.test running under them from another session's go test; the OS's low-priority daemons (dasd at priority 4) got under a millisecond of CPU, 500-plus threads queued behind them through turnstiles, and WindowServer blocked in a synchronous XPC to cfprefsd that was itself blocked behind dasd. The burners came from a test-under-load experiment in a managed repository on 2026-09-19: an agent launched eight of them with nohup yes and appended each pid to a file whose directory did not exist yet, so the launches succeeded and the bookkeeping failed; the later kill loop read the pid file, pgrep -x yes still printed 8, a second kill pass over the same file followed, and the agent declared the machine clean. The pattern is one abcd can be asked to run and must refuse to run this way. Wanted, as the rule the record carries: (1) a test or experiment that spawns background load owns its children in a way that survives a failed bookkeeping step, a process group or setsid with the group killed, or a parent that dies with the session, never nohup with pids in a file as the only handle; (2) clean is proven by a process query, pgrep -x on the session's own burner name returning nothing, never by the pid file having been read; (3) a load experiment on a live development machine needs explicit consent and a hard ceiling below the core count, leaving cores for the OS's own daemons, and abcd's own test run is never started while such load is present, so the gate reads the load average before it begins and refuses above a declared ceiling, naming what is burning. Severity major: it took the product thinker's machine down and lost a session. Diagnostic report names (under the system's diagnostic-reports directory): panic-full-2026-09-21-091803.0002.panic, WindowServer-2026-09-21-091552.ips, WindowServer-2026-09-21-091632.ips, and two WindowServer userspace_watchdog_timeout spin stackshots.related itd-2609231434459890
- iss-2609211105010877Two lanes that each add a verb to the same surface conflict by construction: commands/intent.md, the CLI's dispatcher and its test file, docs/reference/cli/commands.md and release/surface.json all took every lane's edit, and every merge of main into a later lane resolved the same files again (lanes A and B on the intent page, B and C on the page and the lifecycle, C and D on the CLI file and the generated pages). Nothing warns a lane when a sibling branch edits the page it is about to edit, and the generated files double the conflict surface. Wanted, as an observation for the implement verb: a lane brief names the sibling branches touching its files (git can answer it at branch time), and the generated surfaces are regenerated on the merged tip rather than merged by hand.
- iss-2609211105011107capture resolve --commit wants the sha of the commit that fixed the record, so the resolution is a second commit by construction: the lane commits the fix, runs capture resolve --commit <that sha>, and commits the ledger move with the Resolves: trailer on the second commit. Every one of the pilot run's four lanes produced this pair, and AGENTS.md's rule that a fix resolves its record in the same change is met only by the pair, never by one commit. Wanted: either resolve accepts a placeholder the post-commit stamp fills (the reachability gates RS002/RS003 already verify the sha after the fact), or the surface page states the two-commit shape as the documented protocol so an implementer stops trying to make it one.
- iss-2609211105011322A pull request that goes BEHIND main under the strict ruleset never enqueues: the merge queue requires an up-to-date branch, and auto-merge armed on a PR that then falls behind waits forever without a word. The only recovery is scripts/pr-keep-current.sh, a forge update-branch that lives outside abcd; the pilot run hit it on its first lane (PR 647, update-branch at 23:37Z after a sibling merged) and every later lane was sequenced around it by hand. Nothing abcd prints at push or PR time names the condition, the remedy or the sequencing rule (one lane in the queue at a time when they share a file). Wanted: the launch or capture surface that opens a PR says the rule, and a verb or the keep-current script is reachable from the plugin surface, so an orchestrating agent does not learn it from a stalled queue.
- iss-2609211105014235Under the two-sub-agent ceiling, reviews run one at a time in the gaps and each fix round is a fresh agent, so the pattern implement, review, fix, security review, fix consumes the whole ceiling for one lane: in the pilot's first two-hour session lane D never opened (40 minutes of pure ceiling wait) and lane B's review waited 27 minutes; in the second session D waited 30 minutes before a stop. Measured cost across the run: 178 agent-minutes in 120 wall-minutes (session 1), 149 in 122 (session 2). Wanted, as a pacing input for itd-2609201925079472: the ceiling counts reviewers separately from implementers, or the window length is set from the lane shape (implement plus two reviews plus two fix rounds is about 90 agent-minutes per lane), rather than a flat two.
- iss-2609211105021406What abcd implement would have to carry to launch the pilot run without its prompt, from having run it: (1) the run file's part 1 as data: the design decisions, one per lane, that the run is not allowed to reopen, and a stop that names the decision it lacks; (2) the lane table: record ids, the files each touches, the sibling lanes touching the same files, the base sha, and the worktree path under the machine-scoped store; (3) the roles and models per role, with a fresh agent per fix round and a reviewer that never implemented; (4) the pace: window length, the pause as idle wake-ups, the agent ceiling with reviewers counted, and the tally fields written per session (lanes opened, finished, PRs, ceiling-wait minutes, agent-minutes, tokens); (5) the gate ladder per lane: preflight and fmt-check under the HOME alias where the username collides, the issue-resolution gate on the PR form, the push, the PR body re-read and lint outbound, auto-merge with the queue's method, and the rule that an armed PR is never pushed to; (6) the pre-authorised remedies, today the window recalibration, as named recipes the lane may run once; (7) the stop conditions as a list the orchestrator checks after every report; (8) the handover shape, NEXT.md's pilot section, so a crashed session is resumed from it (this run's orchestrator died once and was resumed from NEXT.md alone, the scratchpad and the run file both lost). Evidence from the sibling pilot on the same day, Dessau pilot 2 (its account is at that repository's for_abcd/pilot-2026-09-21-2-experiment.md): the outer loop ran as a script end to end in 82 minutes with zero stops for the work; every step that needed a hand was record-writing (Departures at close, captures for audit concerns, reviewers missing from the session ledger), and the pause never fired because the run fit one window, so itd-2609201925079472's pacing is untested past the first window. Implementer context peaked at 170k there against 349k in the first pilot.
- iss-2609211105023379N lanes in flight that grow the reading corpus are N serial recalibrations of one file, .abcd/config/reading-presets.json, because every lane's recalibration rewrites the same four fields per position and conflicts with every other lane's, and the merge queue's update-branch cannot merge them. So two such PRs cannot be in the queue together: the second goes BEHIND when the first merges and is stuck on a conflict the forge cannot resolve. The pilot run sequenced its lanes by hand around this: lane C recalibrated three times (at its own tip, after PR 648, after PR 649) and lane D twice, at fifteen minutes and sixty to eighty thousand tokens each, and the last lane closed a full session later than its code was ready. Sibling of iss-2609210748032488 (the recalibration is a hand-run recipe): that record wants the verb; this one records that even with the verb the recalibration must happen once, on the integration tip, not once per lane — the calibration belongs to the merge, as a queue-side step or a single post-merge commit, not to the branch. For the big run's file: lanes that touch internal/core/intent, internal/core/lint, internal/core/capture or their surface pages cannot be queued together.
- iss-2609211119023345The command list shows a person and an agent the same verbs. abcd --help and the plugin's command pages list every verb alike, but the verbs split by who types them: a person types abcd build <itd-N>, abcd build next, abcd drain, abcd intent, abcd capture; a driving host or an agent calls abcd implement step, abcd implement receipt, abcd reading assemble, abcd intent audit ingest and the other machinery verbs a person never types. A product thinker reading the list today cannot tell which half is theirs, and the ruling of 2026-09-21 that build is the verb for people and implement the loop for the machine (itd-2609201916151817, decision 8) needs a place to show. Wanted: the command list distinguishes the two, the person's verbs by default and the agent's behind a flag such as --agent (or a section), with each command page saying which it is; the product thinker recalls an existing record asking for this cleanup, so the first step is to find and link it rather than file twice.
- iss-2609211414208891A reading run id drawn twice in one second refuses the second run instead of redrawing. The run id is the family tag, a second-resolution stamp and a uniform four-digit draw (adr-45), and reading assemble derives the default output directory from it; when two assemblies in the same second draw the same suffix, the second finds the first's directory non-empty and exits 2 with the one-run-one-directory refusal, though nothing about the second run was wrong. The rehearsal eval assembles several runs within one second, so the one-in-ten-thousand coincidence per same-second pair is met in CI: TestRehearseTheOpeningRunLoop/empty-output-commits-a-clean-run failed on PR 651 at 12:09Z with rdg-2609211209406944 already holding two entries, on a docs-only branch whose local preflight had passed twice. adr-45 leaves the same-second coincidence to the armed uniqueness detectors to assert against, and here the detector is the empty-directory refusal, which asserts by refusing the innocent run. Wanted: when the run will land in the default directory, the mint redraws while the drawn directory exists (a bounded number of draws, then a refusal that names the collision), so the detector's residue is absorbed at the one site that can tell a collision from an operator's occupied directory; an operator-named --out that is non-empty keeps refusing as it does.
- iss-2609211735419853A record slug is cut mid-token at the sixty-character cap, so a slug that ends in a numbered token reads as a different token: a capture whose text named acceptance criterion ac-10 landed as ...-ac-1, and one naming ac-13 the same, which reads as a capture about ac-1 and makes two distinct records look like one in a directory listing. The cut is collapsed[:60] followed by a hyphen trim, in three places that each derive a slug the same way and cap it the same way: the capture ledger, the intent store and the decision store. Wanted: one slug cap in the record-id package, the one home for record filenames, that cuts at the last token boundary at or before the cap (and only falls back to a hard cut when the first token alone exceeds it), with the three sites calling it; a slug never ends in a token the text did not contain.
- iss-2609211738504433A planned intent with no spec cannot be given one by any verb. Fourteen intents sit in planned/ with spec_id null (itd-6, 7, 24, 27, 28, 34, 36, 42, 48, 50, 53, 58, 63, 69), planned before the spec seam existed; the readiness gate reports each as not ready, and the autonomous run treats them as skips with a planning brief each. The way to a spec is closed on every side: intent plan on an already-planned record does the identity step alone and touches no spec; intent link writes a spec_id only for a spec that exists; the spec store has no mint of its own, only close. So the only path is a hand move of the record from planned/ back to drafts/ and a fresh plan, which no verb performs and the lifecycle does not name. Wanted: intent plan on a planned record whose spec_id is null mints and links the spec the way it does for a draft, without moving a bucket, on the same human sign-off; the readiness gate's remedy names that command instead of one that cannot run.
- iss-2609211905340006Dredge synthesis output lands in the memory store as its own source class. itd-36 (closed as delivered on 2026-09-21) asked that the dredge synthesiser (itd-25, still a draft) write its synthesised entries to .abcd/memory/<type>_<domain>_<slug>.md with source.class dredge_synthesis and the per-run provenance the lint reads; dredge does not exist yet, so the memory store has no such class and the lint has no rule for it. Wanted, when itd-25 is planned: the class in the closed enum, the writer in the dredge path, and MS001/MS002 reading it as a cross-class input.related itd-25
- iss-2609211905346507One registry entry for a source ingested as documentation and vendored as code. itd-36 (closed as delivered on 2026-09-21) asked that the same source content ingested by memory ingest and by the code-vendoring path (itd-26, loot, still a draft) share one provenance registry entry with an ingest count of two; the vendoring path does not exist, so the registry has one writer and no count. Wanted, when itd-26 is planned: the registry keyed by source hash across both paths, the count, and one licence declaration read by both.related itd-26
- iss-2609211905347458The lifeboat restrictive-licence gate does not read a kept memory original. itd-36 (closed as delivered on 2026-09-21) asked that disembark refuse to surface .abcd/memory/sources/<sha256>.<ext> (an original kept with --keep-original) unless the launch allowlist names it, and refuse a gated payload carrying a GPL-3.0 citation when the project publishes as MIT; the memory pages carry source.licence today, and disembark packs the record families by path without reading that field. Wanted: the disembark gate reads source.licence on memory pages and the kept originals, refuses a restrictive licence against the project licence, and names the allowlist that admits one.
- iss-2609212142557657The guard's hook payload omits a per-call working directory, so a command moved into it slips the command-string match. guardHookInput reads the session cwd and tool_input.command and nothing else; a host whose shell tool takes a per-call working-directory field (opencode's does; a future Claude Code field would) can carry a destructive command whose target is the directory rather than an argument, and the match over argv sees nothing hazardous. Live-demonstrated in lab 2's smoke (probe p5b-live-session-retest under the lab home): the model set the tool's workdir and ran the bare destructive verb. Verified at main on 2026-09-21: the struct is unchanged. Decision owed to the product thinker: extend the guard contract to read a working-directory field where the host supplies one and resolve the command against it, or document the reach in adr-42's mistake-filter scope as outside the boundary. Not a security boundary by adr-42's own statement, which is why the severity is minor; the category is security because the slip is the shape a mistake filter exists to catch.
- iss-2609212142568782The private banlist accepts a fragment shorter than a word and nothing warns that it will match names. A five-character fragment in the operator-tier private list matched a cited author's first name, so the guard refused a design branch's merge on one machine until the pattern was refined by hand; the store took the fragment without comment. The pattern itself is private and stays out of the record. Wanted: banlist add warns on a pattern below a declared length or without a word boundary, names the risk (it will match inside ordinary words and names), and takes an explicit flag to keep it; the guard's refusal on a private-tier hit names the pattern's length class so the operator knows where to look.
- iss-2609221820487644The attribution gate should let a dependabot dependency bump through without a human re-authoring it. The product thinker asked for this on 2026-09-22 after PR 655 sat blocked with auto-merge armed and every other check green. Two things must be said precisely, because the request names the trailer and the trailer is not what fails. The gate refuses a bot on IDENTITY: check_ident reads dependabot[bot] as a machine in the author role on two independent signals, the forge's [bot] name suffix and the bot mailbox, and it deliberately stays silent about the missing Assisted-by trailer so the remedy is not misread, its own comment saying that adding a trailer is not the fix for a dependency bump and landing it as a human is. No review clears an identity refusal, which is why an armed auto-merge looks like it is waiting for a reviewer when it is waiting for something no reviewer can give. The rule is deliberate and stated in AGENTS.md: the contributor graph is built from the author and committer fields, a machine there asserts an authorship it does not hold, and a squash merge re-appends a mis-identified branch author as a co-author, so the consequence, that a dependabot pull request is not mergeable as authored, is written down as intended. Wanted: a way for a dependency bump to land without a person re-authoring it every time, without letting a machine into the contributor graph on any other change. Candidate shapes for the decision to weigh: the gate exempts a commit whose diff touches only go.mod and go.sum on a branch the forge marks as dependabot's, with the exemption named in the refusal it would otherwise raise; or the repository takes dependabot's bumps through a workflow that re-authors them as the human owner before the gate runs, so nothing about the gate changes; or dependabot is turned off for this repository and bumps are made by hand on a schedule. This reverses a stated rule, so it is an ADR plus a brief invariant before any code moves, not a quiet edit to the script.related itd-2609221842494980
- iss-2609230641546141fsutil.RedactRoot (and so RedactHome and the CLI's error scrub) replaces a root that ends at a path boundary but never checks the boundary BEFORE it, so a root that appears as a suffix of a longer absolute path is redacted inside it: with HOME=/var/folders/x/T/home and git reporting the resolved /private/var/folders/x/T/home/wt/a, RedactHome returns /private~/wt/a — the prefix stranded in front of the tilde, and the path neither redacted nor intact. Seen while building the peer listing on macOS, whose temp dirs sit behind the /var -> /private/var symlink; the peers surface works around it by redacting the resolved home spelling first (internal/surface/cli/peers.go redactHomePath). Expected: a match that does not start at the string's start or after a non-path character is left alone, the way the right-hand boundary already is.
- iss-2609230720193756The implement run state has two same-uid hygiene gaps the security review of itd-2609221656373558 rated LOW and shipped past on the record: fsutil.AppendLineIn's openAppendIn (internal/fsutil/fsutil.go) opens the log leaf without the Lstat and symlink refusal its read twin ReadGuardedInRoot applies, so an in-root symlink leaf redirects every appended line (demonstrated: a log symlinked onto a claim file makes the claim unreadable); and readClaim (internal/core/implement/claim.go) checks a claim file's session and lane only for non-empty before they reach HeldError and the release refusal, printed to stderr unsanitised, so a hand-edited claim can put terminal escapes on the operator's screen. Remedy, each test-held: refuse a symlink leaf in openAppendIn as the read primitive does, and run validName on the claim's session and lane in readClaim treating failure as unreadable. Also: .lock is created 0644 beside 0600 run files (internal/fsutil/flock.go), and commands/implement.md does not say the release refusal rests on a cooperative, unauthenticated role. The next lane that extends internal/core/implement (the build verb, itd-2609201916151817) takes it.
- iss-2609230733497536itd-67 ac-3 promises that a ship bumps plugin.json.version, updates marketplace.json and that /plugin update abcd pulls the new version; delivered reality: launch ship stamps the version only into a payload staged outside the repository when --payload-dir is passed (internal/surface/cli/ship.go), release.yml uploads binaries and checksums.txt only, and the marketplace source ./ is the git tree whose committed manifests carry no version — so the version-stamped manifests are produced by nothing in the release path and consumed by nothing; the installed plugin's version arrives through the bootstrap binary download alone. Found by the itd-67 fidelity audit (rcp-7af1556ce4f7).
- iss-2609230733540527itd-67 ac-4 promises a phase-completion bump tier named in the launch report and a major bump only via an explicit --version <x.0.0>; delivered reality: the tier derives from record impact (internal/core/changelog/version.go), the report names the deciding impact and record and no phase, and the ship verb carries no --version flag at all — spc-11 records the supersession under Reconciliations but the intent's criterion was never amended, and the documented human override for the first 1.0.0 has no verb: the only path is a hand-written CHANGELOG heading. Found by the itd-67 fidelity audit (rcp-7af1556ce4f7).
- iss-2609230733586740itd-73 ac-5 promises that an intent captured or shaped with an absent or invalid impact is flagged as a blocker; delivered reality: intent_impact_valid flags an invalid or internal value in every bucket but an ABSENT impact only in shipped/ (internal/core/lint/lint.go checkIntentImpact), and CreateFromText leaves impact optional on a draft — so a draft or planned intent carries no impact until the spec close forces one. Narrower than the criterion; spc-10 states the shipped/ bar only. Found by the itd-73 fidelity audit (rcp-0d18ea2d4682).
- iss-2609230734017018itd-101 ac-4 promises that the later generated checklist page hands back a receipt file the confirm verb ingests; delivered reality: docs cite confirm --receipt ingests the one Receipt schema (internal/core/cite/confirm.go) and refresh prints the manual queue, but no generated checklist page exists in the tree — spc-17 records it as a rung that may land later, so the receipt-file half of the criterion has a consumer and no producer. Found by the itd-101 fidelity audit (rcp-c9215c58f907).
- iss-2609230851376499The read-side MR001 lint reports an ordinary memory store as a blocker when a page name is prose-shaped. residueOfStoreFiles scans the sources registry bytes at the scanner.BlockingResidual bar, and the registry carries every page back-link, so a back-link such as topic_home_migrating-[redacted-hostname].md matches net_device_hostname at warn on the hyphen boundary and memory lint exits 1 with 'stored text carries a net:device_hostname span' on a store the write side produced without complaint. The write side already knows this: redactRegistryLeaves excludes the back-link list from the leaf walk for exactly this slug, and judgeFilename judges page names at the hard_fail bar alone. The read side holds a back-link to the free-text bar, so the two sides disagree on the same bytes. Reproduced at bad1c73e by ingesting a page with domain home and slug [redacted-hostname] and running Lint: one MR001 blocker on .sources_index.json. Remedy: judge back-link names by the page-name rule and keep them out of the registry's free-text scan.
- iss-2609230949465250itd-155 ac-1 narrowed: the galloping adjacency probe (internal/adapter/scanner/scanner.go gallopingFind) grows under a per-line budget of 4*len(line)+4096 bytes and, once that budget is spent, keeps the fixed 512-byte window it already has — so on a line engineered to grow the window at many junctions a match end can again be a truncation artefact of the window edge, the shape iss-189/iss-190 were about. A single long token always fits the budget. The trade-off (a measured quadratic cliff without the cap) is recorded in code only; the intent promises 'never a truncation artifact' unconditionally, so the promise or the record should say where the guarantee ends
- iss-2609230949466602itd-154 ac-2 not met: hooks/bootstrap.sh deliberately prints no eager 'provisioning the abcd binary…' line when it fetches the binary (the phrase is reserved for the EXIT trap's death report), so a successful provisioning run emits only the terminal 'abcd bootstrap: installed' line; the intent's criterion promised a visible loud-staged provisioning line on every fetch. The reasoning (only the first stderr line reaches the transcript, iss-208/iss-207) is recorded in the script, not in the intent or its spec — the record and the delivery disagree and one of them should move
- iss-2609231006554434The user-scope inventory omits the run store: abcd implement keeps its run state in ~/.abcd/runs/<root-sha>/, but neither the tree in 04-surfaces/01-ahoy.md nor the paragraph in 05-internals/03-configuration.md, which say they are one list that must agree, names it.
- iss-2609231010077584itd-157 ac-3 narrowed: the intent promised that the overlap gate 'flags the by-links overlap as a red result', and the delivery (PR #555, 64ac809c) widens the count to both arrangements and prints it (internal/surface/cli/site.go:201 'N overlapping bubbles across both arrangements'), but nothing outside the test suite goes red on a non-zero count — 'site build' exits 0 with the number in its summary, and 'site check' (internal/core/site/check.go) never reads Layout.Overlaps, so the make site-render gate passes a record whose by-links picture overlaps. The only red is TestBuildLayoutDoesNotOverlap over the test fixture and TestByLinksNeverOverlaps over synthetic corpora, neither of which sees a user's record. Either 'site check' should refuse on a non-zero published count or the intent's criterion should say the gate is the test suite
- iss-2609231011136579abcd intent audit ingest writes the shipped intent back with no trailing newline: upsertReviewBlock (internal/core/intent/audit.go:956-980) splits the record on newline, and when the OWED marker's block runs to end of file it sets end = len(lines), so the trailing empty element that carried the file's final newline is dropped from lines[end:] and strings.Join returns a body ending at the last byte of the new block. The appendToAuditNotes path (audit.go:985-1041) re-adds the separator, so only the replace-in-place path (every OWED -> INGESTED transition) loses the newline. Observed on itd-157 and the batch-0 audits before it: the file ends in '- missing: (none)' with no newline. Every other record writer in the tree ends its file with a newline; the fix is to preserve the trailing empty element (or TrimRight and append one newline) in upsertReviewBlock, with a test asserting the ingested record ends in a newline
- iss-2609231012180437itd-158 ac-2 narrowed: spc-51 says a provenance record carrying pass_b_exemption makes the consumer classify the section Pass B would have grounded as declared exempt — 'reported as an exemption with its reason, not enumerated among the coverage blanks — answer these first'. The delivery (PR #555) recognises the exemption at record level only: renderCoverageBlanks (internal/core/lifeboat/embark_render.go:85) prints one 'pass B (transcripts): declared exempt — <reason>' line above the blanks, and TestEmbarkUnmarkedProvenanceReadsAsBefore (embark_test.go:1167) pins that the marker changes nothing else, so every blank Pass B would have filled is still listed as work the human is left. The intent's criterion (the record is recognised as exempt rather than as an unmarked gap) holds; the spec's per-section reclassification does not, and coverage carries no per-pass attribution to make it possible. Either the spec's approach should be corrected to what shipped or the handoff should stop asking the human for Pass-B-shaped blanks
- iss-2609231016278107itd-162 ac-1/ac-2 diverged: the adopt phase's commit-gate step used to offer a secrets + absolute-path gate as a pre-commit framework config (commands/prepare-this-repo.md at 328a6755^1 lines 171-174, template under a machine-local ~ path), and the intent promised that asset would resolve from the record or the binary instead. The delivery (PR #555) substitutes a different asset: step 5 now scaffolds abcd's private name guard (internal/core/ahoy/defaults/pre-commit, via ahoy install), and the embedded hook carries no secrets scan and no absolute-path gate, so an adopted repository no longer gets the gate the step existed to offer. spc-54 conflated the two ('the pre-commit config the Phase-3 line reaches for is thus already available embedded'). Either the adopt phase should offer a secrets/absolute-path commit gate from the binary or the record should say that gate was dropped deliberately
- iss-2609231036448320abcd intent audit ingest copies the verifier's rationale prose verbatim into the shipped intent's Audit Notes, and that record is lint-bound: a rationale that names a test's illustrative id (an auditor citing TestCheckRefusesADanglingSpecTarget wrote the spec id the fixture dangles to) makes record-lint refuse the whole tree with a prose_citation_resolves BLOCKER on the ingested line, and the verdict schema offers no way to carry the '<!-- record-lint: illustrative -->' marker the rule asks for. The ingest validates the verdict against the rubric but not against the record gates the record it writes must pass, so a valid verdict can produce an uncommittable record; the auditor's only remedy is to re-word and re-ingest. Either the ingest should run the prose-citation check over the rendered block and refuse the verdict with the offending id named, or the verdict shape should let a rationale mark an id as illustrative
- iss-2609231050273096abcd update verifies a downloaded binary only against the checksums.txt published in the same GitHub release (internal/core/update/update.go), so it catches corruption in transit but not a release page whose binary and checksums.txt were both replaced; the binary needs an independent check next cycle, such as a digest committed in the repository's history the way the plugin catalog now pins the plugin archive (adr-2609231048308186), or verification of the release's signed build-provenance attestation (a new verification dependency needs sign-off first). Ruled by the product thinker on 2026-09-23 (E5, 10:27Z): harden next cycle; this release keeps the same-page check.
- iss-2609231101102072The verification matrix keeps pre-rename vocabulary for two renamed verbs: its rows read 'Intent fidelity review (Role 1)' and 'Press-release oracle audit', while the intent audit (itd-123, ac-2: brief prose moves to the audit vocabulary) and the lifeboat review (itd-125, ac-5: the brief's oracle-audit prose moves to review) each promised the brief's current-state prose would move. Found by the fidelity audit of both intents; the page is 06-delivery/02-verification-matrix.md.
- iss-2609231103413459A default ahoy install still commits abcd's name, and abcd-internal record references, outside the .abcd/ namespace the adopter accepts: the two name-guard hooks (.githooks/pre-commit and .githooks/pre-merge-commit: the '# abcd-name-guard: v1' marker, prose naming abcd, 'abcd ahoy' and 'abcd banlist', and the itd-74 / spc-20 ids) and the .gitignore fence ('# BEGIN ABCD', '# abcd-managed block — do not hand-edit. Run /abcd:ahoy to refresh.'). Reproduced 2026-09-23 on a fresh git repo with 'abcd ahoy install --yes --adopt --visibility private': grep -ril abcd over the tracked result names both hooks and .gitignore. The 2026-09-11 ruling (iss-2609110944498549) is that ahoy install must not write abcd by name into a repository it adopts, and prepare-this-repo's acceptance promises no abcd-internal content in any committed artefact. The fix for that record removed the conventions-file block from the default (docs target skip); these writes remain. Major: this is the unmet remainder of iss-2609110944498549 (major), whose acceptance 1 (no committed file contains abcd after a default install) this record now holds; it carries that severity rather than a lower one, so the remainder still meets the release-cut guard. The hooks are not the files a repository's contributors read first, and the hooks run the abcd binary, so part of the naming is functional, but that bears on the fix, not on whether the ruling is met. What a fix has to settle: the hook marker and the fence are what detection classifies by (classifyGuardHook, gitignoreBlockDrifts), so a rename is a migration over every already-adopted repo, and the hooks are security-sensitive; whether the name in a hook that invokes the tool is in scope of the ruling at all is the product thinker's call.
- iss-2609231128235366The capture surface chapter (.abcd/development/brief/04-surfaces/06-capture.md, 'One flag is conditionally required') and the ledger README (.abcd/work/issues/README.md, '--lapsed-at (required with --category lapse)') state that a lapse capture without --lapsed-at exits 2 and writes nothing. It does not: the refusal is parked (iss-2609091009111294; the CLI comment in internal/surface/cli/cli.go says so, as does commands/capture.md and the same chapter further down), and 'abcd capture "..." --category lapse' with no --lapsed-at files the record at exit 0, confirmed in a scratch repository on 2026-09-23. Two prose surfaces describe a refusal the verb does not make.
- iss-2609231156260287abcd capture writes a record with an empty found_at silently, and that is the shape all nine misfiled installer records of iss-2609120511058115 had: the guard that closed that record refuses a path-shaped found_at absent from the checkout, which none of the nine carried, so the batch that motivated it would still file today. A capture without found_at is legitimate (a conceptual finding, a process observation) and must stay legitimate, so the remedy the record floated is a nudge rather than a refusal: when --found-at is absent, the verb says the record names no location in this checkout and so nothing ties it to the repository it is filed into (on stderr, and as a field in --json), without changing the exit code or what is written. Acceptance: given a capture with no --found-at, when the verb runs, then the record is written as today and the output says no location was named; given one with a found_at, no such line appears.
- iss-2609231159264048TestBannerRendersAboveBoard renders the bare board twice in the package directory of the live checkout and requires the two renders to agree byte for byte; since the board gained its peers line it reads the sibling worktrees on disk, so a peer session creating or retiring a worktree between the two renders changes the live-peer count and fails the test (seen in a preflight: 30 live peers without the banner, 31 with it). The test is not hermetic: it should render in a directory with no peers.
- iss-2609231206190526itd-2609221656373558 criterion 4 promises the second session refuses a lane that recalibrates the reading corpus. Delivered: the corpus bound is applied only to paths the session declares, and a claim or lane check that declares no paths asks no corpus question (internal/core/implement/bounds.go:94-98), so a second session that names no paths opens a corpus lane unrefused. The refusal rests on self-declaration; the record should say so, or the bound should refuse an undeclared lane for the second role. Found by the fidelity audit; not fixed here.
- iss-2609231206196407itd-2609221656373558 criterion 6 promises that on contention of any kind the second session backs off and the log names the reason and the minutes spent. Delivered: a refused claim writes a backoff line with the reason but minutes fixed at 0 (internal/core/implement/claim.go:232), and a locked run state returns ErrContention from withLock with no log line at all (internal/core/implement/run.go:182-186), so lock contention is never counted in the derived comparison and the verb measures no backed-off minutes; queue contention is logged only when the session hand-writes implement log backoff. Found by the fidelity audit; not fixed here.
- iss-2609231206207995itd-43 criterion 1 promises no live reference to epic as a standalone noun in abcd-owned files. One survives on the brief's intent surface page, .abcd/development/brief/04-surfaces/05-intent.md:244 ('no epic currently owns it'), inside the fenced surface diagram opened at line 176, which GL002 skips by design as fenced text and a grep finds. Reword it to spec, or record that fenced diagrams are out of the sweep's scope. Found by the fidelity audit; not fixed here.
- iss-2609231526392449guard hook reads .abcd/guard.json from a REFUSED foreign-uid root when the workdir (or session cwd) is that root, while the refusal note says it was not read (internal/surface/cli/guard.go:430, internal/core/rules/root.go:255); it can only add hazards (Strictest), but the foreign file's why/successor text reaches the agent as the block message. Fixed on feat/ruled-security-forks (da3efea6/ebc6290d), not on main.
- iss-2609231553391212The promote join's back-links are renamed: an intent's `promoted_from` becomes `related_issues` and a ledger record's `promoted_to` becomes `related_intents`, in the files and the JSON output. Nothing reads the retired names; a record still carrying `promoted_to` is refused. A managed repository runs `abcd capture migrate --apply` once to rewrite them (without `--apply` it only reports).
- 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-2609231931006041itd-147 ac-3 (fidelity audit): the generated appendix of the three host-delegated commands says 'There is no shipped surface' while their register rows read shipped. UnbuiltSentence (internal/core/surface/appendix.go) is emitted for any chapter whose command the Go tree does not register, and /abcd:consult, /abcd:ingest and /abcd:prepare-this-repo are shipped host-delegated commands with a command page and no Go verb (04-surfaces/README.md, No skills). The block therefore states a false claim about the surface — the class the intent exists to remove — in 13-consult.md, 14-ingest.md and 15-prepare-this-repo.md. A host-delegated chapter needs its own sentence: shipped as a command page, with no Go verb and so no flags or sub-verbs to list; the generator can tell the cases apart from the register's Status column, which it already parses.
- iss-2609231931064874itd-147 ac-6 and ac-8 (fidelity audit): the intent's outcome check is owed and has no ledger record. The intent shipped by PR #671 with ac-6 (a full-tier brief-to-surface crosscheck after the seam lands classifies to no false-claim or stale-count about a covered flag or sub-verb) and ac-8 (progress assessed on which chapters are implicated) deferred to the next release gate; the only carrier is a paragraph in .abcd/development/release-gate/README.md that asks to be deleted when the result is recorded. Nothing in CI or the release cut asserts it, so a cut that skips the classification leaves the intent's headline outcome unverified with nothing to show it. The fidelity audit recorded ac-6 INCONCLUSIVE and ac-8 MET_WITH_CONCERNS for this reason. Resolve by running the full-tier crosscheck at the next release gate, classifying its findings chapter by chapter against the baseline table in research/data/2026-08-23-brief-surface-crosscheck/README.md, and recording the result with the run's commit in itd-147's Audit Notes.
- iss-2609231947544298The load check's stray rule is silent across a load band that itd-2609231434459890's Mechanism, Decision 1 and Grounds claim it covers. A process is a stray only when it is older than the stray limit and its lifetime share of a core is at least 0.9 (NearFullShare, internal/core/machineload/classify.go); the extreme trigger fires only when the one-minute load is strictly above four times the online cores. Busy loops that have run for days each hold their fair share, cores divided by their count, so on 16 cores at the default limits: 17 loops (0.94 of a core each) warn through the stray trigger; 18, 20, 40 or 64 loops, a load between 1.125 and 4 times the cores, each hold under 0.9 of a core and raise no trigger, so the check is silent (no warning, no run-log event); from 65 loops the warning is the extreme trigger's alone, as at the 2026-09-22/23 incident's load of about 440, where the stray count read 0. The share filter applies before the uid split, so the band silences the caller's own loops as well as another account's. The fixture that shows it is TestStrayRuleSilentBand in internal/core/machineload/classify_test.go (TestMechanismFlagsIncidentTwo pins the 440 case). Major: the check's main purpose, flagging a forgotten busy loop, fails silently in the band, and the intent's Grounds say it is shown wrong by exactly that. The remainder spec spc-2609232027132755 holds the intent planned on this band. Fixing it needs a ruling on the stray definition (a share relative to what the machine could give the process, or a second sample), which the lane cannot take.
- iss-2609232048579579TestPNGChunkCountBombIsBounded (internal/adapter/scanner/container_test.go) still fails on machine load although iss-2609091215552981 was resolved: the resolution moved the proof to the refusal but kept a plain-run wall-clock runaway guard of 10s against a run of about 1.5s, and at a 1-minute load of about 20 to 40 the plain run took 10.63s and failed while its own result carried the chunk bound's refusal (png: more than 1024 compressed chunks). The resolved record's grounds name exactly this as what would show it wrong: a red on a slow machine where the bound held. Observed in make preflight on the merged tip 7469213f of feat/guard-per-call-workdir. Fix: size the guard as a hang detector far above any plausible loaded run (or route it through the hang-budget helper the wall-clock sweep introduces), so only a runaway reds it; detector: with the chunk bound removed the test must still fail on the missing refusal.
- 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-2609240046582859Four tests outside the scanner package guard bounded work with a tight wall-clock ceiling, the shape that made the scanner's cost guards fail gates under machine load: internal/core/reading/project_test.go (10s near line 89 and 5s near line 112), internal/core/guard/speculate_bound_test.go (3s near line 108, the tightest) and internal/core/guard/brace_test.go (5s near line 190). Each should assert a load-independent count of work, as the scanner's guards now do, or carry a ceiling generous enough that load cannot trip it. Found by the gallop lane's sibling sweep.
- iss-2609240133234244Fidelity audit of itd-2609221656361680, ac-4 (the inbox renders waiting reports naming the sender repository): a waiting report the inbox cannot read — a later template version, or a malformed block — is listed by abcd inbox with a 12-hex prefix of its sender key and no sender name (internal/surface/cli/report.go, the UNREADABLE line), because the name sits in the envelope keys the failed parse never reaches (report.go judges schema_version before any other key). The intent's decision 4 puts identity in the inbox so the reader knows who is asking; for exactly the report that most needs a reply (a sender running a newer abcd), the reader gets a key prefix. The envelope is abcd's own writing, so it could be read independently of the reporter's block; or the unreadable line could name the sender from the promoted log or the other reports sharing that key. Minor; the report is not dropped and show renders the same.
- iss-2609240133237651Fidelity audit of itd-2609221656361680, ac-5 and ac-7 (no repository name in anything abcd commits): the name scrub a promotion runs (nameScrubber, commonName in internal/core/report/inbox.go) deliberately leaves a sender whose directory name is a common word or three letters or fewer (cli, api, go, docs, site, tools, unnamed, abcd) in the capture as a word, replacing it only where it ends a forge address. The brief chapter 30-inbox.md documents the exemption and its reason (the word identifies no one), but the intent's criterion and decision 4 promise the name is absent from anything committed without that qualification. Either the record narrows the promise to distinctive names or the scrub takes another route for common-word senders (a per-report marker, a generic replacement of the whole phrase). A record decision, not a code fix, until the product thinker rules.
- iss-2609240200426413`abcd <iss-N>` answers that the record is not found in the issue ledger when the record's file is there but was skipped on read, for example because it still carries a retired property such as `promoted_to`. describeIssue in internal/core/record/record.go reads only the parsed issues and never the skipped roster, so an adopter with an unmigrated ledger gets a false 'not found' with no hint to run `abcd capture migrate --apply`, while `abcd capture list` beside it names the remedy. The shape predates the related-links rename; the rename widens it to every unmigrated record.
- iss-2609240203342061The \A anchor in the scanner's adjacencyProbe is untested: with the anchor removed and the fixed probe window kept, the whole scanner package passes (confirmed by the gallop lane's second implementer and by its review, item 4). scanAllPatterns rejects any probe match whose start is not 0, so an unanchored probe returns no wrong result; the window still bounds each attempt, so the loss is a constant-factor cost (each attempt searches its whole window for a leftmost match instead of failing at byte 0, up to 512x per attempt), not a wrong finding. No cost guard sees it, because the count guards assert growth ratios and a constant factor leaves every ratio unchanged. This duplicates the parked iss-2609021205449871, which is not on main: whoever lands the parked sweep closes one of the pair as a duplicate of the other. <!-- record-lint: forward-looking -->
- iss-2609240203462704The scanner's count-based cost guards measure scanAllPatterns alone, so the rest of the per-line scan is outside every cost guard. probeWork (internal/adapter/scanner/adjacency_test.go) tallies only the bytes handed to the adjacency probes and the junction probe inside scanAllPatterns; the wall-clock guards it replaced timed scanLine, which is the whole of scanText. Uncovered stages: (1) each pattern's Skip and SkipAt callbacks, run per match against the matched text and the whole line; (2) the identity matchers (matchers.findings), run over the raw line and again over the decoded copy; (3) the percent-decode pre-pass (decodedLineFindings: percentDecodeBounded, the second scanAllPatterns run over the decoded copy, mapDecodedSpan); (4) the top-level cp.Re.FindAllStringIndex pass per pattern, which is RE2-linear but untallied. A regression that makes any of these superlinear passes every guard in the package. Counting them at the scanLine level needs a seam in scanText, which builds its probes internally and constructs the identity matchers from a fixed type with no hook for a counting stand-in, so it is a production change rather than a test-only one; hence captured, not added, in the gallop lane.
- iss-2609240227150859itd-6's Implementation status and its post-spc-5 Status paragraph say spc-5 built a typed RPUnavailable error in internal/core and a concrete MCPBridge (the ADR-02 spawn implementation and the ADR-03 host-reuse path), and its Resolved sections route failures through oracle.py. None of it is in the binary: grep for MCPBridge, RPUnavailable and RepoPrompt over internal/ and cmd/ finds only the scanner's RepoPrompt sessionKey pattern (internal/adapter/scanner/patterns.go) and a guard corpus line, and go.mod carries no MCP dependency. The sections describe an earlier Python lineage, so a planner or an implementer reading the planned record is told a foundation exists that does not; the re-filed scope (spc-2609211950427074) needs that foundation built from nothing.
- iss-2609240227236354itd-6 passes its readiness gate (intent ready itd-6: READY, all seven checks ok) but cannot be built from today's tree: its spec spc-2609211950427074 stands on four things that do not exist. (1) The build loop's validator stage the adapter implements, itd-2609201916151817 (planned, spec spc-2609202134338445 open; there is no build verb). (2) The layered oracle.review resolver the model-tier and pacing intents share, itd-2609170822093401 and itd-2609201925079472 (both planned, specs spc-2609180535002478 and spc-2609202134341288 open). (3) The command-line runner the adapters chapter entry sits beside, itd-2609201916056194 (planned, spec spc-2609221533057881 open). (4) An MCP client, which the spec's Approach names as a new dependency subject to the new-dependency sign-off; go.mod has none. itd-6 declares builds_on [itd-2] only, so the gate has no edge to refuse on and READY reads as buildable to a run that picks it.
- iss-2609240227447110itd-7 (planned, spec_id null) hangs its workspace pull on abcd dev-sync, which has no verb and no code: the CLI's command list carries no dev-sync, grep over internal/ and cmd/ finds none, and the only record of it is the draft itd-13 (scheduled dev-sync). Its lifeboat route does not exist either: embark writes only four record families, adrs, issues, intents and specs (embarkFamilies in internal/core/lifeboat/embark_types.go), and names every other file as one it does not write, so .abcd/rp/workspace.json has no path from a lifeboat into a target repository as acceptance criteria 6 and 7 require. itd-6 Decision 4 already has itd-7 waiting; the record does not say that its own two prerequisites are missing as well.
- iss-2609240227595724itd-33 (draft, written 2026-07-06) runs against three later rulings, which its planning interview has to settle. (1) adr-2609091248200336 (2026-09-09): agent and session state is machine-scoped under ~/.abcd/ keyed on the root commit, and the checkout holds only its declared tiers; itd-33 puts per-machine live state and locks (active-work.json, *.lock) in a new .abcd/coordination/ directory inside the checkout, which is no declared tier, beside a committed audit/ log. The shipped claim of itd-2609221656373558 already keeps its run store outside the repository. (2) The basics-plus-adapter principle (principles/basics-built-in-adapters-bring-power.md, 2026-09-15): every capability ships a basic form and offers an opt-in adapter for the full form; itd-33 is always on with no opt-out and rules out any external route, so it offers no adapter. This one is a tension in spirit: the principle's letter does not forbid an always-on basic. (3) itd-2609221656361680 Decision 4, identity in the inbox and a fingerprint in the record: anything committed carries the root-commit key and a generic description; itd-33's committed audit log names the person from git config on every agent_registered event and in resolved_by_human. Decision 4's letter governs the managed-repository reports; applying it here is by extension. The register ruling (itd-2609150819440345 Decision 1, the register is where claims live) overlaps its claim model too. Distinct from iss-2608230943533581, which asks for the coordination SOTA sweep.
- iss-2609240307549105itd-4 AC5 says `capture list --open` lists every open issue with id, slug, severity and a one-line summary. The human render prints id, status, severity and slug and no summary (internal/surface/cli/cli.go, the list render's Fprintf); only `--json` carries the body. spc-6's AC5 pin, TestCaptureListOpenRendersIssueFields, asserts the --json shape alone, so the shipped criterion is covered on one of its two surfaces. Found during the fidelity audit of itd-4 (receipt rcp-2662745d5344), criterion ac-5.
- iss-2609240311058767The store-before-commit redactor rewrites a hyphenated vocabulary word when its first token equals the local account name. Observed on `abcd intent audit ingest` for itd-4 (receipt rcp-2662745d5344): the verdict's ac-4 rationale named the historical sync verb of the plugin, the two-token hyphenated term the intent's own fourth acceptance criterion carries verbatim, and the ingested Audit Notes now read `[redacted-user]-sync` in two places (the criterion line and the gap-audit claim) while the criterion text forty lines above carries the term unredacted. The identity kinds in internal/adapter/scanner/redact.go (kindLocalUser, replaced by the marker at redactionReplacement) treat a hyphen as a word boundary, so a product term is redacted as a person. The committed record is machine-dependent: on an account with another name the same ingest writes the term. Found during the fidelity audit of itd-4 in the autonomous run.
- iss-2609240519413467The disembark plugin page's argument-hint advertises '<source-repo> <dest>', a form the binary rejects with 'unknown command' because packing needs the explicit pack sub-verb; the hint also omits pack and five shipped sub-verbs (coverage, graveyard, press-release, principles, review) and presents plan/probe <source-repo> as required where the CLI makes the repo optional. Found by checker a01 at fa744b41 (finding x-011).
- iss-2609240519418856The help for 'abcd docs cite confirm --receipt' (cite.go:165, mirrored in docs/reference/cli/commands.md:437) describes the receipt file as 'the format the generated checklist page emits', presenting a generated checklist page as an existing producer; no such generator exists in the tree (internal/core/cite/confirm.go names it as later). Found by checker a09 at fa744b41 (finding x-035).
- iss-2609240519422232The ingest surface chapter's prose above its generated-appendix marker enumerates ingest sub-verbs and omits 'history ingest', the one v0.10.0 crosscheck finding inside a chapter where itd-147's rule (prose above the marker states no flag and no sub-verb) applies; itd-147 ac-6 is therefore not met at fa744b41 (finding x-049).
- iss-2609240519427388commands/prepare-this-repo.md:228-231 promises that no lint-config JSON is committed, but step 5 runs ahoy install, which writes .abcd/docs-lint.json into the target repository, so an adopter commits abcd-authored content the page said would not be there. Found by the v0.10.0 brief-surface crosscheck at fa744b41 (finding x-050).
- iss-2609240519471816abcd consult's stale-usage error text tells the user the binary predates the consult command and to rebuild it with make build, although consult is host-delegated by design, so a user rebuilds for nothing. Found by the v0.10.0 brief-surface crosscheck at fa744b41 (finding x-043).
- iss-2609240646458365The machine-scoped stores are documented as keyed on the repository's root commit (`~/.abcd/<store>/<root-sha>/`), and no page says the key is the full forty-character sha. The verbs that create a store (the run store, the history store, the transcript store) key on the full sha. The worktree store has no verb yet and is laid by hand, and its lanes sit under the eight-character short form; AGENTS.md says it is keyed "the way the history, transcript and voyage stores already are", which only a reader who checks those stores reads as the full sha. Autonomous run A's run file named the run store by the short form too, so the orchestrator appended its first events by hand to `~/.abcd/runs/<short-sha>/` while `abcd implement` wrote to the full-sha directory, and the two logs were joined by moving the short directory and leaving a symlink in its place. Wanted: AGENTS.md, the brief's configuration chapter and the worktree-store draft itd-2609091014076309 say the key is the full sha, and whatever lists the stores names a short-form directory beside a full one.
- iss-2609240646522330`abcd spec close <spc-N> --remainder <slug> --impact <value>` is refused by design, because a remainder close ships nothing, and the refusal says to supply the impact at the close that ships. It does not say that the judgement can be kept now: `abcd intent plan <itd-N> --impact <value>` stamps the impact on an intent that is already planned, and the later close then needs no flag. In autonomous run A a lane that knew the impact at a remainder close dropped it, which left it to be remembered by whichever session makes the final close. Wanted: both remainder refusals in internal/core/intent/lifecycle.go name `abcd intent plan <itd-N> --impact <value>` as the way to record the judgement at once.
- iss-2609240646530590On 2026-09-23 at about 16:20-16:22Z, during autonomous run A, four shells running gates in three agent sessions died at once: a lane's preflight, another lane's preflight in a separate worktree, a push whose pre-push preflight "died of signal 15", and the orchestrator's own push. The killed shells exited with status 144, and their `make` children survived, reparented to init. The pattern kill that explained the two SIGTERMs earlier that day (the guard-registry record filed with this one) was ruled out: the lanes alive at the time reported no kill beyond one agent's `kill -TERM` of its own orphaned process group, checked by its working directory first. Every killed command line carried the HOME alias the run used for gates, and every killed shell was a harness background shell, so the cause is placed provisionally in the host's shell management rather than in abcd; it was not reproduced. Recorded so that the next run seeing exit 144 on a gate has this instance: the gate's log ends with no `rc=` line, the lane loses one gate run and nothing committed, and re-running the gate was the remedy. The orchestrator then stopped three orphaned process groups by group id, and one of them was a peer's live preflight; that is the other half of the lesson: an orphaned process is not an unread one, so check its working directory, its log redirect and its owner before stopping it.
- iss-2609240646532741The store-before-commit redactor on the capture path rewrites a hyphenated prose slug that ends in a device word as `[redacted-hostname]`: the net_device_hostname rule matches any hyphenated token ending in a word such as laptop, macbook or nas, although the author named a page, not a machine. Observed on 2026-09-23 in iss-2609230851376499: its reproduction step names the memory page slug it ingested, and the stored record reads "slug [redacted-hostname]", so the reproduction cannot be followed from the record's own text. #663 fixed the same false positive on the memory lint's read side by judging page back-links by the page-name rule; the capture path applies the free-text rule to every token and has no such distinction. Wanted: the capture path spares a token the author set in code quotes, or the rule asks for a shape only a host name takes; either change carries a fixture with a slug of that shape.
- iss-2609240646533487RS005 judges every `Delivers: itd-N` trailer in the range, so once a commit carrying the trailer is on a branch, a later `git revert` of that commit cannot withdraw the declaration: the revert takes the intent back out of `shipped/`, the trailer stays in the range, and `lint-issues` refuses the branch. In autonomous run A the load-check lane (itd-2609231434459890) shipped its intent, review found that shipping it over-claimed, and the fix round reverted the ship commit and closed the spec with a remainder instead, which RS005 refused. The branch had not been pushed, so the orchestrator rebuilt it from the commits before the ship plus cherry-picks, with no ship-and-revert pair in the history; a pushed branch under an open pull request has no such exit short of a new branch and a new pull request. Wanted: RS005 treats a delivery whose commit is reverted within the same range as withdrawn (git names the reverted commit in the revert's message), or its refusal names the rebuild as the remedy.
- iss-2609240646538011The `merge=union` driver that .gitattributes gives `.abcd/work/DECISIONS.md` and `CHANGELOG.md` (the remedy iss-118 adopted) holds for a local merge only; the forge does not apply it. A pull request's mergeability and the merge queue's merge are computed on the forge, so two open pull requests that each append a DECISIONS.md entry conflict there as soon as one merges, while a local `git merge` of the same two is clean. In autonomous run A every records pull request went DIRTY whenever another records pull request merged first (#678, #679 and #681 on 2026-09-23), and each was recovered by a local merge in the lane's worktree, a push to the same branch behind a ten-to-twenty-minute pre-push preflight, and a re-armed auto-merge. Nothing tells an author that the union driver stops at the local clone. Wanted: the .gitattributes comment and the conventions that cite the driver say it holds locally only, and the remedy that needs no driver (one file per decision, as iss-2609100507439414 and iss-2608220150157511 propose) is weighed with this cost counted, since it removes the conflict on the forge as well.
- iss-2609240646538696The shell guard's bundled hazard registry has no entry for a kill by pattern: `abcd guard check --command "pkill -f 'make preflight'"` answers allow, and so does `killall make`. On 2026-09-23 a lane agent in autonomous run A stopped its own gate with `pkill -f "make preflight"` on a machine where several sessions ran gates at once. The pattern matched every session's preflight, so two peer lanes lost theirs, and the loss read as an unexplained SIGTERM for about half an hour until the agent's command was found. The run's lane brief then forbade pattern kills, which is the discipline rung. Wanted: a registry entry that blocks, or at least warns on, `pkill -f`, `pkill` and `killall` with a name or pattern, and a kill whose pid list comes from a pattern search, naming the successor: kill the pid you recorded when you started the process, or its own process group. The LOAD rule domain (iss-2609210828122412) already states the same rule for a test's own children.
- iss-2609240646542516Nothing in `abcd implement` counts the agents alive, so a run's ceiling rests on the orchestrator's arithmetic: `implement join --ceiling N` records the ceiling and the report repeats it, and the v0.10.0 changelog says as much (recorded and reported, not enforced). Autonomous run A went over its ceiling three ways. At the start two lane agents each forked themselves into three parallel workers that no count saw, until the lane brief forbade forks. At 10:28Z on 2026-09-23 the orchestrator had six agents alive against a ruled five. During the v0.10.0 cut, at 05:06Z on 2026-09-24, it launched two cross-check agents into one free slot, five alive against four, and stopped one within a minute. Each was found by the orchestrator recounting, never by a tool. Wanted, for the implement verb (itd-2609201916151817): agent_start and agent_end kept by the verb itself, a live count derived from them, and a refusal to start an agent over the ceiling. A fork cannot be seen from outside the host, so the lane brief's no-fork rule stays the discipline for that half.
- iss-2609240646544930`abcd implement report` gives each event to the window open when it happened, so a session that joins a second before the first session sets the window's mode is counted in the previous window. In autonomous run A the second session's session_open landed one second before the first session's `implement mode claim --window 2`, and the report lists that session under `single` with no lanes while its one lane, landed, sits under `claim`. Wanted: a join is attributed to the window whose window_mode line follows it within a short grace, or the report names a session whose open and whose work fall in different windows.
- iss-2609240646546286An `abcd implement claim` holds one record, and a lane is often a cluster of records. In autonomous run A the second session's first lane fixed three issues and captured and fixed a fourth under one claim; the other records were unguarded against the first session for the lane's whole life, and only the two orchestrators' agreement kept a second lane off them. The second session cannot close the gap by claiming each record either, because it is refused a second live claim. Wanted: a cluster form of the claim, several record ids in one claim or a lane key the records are declared under, refused whole when any member is held elsewhere.related itd-2609091034175565
- iss-2609240646549900`abcd implement log` has no event for going over the ceiling. Its loggable events are backoff, lane_open, lane_close, agent_start, agent_end, ceiling_wait, gate_run, review, fallback, stop, refusal, pr, capture and context. When the orchestrator of autonomous run A launched a fifth agent under a ceiling of four during the v0.10.0 cut, the only fit was `refusal` with a hand-chosen `kind=ceiling_overrun` field, and the earlier breach of 2026-09-23 (six alive against five) went in as a `refusal` with the condition in prose. `abcd implement report` counts ceiling waits and cannot count breaches, so the run's report is silent on the one ceiling figure that went wrong. Wanted: a `ceiling_overrun` event (agents alive, the ceiling, the lane, the minutes over) and a report column for it.
- iss-2609240646555891`abcd implement report` derives its figures from fields no writer is required to supply, and says nothing when they are missing. It counts a lane as landed only when its lane_close carries `outcome` merged or landed, and agent minutes only from agent_end lines, while `abcd implement log` accepts any set of fields on any event. In autonomous run A the orchestrator that took over at the first rotation (16:15Z on 2026-09-23) wrote lane_close lines with `pr` and `merge` fields and no outcome, used lane_open and lane_close for review and fix rounds, and wrote no agent_start, agent_end, gate_run or ceiling_wait line for the rest of the run. Over both days the report counts ten lanes landed for the first session and one for the second, where thirty pull requests merged, and its agent minutes stop at 16:08Z on the first day. None of this is flagged, because every line parses. Wanted: per-event required fields (an outcome on lane_close; role, model and minutes on agent_end) refused at `implement log` time, and a report line naming any event kind whose coverage stops partway through the run.
- iss-2609240646556459The release gate's brief-surface cross-check workflow (.abcd/development/release-gate/brief-surface-crosscheck.js) starts every checker at once: it maps each brief doc and each surface to an agent and awaits them all in one parallel() call, forty agents at v0.10.0, with no bound the script sets, so the concurrency is whatever the harness's pool gives it. A run under an agent ceiling cannot use it unmodified. The v0.10.0 cut, under a ceiling of four, ran the forty pinned prompts by hand four at a time and re-implemented the script's merge in a local script (the dedup key of `where` plus the first sixty characters of `claim`) to produce the merged findings the receipt records. The receipt's manifest hash pins the prompts and not the concurrency, so the gate's result does not depend on the pool. Wanted: the script takes a concurrency bound from the manifest or the invocation, and the merge is a function a hand-run can call rather than re-type.
- iss-2609240648533996What `abcd implement` (itd-2609201916151817) would have to carry to launch autonomous run A without its hand-written prompt, from having run it over 2026-09-23/24. The pilot's list (iss-2609211105021406) stands; this adds what a two-day run across three orchestrator sessions and a second session needed. (1) The run manifest as data: the batches and lanes in order with their record ids, the decisions the run may not reopen, the stop list, and the release step with the agenda line that authorises the publish approval. (2) The routing table as a verb output the orchestrator reads, not a scratch file its first lane derived by hand: 490 open captures split into 249 to build, 203 for the product thinker, 38 to judge on their merits, with 11 duplicates marked. (3) The pace and ceiling rulings as dated values that supersede one another, which the verb enforces and the log cites: the run lived under four ceilings (two implementers and one reviewer, then five, six and four agents) and three paces (two hours on and five off, three on and two off, then no pauses), each re-read by hand from a notes file by every orchestrator. (4) The roles and the model per role: implementers and fix rounds on one model, reviewers and auditors on another and one at a time, a fresh implementer per fix round, a reviewer that never implemented, and the model id each agent writes into its trailer. (5) The review receipts: which reviews a lane owes before it lands (ruthless, security at a trust boundary, a second lens on an ADR, the fidelity audit after merge) and the verdict each returned, so that "owed" is a query rather than a list in the handover. (6) The rotation chain and the handover block: the named successor sessions, the trigger at about 60% of context, and the block's fields (rulings in force, queue state, each lane's next move, hazards, owed items) written by the verb from run state; a fresh orchestrator started from a handover of about 650 words in 4% of its context. (7) A live-agent count that enforces the ceiling: agent_start and agent_end kept by the verb, a refusal to start an agent over the ceiling, and a ceiling_overrun event when one is found (iss-2609240646542516, iss-2609240646549900). (8) Lane retirement as a step: the ancestor check against the remote default branch, the worktree removal, and a branch delete that does not wait on the local default branch (`git branch -d` refuses a branch the merge queue merged until the local default branch is fast-forwarded). (9) Measurement the verb writes itself, with required fields per event, since the hand-written log lost its agent, gate and review lines at the first rotation (iss-2609240646555891). Evidence: the run's prompt, run file and lane brief were about 50 KB of prose; the first orchestrator's start-up reading cost about 15% of its context before any lane opened, and each rotation re-read the rulings from the top of the notes file.
- iss-2609250834251447A managed repository still has no local gate on a commit message carrying a live agent-session URL or a tool attribution footer, and nothing guards the text handed to the forge CLI for a pull request, an issue or a comment. abcd's own repository refuses both shapes in a commit message through its committed commit-msg hook, which runs go run ./cmd/abcd lint outbound from the source checkout; a managed repository has no source checkout, so the scaffolded form of that hook needs three product decisions first: how it finds an abcd binary (a git hook has no plugin root, so only the PATH rung survives), whether it fails closed or open when none is found, and whether abcd ahoy installs it by default or on opt-in. Split out of iss-2609061438431625 when its local half landed for this repository.
- iss-2609250846525896capture resolve, capture wontfix and intent plan move a record between status folders and leave every relative markdown link that named its old path pointing at nothing, the same gap iss-2609091732329046 records for spec close. Lane records1 of run A closed two issues that three ADRs and two draft intents linked by path, and record-lint refused seven links_resolve blockers until the links were repointed by hand. Every verb that moves a record is the one place that knows the old and the new path, so each should repoint the links through one shared primitive and report what it rewrote.
- iss-2609250850380420This repository's own committed .githooks/pre-commit name guard lacks the four hardening fixes the scaffolded template received on 2026-08-26 (f95650de): it does not pin read, echo, exit, test and [ against inherited shell functions or sweep the survivors, so a BASH_ENV defining read and echo makes it read zero entries and commit a banned name, and a shadowed declare plus exit turns a printed refusal into a commit; it appends a staged path after the gitlink skip, so a submodule path carrying a banned name is never scanned; and it echoes staged paths raw, so control bytes in a refused path can forge the refusal text. The fix landed on the template alone, and its test drives only the template, so nothing held the dogfood copy to it. The .githooks/pre-merge-commit half lacks the same pin.
- iss-2609250915305413record-lint's links_resolve rule reads a Markdown link inside an inline code span: checkLinks masks fenced blocks but runs linkRe over every other line whole, so a code span such as `Get[T](s, key)` or `Decode[T](raw)` in a record is reported as a BLOCKER 'link target does not resolve'. CommonMark gives a code span precedence over link syntax, so the text is not a link; a record author has to reword code to pass the gate.
- iss-2609250937494009The sub-verb lint (internal/core/lint/subverbs.go parseSubVerbTable) treats finding the ## Sub-verbs heading as finding the table: a surface file with the heading followed by prose and no header row passes with no finding, while the brief surfaces README promises that a file without the table is a finding whatever its verb registers. Fix: require the table's header row under the heading; test a heading-only file.
- iss-2609250947113245itd-199's three scope-condition identity markers are wrapped in backticks in its shipped record, so the claim reader treats each as documentation of the marker grammar rather than an identity: ParseClaims reports zero conditions, the verdict dispositions keyed to cond-2608312031029678, cond-2608312031028702 and cond-2608312031020321 key to nothing the record carries, and abcd intent condition refuses to re-disposition cond-2608312031028702, the worked example its own spec names
- iss-2609250955051598internal/core/site keeps a private fence toggle (sections.go isFenceLine, used by Sections, Blocks, and compose.go auditIsMet and releaseOf) that diverges from mdrecord.Mask, the tree's CommonMark reading, and returns wrong sections. isFenceLine matches any line whose trimmed text starts with three backticks and flips a boolean. So it never sees a tilde fence, closes a four-backtick fence on a three-backtick line, closes on a line that carries an info string, and cannot see an HTML comment. Probe at 70daf701 via Sections: a # line inside a ~~~ block becomes a section, and so does a # line inside a three-backtick block quoted in a four-backtick fence (both give sections Doc, a shell comment, Real). A heading parked in <!-- --> becomes the section Parked. An unclosed ~~~ fence is not refused, even though Sections refuses an unclosed backtick fence as its quietest failure. The same walk decides auditIsMet (a ~~~-fenced Acceptance rollup: MET 1 counts as a verdict, the failure iss-2609090951277880 closed for backtick fences) and releaseOf (a ~~~-fenced credit stamps a version). The fix is not a drop-in swap for mdrecord.Mask, because the site deliberately reads fences indented under list items and mdrecord recognises only the 0-3 space indent, so the indent rule needs a decision first.
- iss-2609250955207041The cold-reading exclusion floor can be walked through by a fence shape both of its halves misread the same way, so an excluded heading's section travels in the bundle and nothing refuses. redactExcluded finds headings through site.Sections, whose private fence toggle (iss-2609250955051598) flips a boolean on every line that starts with three backticks. verifyRedaction re-checks with bodyFenceMask, a second private backtick-only toggle, so the two agree on the wrong answer. Probe at 70daf701: a document holding a four-backtick fence that quotes a bare three-backtick line, then '## Private Notes' with a body line, then a ~~~ block holding a three-backtick line. redactExcluded with the heading Private Notes excluded returns nil error and the body line still in the output. Under CommonMark (mdrecord.Mask) the heading is live. The four-backtick block is one fence, and the three-backtick line inside the tilde block is literal. So the manifest asserts a refusal that did not happen, the silent-bypass class iss-2608301350533102 closed for a delimiter inside the frontmatter. The fix is not a one-line swap. Moving the verifier onto mdrecord.Mask would make it refuse this shape, but mdrecord also masks HTML comments, and comment text travels to the reader, so the floor's view of comments needs a decision.
- iss-2609250955209513internal/core/lint fenceMask (lint.go), which about a dozen rules use to skip example text (citations, persona, context currency, delivery state, cross-store, subverbs and the rules in lint.go), is a private backtick-only toggle that diverges from mdrecord.Mask. It flips on any line whose trimmed text starts with three backticks. So a tilde-fenced example is linted as live prose, which gives false findings. And a three-backtick line inside a ~~~ block flips the mask on, so the live prose after the block is masked until the next backtick line, and a real finding there is silently missed. Probe at 70daf701: in lines [~~~, three-backtick-go, ~~~, blank, LIVE PROSE LINE], fenceMask marks the live line masked, and in [~~~, example prose, ~~~] it marks the example unmasked. Moving onto mdrecord.Mask is not a mechanical swap. mdrecord also masks HTML comments, so every rule would stop reading commented text, and it recognises only the 0-3 space fence indent. Both are per-rule decisions.
- iss-2609250955219864internal/core/ahoy firstOutOfFenceH1 (marker.go), which picks where the identity marker block is inserted in a file with no frontmatter, keeps a private fence toggle that diverges from mdrecord.Mask. It flips on any line starting with three backticks or three tildes, whatever the marker, run length or info string, and it cannot see an HTML comment. So a three-backtick line quoted inside a four-backtick fence closes the fence early. Probe at 70daf701: in a README opening with a four-backtick markdown example that quotes a three-backtick sh block holding '# not the title', the function returns the offset after '# not the title'. The marker block is then written inside the fenced example, above the real '# Real Title'. That is a write into the operator's file at the wrong place. A '# ' heading parked in a comment is also taken as the H1.
- iss-2609251004336500links_resolve can miss a real broken link on a line that carries a backslash-escaped backtick: stripInlineCode (internal/core/lint/lint.go) pairs every backtick it meets, so an escaped backtick, which CommonMark reads as a literal character and never as a code-span delimiter, opens a span that the next backtick closes, and a link between them is blanked before the link pattern runs. A line reading a literal backtick, then text with a link to a missing file, then another literal backtick reports no finding, so the records gate passes a broken link. Found by the tier1 review (review-tier1 finding 4).
- iss-2609251044055902Three more private fence toggles diverge from mdrecord, the tree's CommonMark fence rule, and each gives a wrong result on a probe. site parseCLIReference (check.go) flips on any line starting with three backticks, so a flag in a tilde fence or in a four-backtick fence quoting a three-backtick line is never credited and the reference check reports drift that is not there. surface markerLines (appendix.go) flips on either a backtick or a tilde line, so a backtick line inside a tilde fence leaves the toggle on and a live appendix marker after the fence is refused as ErrMarkerInFence. memory fenceMask (coverage.go) closes a fence on a run indented four or more columns, which CommonMark reads as content, so a blockquote example inside the fence becomes a quoted span and the live quote after it is masked when the real closer reopens the toggle. Found by the TestNoSecondFenceRule detector ported onto mdrecord.
- iss-2609251045302499surface ProseShapeClaims (appendix.go) decides whether a sub-verb path is written as an invocation through codeRegions, which pairs backtick runs and so covers a backtick fence but never a tilde fence. A sub-verb path inside a tilde-fenced example, written without an abcd prefix, is not a claim, so a stale sub-verb there passes the brief surface drift check silently. Probe: prose '~~~ / capture list / ~~~' against a tree registering 'abcd capture list' yields no claim. Found in the fence sweep beside TestNoSecondFenceRule, which does not flag it because codeRegions keeps no per-line state.
- iss-2609251052591014readingitem.ResolveOccasion takes an issues root and, for an itd-N occasion, recovers the repository root by suffix-stripping .abcd/work/issues off it, while its one caller (intent/condition.go) joins that suffix on only for it to be stripped; the lookup then builds a full recordid.NewResolver over every record family (intents, specs, issues, ADRs) to find one intent, so an unreadable spec store refuses an intent occasion. The leaf should take the repository root and look up the intent store alone.
- iss-2609251052592668refuseSymlinkedDir is defined twice with identical bodies, in internal/core/capture/reading.go and internal/core/readingitem/readingitem.go, since the reading-item locator moved into the readingitem leaf; two copies of the symlink guard are how two walks come to disagree about what the ledger contains. One primitive, in the leaf, with capture's call sites routed through it.
- iss-2609251053001508The issue ledger's repo-relative root .abcd/work/issues is spelled as a string literal in seven packages (capture.LedgerRelPath, lint issuesDirOf, changelog issuesLedgerDir, readingitem ledgerRelDir, lifeboat nativeIssuesDir, intent issuesRelDir, recordid familyRoots), so a move of the ledger is seven edits and a missed one is a reader looking at an empty tree. One exported constant in the stdlib-only recordid leaf, referenced by the rest.
- iss-2609251053005833appendToAuditNotes leaves two blank lines under the Audit Notes heading whenever the section already holds a block: it writes one blank after the heading and then copies the section back with its own leading blank line, trimming only the trailing ones. So the second write into a section (a condition block after the OWED stub, on every shipped record) opens it with a double blank line.
- iss-2609251125591539git revert writes no Assisted-by trailer, and the attribution commit gate (now also on the merge queue and on push to main, iss-280) refuses the message, so a plain revert can only be satisfied by rewriting history. Carried from the duplicate iss-2609100513521322's third acceptance: the trailer should be written when the message is written (a commit template or a prepare-commit-msg hook), not demanded after.
- iss-2609251125599536auto-release's heal path rebuilds a hand-pushed tag whose verify failed on every later push to main. With the tag now made after verify on the auto-release path (iss-2608231226347380), a tag without a Release can still arise from a hand-pushed tag whose release.yml verify refused. detect cannot tell that from a transient publish failure (both are tag-present, Release-missing), so it sets need_release and rebuilds the same tagged commit, which fails again, on each push. Carried from the duplicate iss-2609100513521322's second acceptance: detect should refuse loudly and name the re-cut when the tag's last verify concluded in failure, or bound the retry.
- iss-2609251144159533The guard never follows a command substitution written inside double quotes: echo "$(gh repo delete owner/repo)" and x="$(gh repo delete owner/repo)" both answer allow, because the double-quote branch of the tokenizer consumes the whole string as one literal word, while the unquoted and backtick forms are followed into command position. Double-quoting a substitution is the idiomatic shell spelling, so this is the common form, not an evasion. The check verb's help text listed it garbled, as 'a hazard inside a top-level command substitution' with a parenthesis saying both forms ARE followed. Wanted: a substitution inside double quotes is read as its own command, as the unquoted form is.
- iss-2609251151293535The source vocabulary has no member for a finding an autonomous bug-hunt loop files, and a downstream loop wrote source autonomous-hunt, which the reader refuses and skips. Decomposed out of iss-2609120452071388 when its code halves were fixed, because this half is a closed-vocabulary ruling for the product thinker, not an implementer's fix: either such a loop uses an existing member (agent-finding is the nearest) or autonomous-hunt joins issueschema.Sources, with record-lint and the help text following from the one list. Until it is ruled, a record carrying it is skipped with the schema layer named on the board.
- iss-2609251208394294capture promote panics with a nil pointer dereference when a promotion given no --grounds fails its ledger stamp after minting the draft: the orphan-draft remedy in Promote calls g.String() on the optional grounds, which is nil once grounds became optional (iss-2609091009111294), so the failure path that exists to name the orphan and its repair crashes instead and the orphan draft is left unreported. Confirmed with a stamp-failure test while fixing the remedy's delimiter.
- iss-2609251235119402abcd intent audit reads the issue ledger (its issue-drift form checks the promote join) without naming which checkout's ledger and branch it read. Decomposed out of iss-2609202053570475, which made every capture verb and the record dispatcher name the ledger they addressed: the audit's output is the intent-auditor verdict envelope, owned by the intent surface, so adding the member there is that surface's change. The helpers to reuse are ledgerIdentityOf and renderLedger in internal/surface/cli.
- iss-2609251238184553The launch preview's retention plan reads a shallow checkout's tag listing as the whole release set: in a shallow clone the listing succeeds but holds only the tags that were fetched, so the plan can preview nothing to prune (or keep the wrong release) for a repository whose tags were never all seen. The listing-error half was fixed under iss-194 (computeRetentionForReport in internal/core/launch/dryrun.go); a SUCCESSFUL but incomplete listing is still indistinguishable from a complete one. Remedy: refuse the plan with its reason when git reports the checkout is shallow.
- iss-2609251324543906The site chapter of the brief (04-surfaces/22-site.md, The gates) says the check's own help text names the same seven gates, kept beside the code that runs them; the check's help carries only its sentence and its --out flag and names no gate, so the chapter claims a surface that does not exist. The seven names do live in one place in the code (site.CheckNames), and the check's report prints each one as it runs it.
- iss-2609251324599468The stubs itd-2609212130136102 leaves for one release are to be removed in the release after it: ahoy dry-run, ahoy identity-check, version, docs lint and site check (deprecated commands), and the bare answers of identity and ahoy remote (whose sub-verbs stay). The spec named a remainder spec minted at close for this, but a remainder close keeps the intent planned while the run closed it shipped, so the removal is held here instead; removing them narrows the surface again and needs the release to declare it.
- iss-2609251355497247The lifeboat half of iss-2609020539188868 is still open after the memory renderers were fixed: synthesis_review renders a finding id through termsafe.Sanitize alone, never CleanProse, so it can still carry an HTML comment opener or link syntax, and wraps a severity in its own bracket; the press-release subhead wraps a cleaned value in its own emphasis; synthesis_principles writes a cleaned principle as a bare paragraph with no leading-marker escape. The fix is the one applied to memory: every untrusted field on a markdown line through CleanProse, and no renderer adding delimiters around a cleaned value (termsafe.CodeSpan where a code span is wanted).
- iss-2609251357387577The DOGFOODING domain in .abcd/rules.json recalls on a fixed keyword list that has drifted from the verb tree: AGENTS.md says it injects the go-run rule on a prompt naming abcd or any of its top-level verbs (the Available Commands list), but decide, implement, inbox, mode, peers, report and statusline are missing from its recall, so a prompt naming one of them never receives the rule that keeps a session off the stale plugin-root binary. Nothing holds the list to the tree, which is why it drifted.
- iss-2609251358062952The CI job id record-lint in .github/workflows/ci.yml runs scripts/check-reviews-cases.sh and scripts/check-reviews.sh (the reviews-charter gate), while the real record-lint is a step of the check job, so a required status check is named for a gate it does not run. Renaming the job alone breaks the merge gate, because the main-protection ruleset (mirrored in .abcd/work/rulesets/main-protection.json) requires the context record-lint: the rename and the live ruleset edit must land together, which needs the forge ruleset changed by someone holding that permission. Carried over from iss-304 (d-12) when its other two halves were closed.
- iss-2609251451432601intent audit ingest: the first ingest, and any replacement, deletes trailing link-reference definitions under Audit Notes when the owed stub sits above them (the itd-114 shape appendToAuditNotes parks a stub above, per iss-2608210737265820). Same root cause as the unbounded review-block extent; same fix (a bounded extent). No record in the tree has a stub followed by refs today.
- iss-2609251451434656intent audit ingest: reviewBlockRange treats any text under an INGESTED review block, up to the next marker, heading or end of file, as part of the block, so a re-ingest of an IDENTICAL payload on a record with hand-written prose under the block reports replaced:true and deletes that prose, where the documented behaviour is a noop. No record in the tree has the shape today. Fix: bound the block's extent with a closing marker, keeping the current rule as the fallback for blocks written without one.
- iss-2609251455354719The cold-reading detection position's declared window is now 1,010,000 estimated tokens (widening 1,000,000) after the recalibration at 1a19fe55, which puts the assembled detection input past the million-token reader window the preset entries' own comment names as the bound. Each merged corpus lane grows it further, so the next recalibration will push widening past a million too. The documented alternative remedy is narrowing an entry's kinds (the comment measures widening without test at about 530,000), which changes a reading instrument and needs a ruling. Until then a reading at detection cannot be handed to a million-token reader whole.
- iss-2609251503459090The reading exclusion floor admits a fence an HTML block swallows, and the excluded section travels. A fence opener written directly under a line that opens a CommonMark HTML block (types 6 and 7, e.g. `<div>` or `<span>`, and the `<!`, `<?` and `</` starts) is raw HTML to a renderer, whose block runs to the first blank line, so a heading after that blank line is live; every mdrecord reading sees a fence and masks it, so the redactor (site.Sections) and the verifier (floorFences) agree it is an example and redactExcluded returns nil with the private section in the bundle. Probe: `<div>` then a backtick fence holding a blank line and '## Private Notes'; the `<span>` plus tilde form regressed on fix/one-fence-rule (the old toggle never saw tildes). The lane's ruling is that any ambiguity fails closed: a fence opener inside an HTML block's run of non-blank lines is refused, naming the line.
- iss-2609251507443137The reading exclusion floor admits two line shapes every renderer reads and its line split does not, and the excluded section travels with a nil error. A byte-order mark before an ATX heading on line 0: floorATXRe is matched against the raw line with no frontmatter.TrimBOM, so the BOM hides the heading from the verifier while a renderer drops it. And a lone carriage return: CommonMark treats a CR not followed by LF as a line ending, but the floor splits only on newline, so a CR-only document (or a lone CR inside a CRLF one) is one line to the floor and many to a renderer. Both leak at base and on fix/one-fence-rule. Each is a one-line refusal.
- iss-2609251509209801The reading exclusion floor admits an excluded heading nested in a list item or a blockquote, and the section travels with a nil error: '- ## Audit Notes', '> ## Audit Notes', and a heading at a list item's content indent of four columns all render as headings, while floorATXRe wants the line's first non-blank character to be '#' within three spaces and the site section walk reads column 0 alone. project.go discloses the residue in a code comment ('Two shapes this floor does NOT see'), and a disclosure in a comment is not a recorded deferral. No committed markdown file carries such a heading naming an excluded title, so the floor can refuse the shape outright.
- iss-2609251510124162TestNoSecondFenceRule (internal/core/mdrecord/fence_canonical_test.go) flags a file only when it writes a fence delimiter AND matches one of a few tracker spellings (inFence, inCode, openChar, fenceOpen, a boolean flipped in place as x = !x), so two common styles of a private fence toggle escape it: a regexp with run tracking kept in a variable named open, and a three-backtick flip written as an if/else rather than x = !x (mutants C and D on a scratch copy; A and B were caught). Only ten non-test Go files outside mdrecord write a delimiter at all, so the detector can be inverted to delimiter-only with a reasoned allowlist, and every new writer then needs a stated reason.
- iss-2609251514129841The site renderer is backtick-only while the block walk it renders is not: site/markdown.go RenderBlock opens a fence only on a first line starting with three backticks (and r.fence assumes exactly that run), so a tilde fence, which Blocks now reads as one block by mdrecord's rule, renders as a paragraph with its delimiters and code inlined into prose, silently; a four-backtick fence renders with its extra backtick in the language class. The site's own doctrine is that its quietest failure is the one to refuse. No tilde fence sits in docs/ or .abcd/development today, so no page is wrong yet.
- iss-2609251517210637lint's recordBodyStart (internal/core/lint/schema.go) skips only leading lines that START with `<!--`, so the second line of a multi-line leading comment is taken for the start of the body and recordTitle reads comment text as the record's title (a record opening with a two-line attribution comment is titled 'attribution line'). It keeps a private reading of HTML comments beside mdrecord's, the tree's one comment reader. One committed file has the shape today (internal/core/ahoy/defaults/claude-md-marker-block.md, not a record).
- iss-2609251518418878Four leading-comment locators each keep a private walk over HTML comments instead of mdrecord's reading: site/sections.go frontmatterLead, lint/lint.go frontmatterOpen, glossary/index.go frontmatterOpen and reading's displacedFrontmatter. The first three read any line starting with a comment opener and ending with a closer as one whole comment, so a line holding a comment, then prose, then a closer is skipped as a comment and a frontmatter block below it is found where every renderer sees prose first. reading's walk is fail-closed (it refuses a displaced block) but is still a fourth spelling of the same locator.
- iss-2609251522453961ahoy's marker install appends the canonical block inside an unclosed fence or comment. composeMarkerInsertion (internal/core/ahoy/marker.go) places the block after frontmatter, else after the first live H1, else at end of file; firstOutOfFenceH1 reads liveness through mdrecord.Mask, so a fence or HTML comment nothing closes masks every line below it, no H1 is found, and the block is appended at end of file INSIDE the open span, where no reader sees it as markdown. classifyMarker's byte regex then finds the block and reports it current, so nothing ever says so. mdrecord.Unclosed is available and unconsulted.
- iss-2609251522588539AGENTS.md's Foreign-uid roots paragraph says a refused foreign-owned root sends the session to its own working directory on the bundled defaults, but rules.Resolve returns Resolution{Root: cwd} on that refusal (internal/core/rules/root.go:138), so when the working directory is the refused root, or lies inside it and carries its own .abcd/, that directory's .abcd/rules.json, .abcd/guard.json and .abcd/config/oracle-routing.json are read. The ownership gate bounds the upward walk, not the read at cwd. layered.RootsFor's comment states this correctly. The posture fix (an empty root with PerRepo false, so no per-repo .abcd is read in any geometry) is on the unmerged branch feat/ruled-security-forks (da3efea6), not on main.
- iss-2609251535090117The generic-account position check in the identity matchers is quadratic in line length. standsAsAccountName (internal/adapter/scanner/identity.go) lower-cases the whole line prefix before every match to test a home-literal suffix and each account-root prefix, and underAbsoluteRoot walks back to the path token's start for every non-boundary home match. A line dense in a generic login (dev, git, test, user, build, app, node: all on genericAccountNames) under a login on that list therefore costs the square of its length: the review measured 80, 160 and 320 KB at 0.92, 3.34 and 13.6 s against 31, 60 and 124 ms for a non-generic control, so one 4 MB transcript line holding a tool result costs about half an hour in the launch gate or the store-before-commit redactor. The identity matchers sat outside every count-based cost guard (iss-2609240203462704), which is why no test saw it.
- iss-2609251535277823Six per-match helpers in the scanner read the line around every match, so a line dense in matches costs the square of its length, independently of the generic-account check. (1) inAnySpan and atURLPathRoot scan the whole URL span list for every identity match, and atURLPathRoot searches each span from its start for the path root; (2) the footer SkipAt runs its line-prefix regex over the whole line before every footer match, and footerLinkTarget searches the rest of the line for the link; (3) isDottedNamespaceComponent walks and re-splits the whole dotted run for every login occurrence in it; (4) colonRunGroups walks and splits the whole hex/colon run for every address candidate in it. The cost meter's linearity guard (TestScanLineWorkIsLinear) measures 8-16x per quadrupling on each shape where linear work is 4x; wall-clock probes agree (a dotted run of a non-generic login, 8000 units: 35, 127, 479 ms). Pre-existing: none of these came in with the scanner cluster lane, and no guard reached them.
- iss-2609251537550065fsutil.ReadDeclaration judges a home-scoped declaration's owner and permissions on an Lstat, then reads it through ReadGuarded's later open by path with no os.SameFile check between the two, so a co-tenant with write on the declaration's directory can rename-swap a different file in after the vetting and have it read as the caller's word; ReadGuardedInRoot already closes the same lstat-to-open window with os.SameFile. Callers: the rules user layer (~/.abcd/rules.json), trusted-roots, local-transcript-roots, path-entry, cache attestation and the implement limits file.
- iss-2609251543293588The generic-account floor misses the JSON-serialised Windows home root. accountRootPrefixes (internal/adapter/scanner/identity.go) carries the single-backslash spelling (\users\) but not the doubled one every JSON encoder writes, so C:\\Users\\carol\\Desktop in a transcript line raises no finding at all while C:\Users\carol\Desktop hard-fails; the home-literal clause of standsAsAccountName compares the configured home verbatim and misses its doubled spelling the same way. Before the generic floor the bare word was flagged, so the floor narrowed a hard_fail rule in the redactor's own input shape: a caller whose login is on the generic list leaks the home path of every Windows path a JSON transcript quotes through capture and history.
- iss-2609251544556874genericHomeRe is the last case-sensitive identity matcher, and it guards the one identity kind whose value is another person's filesystem path. internal/adapter/scanner/identity.go compiles it as (?:/Users/[A-Za-z0-9._-]+|/home/[A-Za-z0-9._-]+) with no (?i), and it is the sole detector for home_path_other. macOS and Windows filesystems fold case, so /USERS/NAME/notes.md and /Home/NAME/notes.md name the file the canonical spelling names, and a path written either way passes every redactor that routes through ScanText and the privacy lint. Every sibling matcher on this boundary already folds (email, github, homeSelf, localBare, githubRemoteRe, noreplyRe). The finding was first recorded on a parked branch whose record never reached main (0fac3697 carries its fix); it is captured afresh here so the fix can land with its record.
- iss-2609251547568307The generic-account floor reports a generic login only after a home root, a tilde or in an address's local part, so the account positions a shell session or a config dump writes pass unreported: a home root with no leading slash (an archive listing's Users/LOGIN/Desktop, a relative home/LOGIN/.config), a key/value position (USER=LOGIN, LOGNAME=LOGIN, username: LOGIN, login: LOGIN, a JSON "user": "LOGIN"), and the argument of an account command (su - LOGIN, chown LOGIN:staff, chown -R LOGIN). Each is where a login stands, not a word in prose, and a caller whose login is on the generic list leaks it from every one of them through capture and history. Found by the scanner-cluster review (floor gaps, item 3).
- iss-2609251549447970A login in a URL's userinfo is never reported as local_username, for any login. localSuppressionSpans (internal/adapter/scanner/identity.go) suppresses the username matcher inside every URL span, so https://LOGIN@host/ and https://LOGIN:PASSWORD@host/ pass the scanner with the caller's login intact; the userinfo is the one part of a URL that names an account rather than a resource, and a clone URL or a proxy setting quoted in a transcript carries it. Pre-existing: the suppression predates the scanner-cluster lane, whose review found it (item 6).
- iss-2609251551533470Under HOME=/root the home-literal clause of standsAsAccountName (internal/adapter/scanner/identity.go) hard-fails every absolute path whose last segment is named root: /sys/fs/cgroup/root, an overlay filesystem's .../root, macOS root's own /var/root. The clause accepts the generic login wherever it closes the home literal, so that a blob-shaped ...0/root/deck.key that home_path_self's leading anchor declines is still caught; but a /root that is a deeper segment of an absolute path is a directory named root, not the caller's home, and the rule refuses the write or the launch on it. It blocks rather than leaks, so it is a nitpick; it came in with the generic floor on this lane (review item 7).
- iss-2609251553082721Four one-line renderings of a private key leak its body past the PEM rules. The same-line pattern's separator (pemPrivateKeyPattern, internal/adapter/scanner/patterns.go) admits a blank, a comma, a quote and an escaped newline but not an escaped quote, so a JSON array serialised inside a JSON string (the elements joined by backslash-quote-comma-backslash-quote) masks the header and keeps the body verbatim on the header's line; an HTML rendering that joins the lines with `<br>` or the ` ` entity leaks the same way; and a header whose case a tool lowered is not detected at all, by the pattern or by the block consumer (pem.go pemBegin/pemEnd), so its whole body is stored. Found by the scanner-cluster review (items 4 and 5).
- iss-2609251600019863reading floor: a CRLF document whose excluded section is the LAST section is refused with 'ends line N with a lone carriage return': the redactor's output ends in a CR with no LF, and the verifier's lone-CR refusal then blames a CR the source does not carry. Fail-closed (no leak), but such a record can never be assembled. Fix: keep the tail's newline when the redactor drops the last section, or trim a trailing lone CR at EOF before the check; add the case to floor_lines_test's CRLF control.
- iss-2609251600023777site renderer: a top-level three-backtick fence indented one to three spaces still renders silently as a paragraph with inline code (site/markdown.go unrenderedFenceRe covers tildes and four or more backticks only). No page in docs/ or site-src/ has the shape today. Refuse it like the other unsupported fence forms, or render it.
- iss-2609251600029607TestNoSecondFenceRule's delimiter-only detector misses a private toggle written as a literal regexp that matches a run (for example a pattern of 0-3 spaces then a backtick or tilde run, with a length check) or as byte comparisons on the first character; its doc says a pattern 'assembled at run time' escapes, which understates a literal regexp. Extend the detector to regexp literals whose pattern can match a fence run, and to first-byte comparisons against a backtick or tilde, or narrow the doc to the truth.
- iss-2609251606543515The spec-close remedy prints the verb twice ("abcd abcd spec close"): route.go:259 prefixes an already-prefixed verb string, and the same doubling stands at cli.go:2360, cli.go:2397 and ship.go:331 (review2-tier2 note a).
- iss-2609251606553359reading ingest with --route refuses an oversized output as "names no reading position" instead of giving the size-cap message (internal/surface/cli/reading.go:246-251), so the operator is told the wrong cause (review2-tier2 note b).
- iss-2609251616248870internal/actionsexpr looseEqual compares a bool to a string by truthiness, where GitHub Actions coerces both to numbers (true == 'true' is false on GitHub), so an if: expression making that comparison would evaluate differently in the test evaluator than in the runner (actionsexpr.go:424-429; carried over unchanged from the old lint evaluator; no committed workflow makes that comparison today; review2-workflows R1).
- iss-2609251616310535The auto-release detect step's tests do not cover a failing gh run view or an in-progress verify job (read to heal); both paths are read correctly but a regression in either would pass (autoreleasedetect_test.go:169-217; review2-workflows R2).
- iss-2609251617091944The record-families page's Moved by column names verbs the binary does not have: intent reclassify, abcd build, intent plan --bundle and drain are not in go run ./cmd/abcd --help, and the bundle glossary entry claims abcd intent plan itd-A itd-B --bundle <name> as present; itd-34 (multi-intent plan) and itd-2609212103565953 (steps and the build) are both planned. The page every glossary entry points at teaches a reader commands that refuse.
- iss-2609251618079479After adr-2609212115255771 retired the phase, the milestone and the word roadmap, the brief outside the mental-model chapter still describes the phase as the live sequencing unit: 59 files under .abcd/development/brief mention it, among them 01-product/04-scope.md (bounded by the planned phases), and the glossary entries release, version, loop, plan and spec, whose prose says a phase sequences the work and a release falls out of completing one. itd-2609211913453478 rewrote only the mental-model chapter and repointed each entry's not_to_be_confused_with; no record carries the rest of the sweep.
- iss-2609251638574543The generic-account floor misses a Windows home root escaped more than once. accountRootPrefixes (internal/adapter/scanner/identity.go) lists the single and the doubled backslash spellings of \users\ and the home-literal clause of standsAsAccountName lists the home and its doubled spelling, so C:\\\\Users\\\\carol\\\\Desktop, the shape a transcript line carries when a tool result is itself JSON text (go env -json, npm config ls --json, any --json output), raises no finding for a login on the generic list while the doubled spelling hard-fails. Before the generic floor the bare word was flagged, so the floor narrowed a hard_fail rule in the redactor input: capture and history redact nothing on such a line.
- iss-2609251639024615The account-key walk gives up after eight blanks, which fails away from the finding. maxKeyGap (internal/adapter/scanner/identity.go) bounds the blanks afterAccountKey reads between a key and its value at eight, so a column-aligned config dump (USER= or username: followed by ten blanks and the login) raises no finding for a login on the generic list. Every other bound in the position checks stops reading and keeps the match; this one stops reading and drops it.
- iss-2609251639261103home_path_other and home_path_self read no Windows home spelling beyond the literal one. genericHomeRe (internal/adapter/scanner/identity.go) is POSIX-only, so C:\Users\OTHER\Desktop and its JSON-escaped spelling C:\\Users\\OTHER\\Desktop raise no home_path_other, and home_path_self matches the configured home verbatim, so the escaped spelling of the caller's own Windows home is reached only through local_username on its last segment. A Windows spelling threads through genericHomeRe, the path-segment byte class, the system-directory allowlist, the traversal walk and the lint audit rule that shares them, so it is not a contained change. <!-- abcd-lint:allow -->
- iss-2609251639263391The identity matchers do not read the JSON solidus escape. A home path written with escaped forward slashes (\/Users\/LOGIN\/Desktop, \/home\/OTHER\/) raises neither home_path_self nor home_path_other, and a login on the generic list in it raises no local_username; a named login is still caught by its bare word. Only PHP json_encode and org.json write the escape; none of the encoders that feed abcd (Go encoding/json, JSON.stringify for transcripts, Python json) does. <!-- abcd-lint:allow -->
- iss-2609251640353017The kill-by-pattern and kill-by-name blockers never fire when the pattern arrives through a command substitution: an unquoted substitution contributes no word under the vanish reading, so the operand count the min_operands constraint reads is zero and pkill or killall with its pattern substituted in is allowed. A substitution standing as its own word is one operand of unknown text for that count. Found by review-guard finding 3.
- iss-2609251640353405The shell guard fails open past maxQuotedSubstitutionDepth: a command substitution nested inside double quotes nine levels deep is left as literal text rather than read, so a blocked command at that depth is allowed, while bash runs the innermost command at any depth. Past the depth the guard must refuse, as the brace-group, here-document and bang-alias budgets do. Found by review-guard finding 2.
- iss-2609251640353993The shell guard allows every blocker when a double-quoted command substitution sits in the same word as the flag: the quoted branch of the tokenizer keeps the substitution text in the word, so a force flag glued after an empty quoted substitution, or split around one, never matches, while bash joins the empty output onto the flag and runs it. The unquoted twin and an empty single-quoted pair already block. Found by review-guard finding 1.
- iss-2609251640354925The shell guard compares git long flags exactly, but git accepts any unambiguous prefix of a long option, so the no-verify flag of commit and push, and the with-lease and if-includes force flags of push, each spelled a few letters short, run as the full flag and are allowed. Found by review-guard finding 4 (pre-existing).
- iss-2609251640452031The kill-by-pattern entries leave four spellings of a kill by name or selector uncovered: kill handed the output of pgrep in a command substitution, pgrep piped into xargs kill, pkill selecting by user with -u, and pkill selecting by terminal with -t. The first two reach the pattern through a second command the entries do not read; the last two are value flags that consume the selector, so no operand remains, and a kill by user is every session of that user. The same holds when the selector is a command substitution, which fills the value flag's slot and leaves no operand: `pkill -u $(whoami)` (every session of the caller) and `pkill -g $(cat p)` are allowed by design, and review2-guard finding 8 names both. The commit that added the entries named the gap; no record did. Found by review-guard finding 5.
- iss-2609251640462464A blocked command piped as text into a bare shell at the top level is allowed: echo or printf of the command string piped into sh, or into bash -s, runs it, but pipesIntoInterpreter is consulted only inside execute-a-string payloads, and the top-level segments carry no record of which operator joined them, so the guard cannot tell a shell reading the pipe from one running a script file without tracking pipes. Found by review-guard finding 6 (pre-existing).
- iss-2609251640464212The no-verify blockers miss the same bypass spelled as configuration: a commit or push that points core.hooksPath elsewhere for that one command, through -c, --config-env or the GIT_CONFIG environment, skips the repository hooks exactly as the no-verify flag does, and the matcher steps the -c value over unread. Found by review-guard finding 6 (pre-existing).
- iss-2609251640464735The rm-after-cd blocker knows only cd as the directory change a delete is chained after, so a recursive forced delete chained after pushd or popd is allowed, though either fails the way cd does and the delete then runs wherever the shell already was. Found by review-guard finding 6 (pre-existing).
- iss-2609251645374557The help renderer computes the name column width over both blocks, so the person's block renders at width 12 under --help and 21 under --help --agent: the people block is not byte-stable across the two forms (internal/surface/cli/helpgroups.go:266-274; review-helpgroups 2).
- iss-2609251645376019abcd help --agent refuses with cobra's bare 'unknown flag: --agent' (exit 2), while abcd --agent refuses naming the spelling that works; the help-subcommand path does not name --help --agent (review-helpgroups 3).
- iss-2609251645376219docs/reference/cli/README.md says abcd --help documents itself, but the default list now omits the agents-and-hosts verbs and nothing in the prose names --help --agent, so a person who finds abcd version in commands.md does not see it under abcd --help and is not told the list expands (review-helpgroups 1).
- iss-2609251707302419The abcd implement load sentence says it never refuses, but the verb refuses an unknown --site with exit 2 before checking anything (implement_load.go)
- iss-2609251707305810The sentence gate walks the command tree before cobra adds help and completion at Execute, so abcd --help lists two framework verbs with cobra's own text that the gate never sees and no test names as exempt: the check reads as covering every listed verb while two are silently outside it
- iss-2609251707308289Seven family plugin pages (ideate, disembark, embark, history, guard, docs, implement) carry a router sentence as the description a host lists the skill by: the parent verbs' manifest sentences describe the dispatcher (List the verbs that ...) or the bare form alone, so an agent choosing a skill from the host list learns only that verbs exist, not the family's work or its write discipline
- iss-2609251707308675The abcd changelog sentence says it never refuses, but the verb exits 2 outside a checkout or on an unreadable ledger (emitCut error in ship.go)
- iss-2609251707310199The sentence lane's claim that the release guardrail reads a version-2 surface baseline from the last tag is wrong: v0.10.0 carries a schema-1 surface.json, and versions 1 to 3 are readable; the claim sits in the doc comment of TestDecodeReadsTheVersionTwoShape
- iss-2609251707317274The stale-surface refusal names each verb whose help placement moved but not a reworded sentence: a snapshot differing from HEAD's only in a sentence yields the generic does-not-match line with nothing to act on
- iss-2609251711096816commands/capture.md's 'Where an rdi-N comes from' paragraph says the cold-reading ingest verb has not landed and that the reading-item sub-verbs have nothing to act on until it does; the ingest verb ships (abcd reading ingest, commands/reading.md), and four capture sub-verbs now act on reading items (disposition, admit, surprise, promote), so the paragraph states a future that is already the past and counts two verbs.
- iss-2609251713073532abcd changelog and abcd launch ship hand the working directory to the cut as the repository root: run from a subdirectory of a checkout, changelog reports an empty cut and a missing surface baseline with exit 0, a plausible wrong answer; outside a checkout both refuse with git's bare 'exit status 128' instead of naming the missing checkout
- iss-2609251728586400Two scanner test nits from review 3: meter_test.go:196 pins the separator-run cap with a true account position (C:\Users followed by 65 backslashes), which passes with or without the cap, so the over-report direction for a rootless run is not itself pinned; and the meter fixtures scale with maxSeparatorRun, so inflating the constant to probe the no-cap case allocates gigabyte strings (remove the loop bound instead).
- iss-2609251734057081A mutually exclusive flag group refuses with exit 1, not the usage-error exit 2: cobra's group validation runs after PreRunE and returns a plain error that markUsageErrorsExitTwo never tags, so abcd ahoy --dry-run --identity, abcd update --check --yes and abcd site build --preview --version exit 1, which a gate reads as a finding rather than a mis-spelt invocation
- iss-2609251734061160Two passages still describe spellings the verb consolidation retired: the surface glossary's example says bare abcd identity reports each surface's verdict and writes nothing, though bare identity now refuses and the report is abcd lint identity; and a cli.go comment calls abcd intent new the deprecated alias, though it is removed
- iss-2609251734069878The CLI reference gives abcd ahoy remote and abcd identity a Usage line of their bare spelling, which only refuses: the reference names the new forms only everywhere else, so a reader copying the Usage line runs a refusal rather than the sub-verb form or the successor the bare form names
- iss-2609251750202525abcd site and abcd site build hand the working directory to site.Describe/site.Build, so run from a subdirectory they report '.abcd/site.json (absent) ... nothing to build' with exit 0: a plausible wrong answer rather than a refusal, the same shape iss-2609251713073532 fixed for the release cut (internal/surface/cli/site.go:31-35, 52-58; review2-sentences).
- iss-2609251751298408commands/launch.md describes the release job's semantic receipt gate at a position it no longer holds. Four places — the Ship intro ('the tag is already created by then'), the release-day failure list ('The tag exists by then'), Semantic receipts ('release.yml derives the content commit as <merge>^2^') and 'Prove the gate before you merge' ('receipt_gate runs inside the release job, which is after the tag is created') — predate adr-52 and iss-355: release.yml runs the gate in its verify job, which the tag job needs, so on the auto-release path a refusal leaves no tag and the version free, and the content commit is derived from the receipts directory of the released tree (record-lint --derive-content-sha), not from merge ancestry. Only a hand-pushed tag exists before the gate. An operator reading the page believes a refusal consumes the version and reaches for a tag deletion the machinery no longer needs.
- iss-2609251755278758applyHookPlaneFailOpen resets FlagErrorFunc and Args on the hook plane but not the PreRunE that markUsageErrorsExitTwo now installs on every command, so a flag group declared on guard hook or hook * in future would refuse at exit 2, the host's BLOCK, bypassing iss-269's fail-open (internal/surface/cli/cli.go:138; hypothetical today: no hook command declares a group; review2-consolidate nit).
- iss-2609251755386183The release job's semantic receipt gate admits a release that carries no receipts of its own, whenever an earlier release's receipts are in the tree. record-lint --derive-content-sha (lint.DeriveReleaseContentSha) arms the gate against the NEAREST commit on the released lineage that a .abcd/work/reviews/<sha>/ directory names, and never checks that the commit belongs to this release. A roll to a new version with no new receipts derives the previous release's content commit, whose PROMOTE receipts are valid, so receipt_gate passes and the release publishes unreviewed. Reproduced on a scratch clone of this repository at the v0.10.0 tip: a commit rolling CHANGELOG to 0.11.0 derived 64ea8f62 (the v0.10.0 cut) and the armed gate printed no finding. Every release after the first that ever recorded receipts is exposed; the itd-93 scaffolded gate and abcd launch receipts inherit it through the same reader. Fix direction: bind the derived commit to the release — its newest dated CHANGELOG version must equal the released tree's, else fail closed naming both.
- iss-2609251812216267The read-block coverage matrix claims caughtLeak for three comparative rows — dispositions, admissions and surprises never reach the comparative reading, falsifier 'delete the derived row and add an include row for it' — but the mutation leaks nothing on the eval corpus: the comparative preset selects only the discipline kind and the candidate set, so an include row for the family at comparative emits no item. Watched on a scratch copy for surprises (an include row plus the derived row removed: TestReadBlockBaselineIsClean stays green). The removed derived row IS caught, by TestManifestNamesEveryExcludedFamily, so the rows' Caught should be caughtFamily with no class, or the corpus needs a comparative-reachable plant. Found while giving the reframe family its comparative coverage row (spc-2609020626048705), which is declared caughtFamily for this reason.
- iss-2609251823551349capture disposition writes disposition_grounds and exit_condition redacted but never through termsafe.EncodeHiddenRunes (internal/core/capture/reading.go:471-479), so a bidi or zero-width rune in --exit-condition lands in the committed record verbatim, the class iss-2608301206073609 closed for other free-text writes (review-capture 2).
- iss-2609251823555125capture defer past the SAME anchor appends a second ## Deferral section (internal/core/capture/deferral.go:114), where the doc says one per cycle (review-capture 3).
- iss-2609251823559111The capture ledger's os.Root escape is classified by matching the string 'path escapes from parent' (internal/core/capture/ledgerroot.go:59-64), and nothing pins the match: ledgerroot_test.go:62 and :97 assert only err != nil, so a Go release that rewords the message would silently degrade ErrPathUnsafe to a generic error (review-capture 1). Assert errors.Is(err, ErrPathUnsafe) in both race tests.
- iss-2609251823560369The capture verbs' --json and stderr print the checkout path through RedactHome only, so a checkout outside HOME is printed in full (internal/surface/cli/cli.go renderLedger), an absolute local path in output that may be pasted elsewhere; renderLedger also splices the ledger member by byte surgery on the trailing brace (review-capture 4).
- iss-2609251824244354The shell guard reads a command substitution's output as an unknown word, but not a parameter expansion's. A dash glued to a variable (git push --$X origin main, rm -$F after a cd) is read as the literal text --$X, which names no flag, so every blocker allows it while its --$(echo x) twin blocks; and ${GIT:-git} standing in command position is compared as text. bash builds the hazard from either. Found while closing review2-guard (its finding 1 names --$X as pre-existing). The record named a second half, a substitution standing in command position, which fix round 3 of lane guard resolved (a name a substitution prints is every program its known tail allows); this record is the parameter-expansion half alone. Fix round 4 made a ${…} that carries a command substitution (${X:-$(…)}, --${X:-$(…)}) unknown from its ${ on (iss-2609252120211621). What remains is exactly a parameter expansion with no substitution in it: $X, ${X}, ${X:-word} and the other operators with literal words, and $@ / $*, standing as the command's program name, as a flag or glued to one, as an operand an entry constrains, or inside a payload the guard reads.
- iss-2609251827104081The launch gate suite's hook-compliance row fails open on a hooks config that does not parse: hookComplianceGate (internal/core/launch/gates.go) skips an unparseable hooks file with a comment claiming the smoke refuses it, and the smoke does not, because hookCommandEntries (installsurface.go) also drops an unparseable hooks document silently and the light tier checks existence only. A plugin shipping a hooks.json the host cannot parse registers no hooks on any install, while the row reads 'ran, 0 concern(s)'. itd-65 AC5 promises the concern is surfaced. Remedy: a hooks config that is present and cannot be read or parsed is a finding of the row, and the resolver refuses it as it refuses an unparseable plugin manifest.
- iss-2609251827286563The launch gate suite's change-narration gate (hard-fail tier) refuses present-state prose: its constructs in internal/core/launch/gates.go flag 'The token used to authenticate the request is read from the environment.' (a participle 'used to'), 'Files that are no longer present in the tree are skipped.' (a state, not a change of abcd), 'The output is renamed to match the tag.' (a present operation), and 'Now, as previously noted, the report lists every gate.' (previously and now with no change verb, which itd-65 AC10 says must not hard-fail; the AC10 test covers the two words only in separate sentences). The finding text never names the docs-lint escape. A doc sentence that narrates nothing refuses the cut, and on a hand-pushed tag the release workflow's archive verify refuses after the tag exists. Remedy: 'used to' only as the past-habit construction, 'no longer' and 'renamed' only beside a change subject naming abcd or its behaviour, a change verb required beside previously/now, and the escape named in the finding.
- iss-2609251827290265The launch dry-run's plain render stages only two gate rows loudly: internal/surface/cli/cli.go prints the citation-baseline and semantic-receipts rows and no other, so a documentation-auditor row that is not_armed (no .abcd/docs-lint.json) is visible only in --json and the pre-flight report file. iss-2608231226342272 is the precedent that a row only --json shows is invisible. Remedy: the plain render prints every gate row whose status is not 'ran'.
- iss-2609251827294854RenderPayload hardcodes the dirty-tree gate to DirtySkip for every caller (internal/core/launch/render.go), with a comment asserting the caller ran the gate earlier, which RenderPayload cannot know: the two live callers (the ship's post-write render, CI's launch archive --verify) are covered today, but any new direct caller (itd-72's publish step) inherits no dirty gate. The render-path precheck also hands the documentation audit nil, so its doc-auditor row claims 'no .abcd/docs-lint.json' for a repository that has one. Remedy: a DirtyPolicy on PayloadRenderRequest whose zero value refuses a dirty tree, each live caller passing its policy explicitly, and a render-path doc-auditor row that says it was not measured rather than that the config is absent.
- iss-2609251827296447The launch gate suite's proseLines (internal/core/launch/gates.go) reads a Markdown document whose first line is '---' as opening YAML frontmatter and drops every line until a second '---'; a document that opens with a horizontal rule and carries no second rule is dropped whole from both the marker-block and the change-narration gates, silently, in a fail-closed gate. Remedy: frontmatter is skipped only when it closes; an unclosed opening rule is read as prose.
- iss-2609251842111403No test opens the admission ordering gate through the comparative channel's real writer: the rehearsal hand-plants the marker (evals/coldreading_rehearsal_test.go:1397), and the comparative eval ingests but never dispositions, so a writer that stops populating candidate_run would leave every such run un-answerable with every gate green (review-admission 3).
- iss-2609251842111593The admission ordering gate reads 'committed' as a run.json decoding to position comparative with a candidate_run, with no run_id/directory, manifest, item or git check (internal/core/capture/itemfate.go:145-186), so an untracked, id-less marker opens the gate; this matches the spec's Approach but not its line that no mutable file anywhere records the outcome (review-admission 2).
- iss-2609251842112266The widening-run summary's stand-down is bypassed for an admitted item: internal/core/lint/readingoutstanding.go:421-425 takes the admissions.admits case before the unsafe/contested/cyclic check, so a run whose only acceptance is unreadable or contested still reports 'admitted 1, outstanding []', contradicting the type's own doc comment (lines 131-135; review-admission 1).
- iss-2609251902438821The deep installability smoke refuses legal frontmatter: pageFields (internal/core/launch/deepsmoke.go) drops indented continuation lines after a key with no block header, so a description written as a plain multi-line scalar reads as absent and a skill is refused for lacking one; a quoted key ("name": or 'name':) or a non-ASCII key is refused as not a YAML mapping entry; and a block closed by the YAML document end ... is refused as never closed. The cut wires the deep tier unconditionally (internal/surface/cli/ship.go), so the first page written in any of these shapes makes launch ship refuse under ErrPayloadPageUnloadable with no opt-out. Latent: every page shipped today passes.
- iss-2609251902439148The cli package's TestMain (internal/surface/cli/main_test.go) re-enters the abcd binary whenever ABCD_CLI_TEST_AS_BINARY=1 is in the environment, whatever the arguments, so an ambient marker makes go test of the package run zero tests, print the bare status board and pass. Test-only; the shipped binary carries no such symbol.
- iss-2609251902439938A checkout without the previous release's tag reads as a first launch: launchParityInput (internal/surface/cli/launch_deep.go) leaves the baseline empty when no release tag is listed, and PayloadParity (internal/core/launch/parity.go) reports every payload path as added with exit 0. A git clone --no-tags of a tree whose CHANGELOG.md dates v0.10.0 reports parity source none and 130 added; a clone --depth 1 reports the retention refusal for a shallow checkout beside the same first-launch diff. The configured-baseline hard error (itd-66 AC7) is defeated in the commoner shape: a fork, a mirror, or tags never pushed.
- iss-2609251902444497launch --fetch-baseline silently unsets the proxy and CA environment variables for the whole process: update.NewReleaseAssets reaches newUpdater, whose scrubEnv calls os.Unsetenv on HTTPS_PROXY, SSL_CERT_FILE and their kin, and the loud fetcher prints fetches only, while abcd update records the ignored names in its receipt. An operator behind a mandatory proxy sees a dial timeout with no hint, and a preview verb mutates its own process environment.
- iss-2609251902445148The deep installability tier's cost is not stated on the launch command page: each preview that asks for it and every staging cut makes a shared clone of the baseline tag and checks it out (about three seconds and a tree the size of the checkout), with no opt-out on the cut. Also smokeDeepOverBundle (internal/core/launch/deepsmoke.go) creates the materialisation root after the copy loop rather than before it.
- iss-2609251939460232The release gate's content-commit derivation applies the version binding to the NEAREST receipts directory only. A co-batched pull request that carries its own commit-keyed receipts directory either ties with the release roll's directory or sits nearer and carries the previous version; both refuse although the roll's correct receipts are on the lineage, and the cut cannot be rerun without a fresh reviewed commit. Candidates should be filtered by version first and the nearest taken from those.
- iss-2609251939461459The release gate's content-commit derivation binds the receipts to the released version with a string equality that admits two empty versions: a released tree with no dated CHANGELOG heading, or with no CHANGELOG.md at all, derives the nearest receipts directory, and the previous release's PROMOTE receipts admit it. releaseVersionAt returns an empty version with no error for a missing file, against its own comment. Reachable on the hand-pushed-tag path, where the verify job's receipts step runs and nothing cross-checks the tag against the CHANGELOG.
- iss-2609251939466588The receipt gate's sha pattern admits 7 to 64 hex digits, so an abbreviated receipts directory for the same commit ties with its full-sha twin and the derivation refuses. The reviews charter, the release protocol and the runbook all say the directory is named by the full sha; the pattern should require 40 or 64 hex digits.
- iss-2609251939468296A pre-release CHANGELOG head such as '## [1.0.0-rc.1] - <date>' is invisible to the dated-heading reader, so the release gate's version binding compares against the previous version and the previous release's receipts admit the release. The release workflow's tag pattern accepts -rc and +build suffixes, so a hand-pushed pre-release tag reaches the gate. The derivation should refuse when the newest release heading is one the reader cannot parse.
- iss-2609251939472371The scaffolded release workflows' in-repo audit covers injection and duplicate keys for every profile, but it is not a full zizmor stand-in for the bare profile: action pinning, permissions and credential classes are unchecked there, and only the abcd profile is zizmor-audited in CI. Follow-up: run zizmor over a rendered bare profile in CI.
- iss-2609251939476304The release protocol text says the receipts step reads 'the commit the release publishes from', but the release publishes from the tagged merge (runbook step 5 has it right); the content commit is the one the receipts name.
- iss-2609251940304726The launch gate suite's change-narration gate (hard-fail tier) misses genuine narration after its round-1 narrowing: 'Previously, the ledger was a flat file; now it is a folder.' passes because changeVerbBesideEither counts ',' and 'the' as tokens, so 'was' falls outside its three-word window (itd-65 AC3 names 'previously X, now Y' as the hard-fail case); 'The registry can no longer be edited by hand.' and 'The scanner no longer skips fenced blocks.' pass because 'no longer' fires only beside a fixed list of subject nouns (AC10 says a genuine 'no longer' DOES hard-fail); 'It was renamed to abcd lint.' passes for the same reason; and 'Until v0.6 the dry-run used to skip the tags.' passes because pastHabitUsedTo requires the subject phrase to open its clause. Docs lint has no token for 'used to' or 'renamed to', so the last two shapes are caught by neither tier. Remedy: count word tokens only in the previously/now window, restore 'no longer' and 'renamed to' as hard fails exempting only the relative-clause and comparative forms ('files that are no longer present', 'no longer than') and the purpose form ('is renamed to match'), and read a past-habit 'used to' after a time adverbial.
- iss-2609251940377887launch archive without --verify refuses a dirty working tree (exit 2), but the verb's own help does not say so: the --verify flag help and the Long text in internal/surface/cli/archive.go are silent on it, so the generated docs/reference/cli/commands.md does not carry the refusal either. A local 'launch archive --out d' on a dirty tree exits 2 with an error its --help never mentioned. Remedy: state the refusal in the --verify help and the Long text, and regenerate the reference.
- iss-2609251940383450proseLines in internal/core/launch/gates.go treats a document that opens with a '---' horizontal rule as opening YAML frontmatter whenever a second '---' rule appears anywhere later, so every line up to that later rule is dropped from the marker-block and change-narration gates, silently. A rule opens frontmatter only when the block it closes holds key: value lines. Remedy: drop the leading block only when its lines read as YAML frontmatter (key: value lines, their continuations, list items, comments), and read the document whole otherwise.
- iss-2609251945586202The release gate never binds the pushed tag to the released tree's CHANGELOG version. The content-commit derivation reads the version from the CHANGELOG only, and the release workflow's tag-shape check admits any vX.Y.Z tag, so a hand-pushed tag naming a version other than the tree's newest dated heading (for example v0.9.1 on a tree whose head is 0.9.0) is gated by the receipts for the CHANGELOG's version and publishes under a version nobody reviewed. abcd's own release has the archive-pin step, which names the tag and probably refuses first; a scaffolded repository has no such step. The fix shape is to pass TAG into record-lint --derive-content-sha on the tag path and require it to equal the bound version, which changes the pinned verify step in release.yml and its template, and needs a ruling on how the local launch receipts check, which has no tag, stays equal to the release job's verdict.
- iss-2609252001486609A stale mirror diffs against an older release with exit 0 and no note: in a full (non-shallow) clone whose newest release tag is missing while CHANGELOG.md dates that release — a fork whose tags froze at fork time, a mirror that never fetched the latest tag — unanchoredBaseline (internal/surface/cli/launch_deep.go) returns the newest tag it finds before CHANGELOG.md is read, so launch --dry-run reports parity against v0.9.0 (6 added, 21 changed, 103 unchanged) where v0.10.0 is dated, with no refusal and no note. commands/launch.md promises that a checkout missing the previous release's tag while CHANGELOG.md dates a release is not a first launch and that parity.refused names that release; this checkout is missing exactly that tag and does not refuse. The ship-to-tag window (CHANGELOG.md dates 0.11.0 just cut, tag v0.10.0) carries the same evidence with the opposite meaning, so the refusal there must not call the release just cut the previous release, and --baseline stays the escape.
- iss-2609252004013212embark's openWalkDir refusal returns the raw error, so the fatal line reads 'openat <name>/.: not a directory' and leaks the '/.' suffix into a user-facing refusal naming a path that does not exist (internal/core/lifeboat/embark.go:622; review-lifeboat 2). Wrap it with the entry name.
- iss-2609252007414882This repository's committed pre-commit guard refreshes the sources corpus's generated banlist block with an INSTALLED abcd (the pinned PATH, then ~/.local/bin), which in this source checkout is the last release and stale by construction, against the dogfooding rule and against the commit-msg hook, which builds ./cmd/abcd from the checkout. The guard should build the checkout's own abcd the way commit-msg does, print one warning line and proceed when the build fails, and never resolve an installed binary.
- iss-2609252007419997The scaffolded pre-commit template refreshes the sources banlist block by default with a binary found on PATH or in ~/.local/bin, which answers by fiat the three questions iss-2609250834251447 holds as a ruling owed to the product thinker (how a scaffolded hook finds a binary, fail open or closed, default or opt-in). Until that ruling, the template should refresh only on repo-local opt-in, git config --local abcd.sourcesBinary naming an absolute path to a regular file, with no PATH search and never an environment variable, and otherwise print one line and proceed.
- iss-2609252007422630The pre-commit guard discards the sources refresh's stdout and stderr (>/dev/null 2>&1), so an older abcd that has the source verb but projects fewer patterns rewrites the generated block weaker and the commit prints nothing about it: a silent downgrade. A binary with no source verb prints 'refresh failed' on every commit, noise that teaches the committer to ignore the one line that matters. The guard should print the binary's one-line count, and one clear remedy line when the binary lacks the verb.
- iss-2609252007426016The pre-commit guard's sources refresh CREATES .abcd/.work.local/private-names.txt in whatever repository the commit runs in when a corpus has confidential entries and no private store exists, writing every confidential title, alias and opted-in author as plaintext patterns into a directory that may be cloud-synced or bind-mounted. The refresh should update an existing keyed store only; creating one stays the by-hand abcd source sync-banlist.
- iss-2609252007433563A legacy (unkeyed) private store with entries is refused by abcd source sync-banlist with no migration path: the refusal asks the user to hand-key every line, and the pre-commit guard repeats a warning about it on every commit, for ever. The verb should offer a migration that keeps every line matching what it matched, and the guard should name it once, not warn on every commit.
- iss-2609252007434356abcd source cite-check reports a finding as 'line L, byte B' where B is grep -b's FILE offset of the matched span, which also includes the leading boundary byte, so a reader takes it for a column in line L. The offset must be documented and rendered as what it is, consistently in the type, the help and the surface pages.
- iss-2609252007448074abcd source ledger --flip is the person's act under adr-41 gate 2 (a line is flipped to public citation only by the human), but the shell guard's default hazard registry does not name it, so an agent can run it unprompted; ledger.go refuses a confidential or non-citable source mechanically, so the exposure is misattributed provenance, not leakage. Register the command in the guard's default registry once the guard lane's registry edit has landed.
- iss-2609252020432185The shell guard's unknown-word mark could be forged from the command line: an ANSI-C escape that decodes to NUL (a hex, octal, unicode or control escape) put the tokenizer's substitution mark into a word after Check had stripped the line's own NUL bytes, so an ANSI-C NUL glued before a blocked command's name made that name an unknown word compared as text, and every blocker allowed. bash ends an ANSI-C string at its first NUL and runs the name that follows. Found by review3-guard finding 1.
- iss-2609252020505990The shell guard's stream rule missed a shell handed the stdin device behind a pipe (/dev/stdin, /dev/fd/0) and a shell or source handed a process substitution as its script: each runs a downloaded stream as a script exactly as a pipe into a bare shell does, and each allowed. Found by review3-guard finding 4.
- iss-2609252020507464The shell guard's readers that step option words before command position, or read a shell's -c, took an unknown dash-word (a dash glued to a command substitution) as one fixed thing: never a value flag, never -c. The wrapper walk (sudo, env, nice, timeout, exec, doas, stdbuf, xargs), the operand walk that finds a subcommand (git, gh), the exec-string scan (su -c) and the shell -c reader each read it so, and a hazard behind such a word allowed or only warned, which runs it. Found by review3-guard finding 2.
- iss-2609252024442310The release gate's content-commit derivation can be shadowed by a pull request that lands between the roll merge and the tag. DeriveReleaseContentSha keeps the nearest receipts directory carrying the released version, so a PR branched after the roll merged (it carries the new version) with its own sha-keyed receipts directory, merged on top before the tag, wins: the gate then judges that commit's receipts, either a genuinely reviewed nearer commit or a fail-closed wedge that ignores the roll's real receipts (review2-gatewire probe S11). It is reachable only when a PR lands in that window (a failed auto-release re-run by hand) and admits nothing past the committed-receipts trust boundary. The reviewer's sharpening, admitting only the candidate whose first parent carries a DIFFERENT version (the roll itself), is not contained: it refuses a release branch whose receipts name a later CHANGELOG revision (roll, then a prose fix the reviewers read), whose first parent already carries the new version, which the derivation admits today and commands/launch.md does not forbid. It needs a ruling on whether the reviewed content commit must be the roll itself before the derivation narrows.
- iss-2609252029191920The scaffold's runbook template renders the abcd profile's 'Deterministic gates' heading glued onto the end of the rehearsal paragraph ('...first real release.## Deterministic gates (CI-enforced)'): the '<%- if not .Abcd %>' before the merge-gate and audit sections trims the blank line ahead of it, and the '<% end -%>' after them trims the newline behind, so when the block is skipped nothing separates the paragraph from the heading. The heading is then not a heading, and a gate_lockstep-style reader of the rendered runbook finds no deterministic-gate list at all. Found by a lockstep test over every rendered profile (TestRunbookGateListMatchesVerifySteps).
- iss-2609252038344132Two low notes from the owed review: (1) intent audit --json echoes a dead-letter reason's attacker-supplied text verbatim, so a quoted-back token shaped like 'Raw payload retained at .../.work.local/...' puts a local-tier-looking string in the output (the real retention path is cut correctly; internal/core/intent/owed.go:120-147), and the test's .work.local substring check proves the fixture, not the property; (2) the resolution of iss-2609100509537730 appends a near-duplicate pursued grounds bullet after its corroboration prose.
- iss-2609252045147575The launch gate suite's change-narration hard tier passes itd-65 AC3's canonical form when it is split at a sentence end: 'Previously, the ledger was a flat file. Now it is a folder.' carries 0 findings, because the previously/now construct reads one sentence at a time and needs both words in it. Remedy: when a sentence opens with 'now' and the sentence before it in the same paragraph opens with 'previously', refuse the pair as 'previously … now', located at its first sentence.
- iss-2609252045148890The launch gate suite's change-narration hard tier refuses a 'no longer' inside a subordinate clause, the commonest present-state shape in reference prose: 'Retry until the error no longer appears.', 'Stop when the gate no longer reports a finding.', 'If the path no longer exists, the loader skips it.', 'Delete the copy once it is no longer needed.', 'Cached entries are dropped once they are no longer referenced.', 'Once a record is resolved it is no longer open.' and 'Branches whose upstream no longer exists are pruned.' all hard-fail, because noLongerNarrates exempts only 'no longer than' and a relative pronoun over is/are. The words can tell these apart: a subordinator (until, once, when, whenever, if, unless, after, before, while, whose) opens the clause. Remedy: exempt a 'no longer' whose clause a subordinator opens, and add the seven sentences to narrationSpecification's must-pass set.
- iss-2609252047459767abcd build <itd-N> run again while its run is in progress re-runs the pre-start checks before looking up the live run (loop.Start, internal/core/implement/loop/loop.go), so once the run's own lane changes the tree the resume the verb documents is refused: a worktree or branch that moves the intent to shipped/ (the Delivers-trailer definition of done), or the lane's own claim in the shared run store, makes the peers check exit 3 'held by a peer', and after a land the ready row refuses. build.go's Long text, 31-build.md and commands/build.md all promise that starting again resumes. Remedy: under the lock, look up a live run for the key first and return it resumed; run the checks only when creating.
- iss-2609252049491342The build's peers check (internal/core/implement/loop/check.go peersCheck) fails open on one side and closed on the other: a peer the peer listing names and does not read (Peer.NotRead: its directory or git refuses, its record folders cannot be listed, its ledger holds one id in two folders) is skipped silently by peers.Report.Locate, so a peer whose holding is unknown reads as holding nothing, while the claim half refuses an Unreadable claim as a holding. A record the check cannot see is not one it may start past; the unread peer should refuse as the unreadable claim does, naming it.
- iss-2609252050506863The build's peers check cannot see a lane that has neither moved nor claimed the intent: the peer listing (peers.Report.Locate) sees a holding only when a sibling worktree or branch holds the intent in another bucket, and the claim half sees only a live claim in the shared run store, so a lane at steps 1 to 4 of any run (worktree made, brief written, implementer working, nothing committed that moves the intent) and a second clone of the repository are both invisible, and a second 'abcd build' of the same intent in another checkout starts a duplicate run. The other half of the same check, a peer named and not read being skipped silently while an unreadable claim refuses (fail-open on one side, fail-closed on the other), is iss-2609252049491342, fixed in the same lane. Closing this half needs Start to write a claim into the shared run store when it creates a run, which needs a session identity the host driver does not have yet.
- iss-2609252052381777intent audit --owed labels every entry 'shipped (not yet committed)' and omits shipped from the JSON when the history walk fails, so a day that is unknown reads exactly like an intent that is uncommitted
- iss-2609252052384356intent audit --owed walks the history (about 0.65 s) before it refuses a negative --max, and its flag help does not say it writes (it parks an OWED stub on a markerless head, a diff a peer sees)
- iss-2609252052385551intent audit --owed ignores --route: the --owed branch returns before auditRoute.resolve and emits the head through the option-less ReEmitAudit, so the drain's request carries no Routing section, its JSON next has no routing member, and --owed --route <x> is accepted and silently dropped, unlike audit <itd-N>
- iss-2609252052386874intent audit --owed exits 2 with no listing when the emit on the queue head fails (a malformed spec_id, an unreadable file), and --max cannot skip it, so one bad oldest record blocks every drain run until it is fixed by hand
- iss-2609252053576085The build's open_questions check (intent.OpenQuestions, read by internal/core/implement/loop/check.go) counts every list item under '## Open Questions' as a question whatever it says, so it refuses records that follow the record's own settled convention: 12 of 50 planned intents carry list items there, and some are settled by their own words, itd-111's section opening '_All resolved or explicitly deferred at planning_' and itd-93's '_All four resolved_', itd-76's item marked '**explicitly deferred**', itd-60's items marked '**Resolved', itd-117's '**Deferred**' items. 'abcd build next' (itd-2609211116005482) would meet refusals nobody planned, and the ruling lives only in a lane report. Keep the check fail-closed, but read the markers the record actually uses.
- iss-2609252054322226bare intent audit (the read-only owed listing) accepts --route and silently drops it: the listing dispatches no agent, yet it never resolves the flag, so unlike --issue-drift it does not refuse; a merge-time gap between the owed listing and tier2's --route
- iss-2609252055468079A run state the loop cannot read for a filesystem reason, a symlinked state.json or a symlinked run-<id> directory under .abcd/.work.local/run/, fails closed but as a generic error (exit 1, 'reading …: not a regular file' or 'path escapes from parent') instead of the loop's refusal shape (step, reason, remedy; exit 2) that every other unreadable state takes (internal/core/implement/loop/state.go readStateIn and runIDs), so implement status/step/receipt and build report it with no remedy.
- iss-2609252055532027Every commit in this checkout now builds ./cmd/abcd twice, once in .githooks/pre-commit for the sources refresh and once in commit-msg for the outbound lint (about 13 s on a cold build cache), where one shared build per commit would do; and in a linked worktree the pre-commit prints a sources skip line on every commit beside the existing linked-worktree notice (review2-sources 4 and 7).
- iss-2609252055533837The decision [dcn-2609250000000027](../../decisions/dcn-2609250000000027-the-pre-commit-guard-s-sources-refresh.md) for the sources refresh says the opt-in shape decides none of iss-2609250834251447's questions, but the template does take a provisional stance for the pre-commit refresh (opt-in; fail open on an unusable opt-in); the entry should call that half provisional (review2-sources 5).
- iss-2609252100150846The memory coverage lint writes .coverage_index.json by path (writeCoverageIndex over CoverageIndexPath) after openStore vetted the store, so a store directory swapped for a symlink between the open and the write lands the index outside the repository: the handle's containment covers its reads, not this write. It is not behind the store lock or validatedMemoryDir the way the page writer is, so the writer residual iss-2608291814572914 declares does not cover it. Fix: write the index through the store handle's os.Root (fsutil.WriteFileAtomicInRoot).
- iss-2609252117203691In the ship-to-tag window a re-run of launch ship now refuses on parity first, and that refusal names --baseline <tag>, a flag launch ship does not have; the older 'release vX in flight, tag pending' refusal was the clearer message there (internal/surface/cli/launch_deep.go:136-139; review3-launchdiff note). Reword the clause for the ship path, or run the in-flight check ahead of the precheck in runShipIngest.
- iss-2609252120204766The shell guard skipped the body of a here-document whose delimiter is unquoted as text, but bash expands that body before the command reads it: a command substitution in it (dollar-paren, backticks, or one inside an arithmetic expansion) runs. Every blocker allowed when its command stood in such a substitution in the body, alone, behind a redirection or a list operator, or inside a substitution of its own (review4-guard finding 1). A quoted, escaped or partly escaped delimiter keeps the body literal.
- iss-2609252120211621The shell guard read a parameter-expansion word that carries a command substitution (a dollar-brace default or alternative holding one) with the closing brace as fixed text after the output, so the program name it could be had to end in a brace and a dash-word only a flag that did: a blocked command whose name or flag was the substitution inside such a default allowed (review4-guard finding 3). A plain variable with no substitution in it is the half iss-2609251824244354 defers.
- iss-2609252120212508The shell guard decoded an ANSI-C \c escape as taking the next byte whatever it was, so a string ending in \c swallowed its own closing quote and the line did not parse, and the pre-tool-use hook maps a parse error to fail-open: a blocked command after such a string ran unchecked on every blocker. bash finds the closing quote first and decodes after, and reads \c followed by a backslash pair as one escape. Behind it, a parse error failing open on the hook is a bypass by construction wherever the tokenizer misreads bash (review4-guard finding 2).
- iss-2609252120212639The shell guard reported a command whose program name is a command substitution under whichever registry entry fired first, with that entry lesson: killall-by-name telling an agent to stop a build command by its pid, where the way past the recorded over-block is to spell the program name. The over-block is also wider than the decision [dcn-2609250000000015](../../decisions/dcn-2609250000000015-correction-to-the-entry-above-on-the.md) states: any command word whose basename ends in a substitution, with any operand (review4-guard finding 4).
- iss-2609252120215011Brief chapter 17-guard.md scopes a bare variable to inside a payload in what an allow still does not see, though a variable in the top-level command position or where a flag would be is not read either, so its claim that the obvious evasions are not evasions overclaims; and the cost guard comment states bounded shapes measure one to five units of work per byte, below what bounded shapes measure (review4-guard findings 6 and 7).
- iss-2609252120215841The reader-site test of the shell guard (unknownsites_test.go) detects a function that reads a word dash only by the shapes the package uses today (strings.HasPrefix with a dash literal, a comparison with a dash); a reader written as a switch on the first byte, strings.IndexByte, bytes.HasPrefix or a named dash constant would pass unlisted (review4-guard finding 5).
- iss-2609252127427592intent audit --owed parks an OWED stub with no request when the request write fails: emitAuditWith writes the intent file before the audit request, and NextOwedAudit moves on after the error, so an environment-shaped failure (the reviews directory unwritable, or a plain file) parks a stub on every markerless entry within the cap while each row still reads 'no receipt (one is minted on re-emit)'. The request should be written first (the updated content is already in memory), then the intent file, so a failed emit leaves the intent untouched and the row truthful.
- iss-2609252127428538The intent audit emit errors carry an absolute path unredacted: the drain's per-entry EmitError reaches the text row and the JSON emit_error of intent audit --owed, and commands/intent.md step 2 tells the host to report that text; the single intent audit <itd-N> refusal carries the same unredacted path. Both should pass through fsutil.RedactHome, as the other home-bearing messages in the cli do.
- iss-2609252135151652Check in the shell guard walks the final segments and appends the unknown-sites block signal twice: the block that caches each segment's walk and refuses a capped one is duplicated verbatim (guard.go, from f38daa9a), so a capped walk adds the same signal two times and the second walk is dead work. Found while fixing review4-guard.
- iss-2609252145018018internal/core/lint still reads repository content through unbounded os.ReadFile at about fifteen sites (contextcurrency.go, indexdrift.go, persona.go, schema.go's bucket read, speclinks.go, subverbs.go, and lint.go's intent-tree, spec-store, registry and surface reads), where the per-root markdown walk and, since iss-131, receipt_gate read through fsutil.ReadGuarded after containment. A committed symlink to /dev/zero or an oversize file at one of those paths is followed and read unbounded. The sweep is the unhardened-sibling class iss-131 named; it changes symlink handling at each site, so each needs its own containment decision and test.
- iss-2609252159470046The lint chapter's section 1.1 says prose_citation_resolves scans nine record stores and lists rdi, dsp, rdg, adm and srp as the non-citation stores, while .abcd/record-lint.json names ten under that rule: the reframe store rfm was added to the config and not to the sentence.
- iss-2609252211487887The exported-reach caller audit iss-33 asked for exists only for internal/core/ahoy (TestEveryExportedAhoyFunctionHasAFrontDoor). A crude survey of the other internal/core packages (an exported top-level function with no 'pkg.Name' selector in non-test Go outside its package) lists about 140 names; many are reached only inside their own package, which is over-export rather than dead code, but some have no production caller anywhere, e.g. launch.Ship (grep for '.Ship(' outside tests finds none). Each hit needs sorting into dead scaffolding (delete or wire), in-package-only (unexport), or a declared test seam (name it ...ForTest), and the audit then generalised to every core package.
- iss-2609252214137586The shell guard ends an unquoted here-document body at a line that bash joins onto the line before it. In a body whose delimiter is unquoted, bash joins a physical line ending in an odd number of backslashes with the next line before it compares the delimiter (read_secondary_line with its backslash-newline splice), so x-backslash then EOF is the one body line xEOF and the body goes on. skipHeredocBodies (internal/core/guard/tokenize.go) compared each physical line, ended the body at that EOF, and read what followed as command text, where a single-quoted span or a # comment hides a substitution the body runs: a blocked command in $( ) on the next line allowed, in the plain, <<- and three-backslash twins (review5-guard finding 1, verified on bash 3.2 and 5.3 with a neutral word). The fix report's claim that the guard can only over-read such a body is false.
- iss-2609252214215409A shell or eval payload written as a here-document substitution is not read, though its text is the payload verbatim. sh -c "$(cat <<EOF … EOF)" and eval "$(cat <<'EOF' … EOF)" carry the document's text as the string the shell runs, but the tokenizer leaves a substitution's output unknown, so the payload is uninspectable and the family's loud WARN is the verdict: a blocked command in the document runs (review5-guard finding 3). Where the output is fixed — cat with nothing but the here-document, a quoted delimiter or a body with no expansion in it — the document's text can be read as the payload as well as the unknown output.
- iss-2609252214217550The shell guard blocks valid bash as command-unparsable when a double-quoted ${…} carries double quotes of its own. Inside double quotes bash parses a parameter expansion to its own closing brace: a double quote in it opens a nested string instead of closing the outer one, and a single quote pairs with the next. The tokenizer's double-quote branch and closingDoubleQuote (internal/core/guard/tokenize.go) ended the string at the first nested quote, so an apostrophe inside the nested quotes read as an unterminated single quote: echo "${MSG:-"don't"}", "${1:-"it's"}", printf '%s\n' "${NAME:-"O'Brien"}" and "${X//"'"/x}" returned ErrUnparsableCommand, which the pre-tool-use hook (internal/surface/cli/guard.go) now blocks as command-unparsable, where the round before they ran (review5-guard finding 2).
- iss-2609252243284279capture reframe's whole write picks the previous distinct frame state in git log date order, so across a --no-ff merge where both parents moved the frame the before state is whichever parent's commit is newer, and changed depends on timestamps rather than topology: a record can under-report the surfaces the merged rewrite moved
- iss-2609252243286219capture reframe's whole write refuses with 'the frame's previous state cannot be fingerprinted: carries no H2 section titled Construal' when no distinct prior state lies within the history that carries a Construal section, instead of naming the true reason: no prior distinct state within the fingerprintable history, and how far back that history reaches
- iss-2609252243290965Cold-reading exclusion of the reframe record is by path: a reframe-shaped file (an rfm-N name or reframe frontmatter) planted outside .abcd/work/issues/reframes/, e.g. as a brief chapter, reaches every cold reading with its grounds and body, and no gate names it, where the open/ look-alike is flagged as a mis-named issue
- iss-2609252243299568The four comparative coverage rows for the reframe and derived families state a two-clause Rule (never reach the bundle AND the manifest says so) while only the manifest clause is falsified; the unfalsified leak half is disclosed in a code comment, not in the row's Gap field the matrix header names as the place for an unfalsifiable claim
- iss-2609252251311346jsonstrict.NoDuplicateKeys compares object keys byte-exactly, but encoding/json binds a struct field case-insensitively (its foldName: Unicode simple folding) and keeps the last match. So a receipt carrying "verificationResult": "REJECT" then "VerificationResult": "PROMOTE" passes the duplicate-key refusal and the receipt_gate reads PROMOTE, the exact reviewer-reads-REJECT, gate-reads-PROMOTE evasion the refusal exists to close; "disabled":false,"Disabled":true flips the rules.json kill switch the same way. The check must fold keys per object the way encoding/json matches them.
- iss-2609252251317108Two private duplicate-key walkers survive beside the canonical jsonstrict check: layered.refuseDuplicateKeys (internal/core/layered/layered.go) and reading.refuseDuplicateKeys (internal/core/reading/scope.go). Neither folds key case the way encoding/json binds struct fields, and the reading-preset walker checks only the keys directly under the presets/positions container, so a key repeated inside one entry (a second kinds or window block under a reviewed position) is read last-wins by the strict decoder: the review-evasion vector the walker's own comment names. One primitive, rerouted, closes both.
- iss-2609252251320133The names/ banned-token family inherits skip_code_fences' default of true, so a banned name inside a fenced code block in AGENTS.md or any markdown under roots or name_roots passes the name gate. The default is a writing rule for the documentation family (an example in a fence is not prose); the name gate is documented as reaching the whole public surface, and a fence is published as readily as prose. Nothing records fence masking as deliberate for the names family.
- iss-2609252251320497The name gate's walk over name_roots (lintNameRoots in internal/core/lint/lint.go) skips a file silently when the post-resolve os.Stat fails (for example a file under a directory that can be listed but not searched), so a leak gate passes a file it never read and says nothing. The adjacent guarded read fails loud; the Stat failure should too (loud staging).
- iss-2609252305404421The shell guard reads a here-document handed to sh -c, bash -c or eval as the payload only one level deep. When the document's own text is a command-position $(cat <<'F' ... F) whose document is literal, the payload re-read sees a bare substitution in command position and warns, and a warn runs: an outer sh -c document whose text is an inner command-position document holding a forced git push reaches the push in bash 3.2 and 5.3 (review6-guard finding 1). literalHeredocOutput runs only for a substitution inside double quotes (tokenize.go), and an unquoted one's fixed output, word-split as bash splits it, is never read. The reference page, the plugin page and the help say the document is read as the command it runs, which overclaims.
- iss-2609252310310823The shell guard reads a fixed-output $(cat <<'EOF' ... EOF) as its document's text, but not the same substitution spelled with backticks. A backtick cat of a literal here-document inside sh -c, bash -c or eval double quotes stays an uninspectable payload and warns, and a warn runs; the same backtick substitution standing alone in command position is a silent allow, while bash 3.2 and 5.3 run the document's command in all three shapes (verified with a neutral word). literalHeredocOutput is called only where the substitution opened with a dollar sign (tokenize.go), so the backtick spelling of the review5-guard finding 3 and review6-guard finding 1 shapes is still open.
- iss-2609252311550527The site internals chapter (brief 05-internals/10-site.md) lists /record/timeline/ as a page the explorer serves, but the build never emits it: the genealogy renders folded into the /record/ dashboard, and timelinePage in internal/core/site/timeline.go is unreachable code.
- iss-2609260002152124Two verbs' Use lines under-declare what the verb requires, so the usage line, the worked example check and the aggregated refusal all read a requirement set smaller than the one the verb enforces. history discard refuses without --yes on every call while its Use line is discard <staged-filename>; capture disposition requires --grounds on every state except held, which requires --exit-condition instead, while its Use line brackets both as optional. Confirmed at 6e4eca9a while writing the worked examples for iss-2609100508565741: a disposition example without --grounds and a discard example without --yes are both refused.
- iss-2609260057111298The plugin-files-missing state is worded two ways in one abcd ahoy render: the plugin.root_missing gap speaks plainly, but the guard-health reason still says: plugin root not resolvable, so the hook manifest cannot be read and the guard wiring is unknown.
- iss-2609260057111315dataDirHazard refuses a world-writable plugin data directory or cache subdirectory, but not a group-writable one or one owned by another uid, so on a shared host a group member or another account can still supply the cache artefact and its recorded hash the hazard check claims to rule out. It should apply the caller-alone test the home-scoped declarations use (not writable by group or other, owned by this uid).
- iss-2609260057112155gitutil.CheckoutRoot's refusal for a repo-shaped tree git will not answer for names three causes (git absent from PATH, the repository unreadable, its ownership refused) and omits the fourth that Toplevel's shape check refuses: a core.worktree setting whose working tree does not contain the working directory. A person in that checkout is offered three causes, none of which is theirs.
- iss-2609260057112822InstallResult.explain labels a write that carries no kind as the optional-scanner hint (its fallback is writeScannerHint), so an unkinded write would be explained as something it is not, and a kind with no entry in allWriteKinds drops out of the summary entirely. The fallback should be an honest unexplained-write item.
- iss-2609260057117838abcd update's foreign refusal, for a PATH entry that is a symlink, reads: the entry at X leads to Y, which is not ... a regular file abcd can verify. But Y is a regular file (the classifier Lstat'd the entry, not Y), so the person is told something false about the link's target. The negatives belong to the entry.
- iss-2609260057117878The install summary's plain-language copy says three untrue things. The identity-pin item tells a person with a wrong recorded name or email to run abcd ahoy install again, but stepIdentityPin writes only while no pin exists, so a re-run changes nothing; the skipped-pin item says to answer y if the name and email shown are yours, but nothing shows a name or email (the pin rides on the settings confirm); and the public visibility meaning says only .abcd/ is kept out of git, omitting the /memory/ fence the public block also writes (gitignore.go visibilityEntries).
- iss-2609260057123452The stray-ledger note every capture verb prints reports the checkout's own ledger as a second ledger when the working directory is a case-variant spelling of the checkout on a case-insensitive filesystem (the APFS default): strayStoreNotes compares EvalSymlinks strings, which keep the caller's case, so the walk never meets the root and names ../<root>/.abcd/work/issues as a ledger below the root.
- iss-2609260057127611Three ahoy install writes still swallow their errors, the class iss-227 fixed for their siblings: the identity pin (stepIdentityPin drops a failed identity.WritePin, and an unset git identity, without a word), the .gitignore visibility block (stepVisibility drops applyVisibilityBlock's error), and the conventions-file marker block (stepMarker drops installMarkerFile and removeMarkerFile failures). A run that wrote none of them reports with no reason.
- iss-2609260100382261The question gate can refuse a legitimate question forever: in a managed checkout whose .abcd/.work.local/ exists but is not writable, HasTier reads true and the absent mode file reads managed, so the guard exits 2 on the host's question tool, while the remedy it names, abcd mode facilitator, fails with permission denied. HasTier tests presence, not writability, though its comment says it gates on the verb being able to set the state.
- iss-2609260100391018The PreToolUse hook wrapper in hooks/hooks.json says 'shell commands run UNGUARDED' when the binary is missing or crashes, including on a call to the host's question tool, where it is the question that runs ungated, not a shell command.
- iss-2609260100393814An undeletable question marker (a directory planted at .abcd/.work.local/question_open) makes every later prompt reset a hand-set mode to managed and repeat the error line: ResetOnAnswer writes managed first and only then fails to remove the marker, so the marker survives to trigger the same reset on the next message.
- iss-2609260100396332The badge and the mode notice name the facilitator role in two different words: the status-line badge hard-codes 'waiting on the technical facilitator' while mode.State.Addressee(), which claims to be the one vocabulary seam for both, returns 'facilitator', so abcd mode facilitator prints 'waiting on the facilitator' where the badge reads 'waiting on the technical facilitator'.
- iss-2609260115287911The shell guard follows a backtick substitution's text verbatim, but between backticks bash removes a backslash before a dollar sign, a backtick or a backslash before it parses the command. So in an unquoted here-document body inside backticks, an escaped dollar-paren substitution or an escaped backtick pair is a live substitution bash runs, and the guard skips it as escaped: echo, a backtick, cat <<F, a body line holding \$( <hazard> ), F, a backtick is a silent allow (and its <<-F, x= and double-quoted twins), while bash 3.2 and 5.3 run the hazard (verified with a neutral word). The same pre-pass is missed for an escaped backtick pair nested inside a top-level backtick. Found by review7-guard finding 1; pre-existing at f97a7514.
- iss-2609260115380561The shell guard reads an unquoted fixed here-document output as its split words only where the word is wholly that substitution. Text glued to it (the substitution followed by x) or two such substitutions glued together fall to the unknown reading and reach ALLOW in command position, while bash runs the joined words: the hazard with x appended to its last word, or the hazard assembled from the two documents (review7-guard finding 3, verified with a neutral word). The guard page and the brief say the words are read wherever the substitution stands, which is false for a glued word.
- iss-2609260115383631The guard brief's residual paragraph does not name two postures the exact-shape read of a cat here-document makes sharp: a lone substitution whose output is unknown in command position is an allow by the recorded posture (an allow means no entry matched), and only the exact shape cat <<DELIM, newline, body, delimiter, blanks is read as fixed output, so /bin/cat, command cat, cat -, a redirection after the delimiter word, a backslash-newline before the <<, a command after the document and a backslash-newline after a backtick document all stay unknown and allow (review7-guard finding 4).
- iss-2609260115387303The shell guard splits an unquoted fixed here-document output on the default IFS (payload.go fixedOutputSegment), whatever the line assigned IFS to before it. A line that sets IFS in a command of its own (IFS=x; or IFS=x and a newline) and then runs an unquoted cat of a quoted here-document whose body spells a hazard joined by x reaches ALLOW as one word with no operand, while bash 3.2 and 5.3 split it on x and run the hazard (review7-guard finding 2, verified with a neutral word). A prefix assignment on the same command does not take effect in bash and is read correctly.
- iss-2609260120380520The machine credential file (internal/core/credential, ~/.abcd/credentials.json) is decoded with plain json.Unmarshal, so a duplicate key silently takes the last value instead of being refused; the strict duplicate-key decoder (jsonstrict) lives on an unmerged lane, not on this base.
- iss-2609260120380835When abcd site setup's forge stage is refused (gh absent or unauthenticated, or a forge call failing) it prints the gh secret set steps for the site environment but no step to create the environments, so a person following the steps sets the token and the first workflow run auto-creates site with no deployment policy, deployable from any branch.
- iss-2609260120383554abcd site setup rewrites an existing deployment environment through PUT /repos/{r}/environments/{env} with only deployment_branch_policy in the body, and that endpoint replaces the whole protection set, so a site environment carrying required reviewers, a wait timer or prevent_self_review loses them after a confirmation that names only a branch restriction (setup.go plan.put, forge.go PutEnvironment).
- iss-2609260120384106The site workflow abcd site setup writes never fires by itself on a repository launch scaffold laid out: auto-release runs release.yml by workflow_call so no run named release exists for workflow_run, a tag-push release run has the tag as head_branch which the branches filter drops, and a GITHUB_TOKEN-made release fires no release:published, so only a hand dispatch deploys while the verb says the site deploys on the next published release.
- iss-2609260149217402The reviews charter (.abcd/work/reviews/README.md, Enforcement) says the RD codes are defined in .abcd/development/brief/05-internals/06-lint.md, and scripts/check-reviews.sh's header points there for the RD family, but 06-lint.md defines no RD code and says the lint engine carries no numbered catalogue; the codes are defined only in scripts/check-reviews.sh, so both pointers send a reader to a chapter that does not hold them.
- iss-2609260149234099TestThePublishConditionNeedsAGreenVerify derives whether a source is the reusable gate from the condition under test (gate := strings.Contains(cond, "inputs.publish")), so deleting the '&& inputs.publish' clause from the gate profile's build and release jobs in release.yml.tmpl leaves the suite green; a caller that passes publish: false with contents: write would then get a Release from the gate before its own build. The expectation must come from the profile that rendered the source.
- iss-2609260149238314gitutil.ArchiveTree asks check-attr about each directory without a trailing slash, so the directory-only export-ignore form (dir/ export-ignore, at the root or in a nested .gitattributes) never matches and the non-plugin launch preview lists and scans files git archive HEAD omits; asking both dir and dir/ is also wrong, since archive asks a directory as dir/ alone and dir export-ignore followed by dir/ -export-ignore keeps it.
- iss-2609260149240890The launch scaffold header prints the host's Go toolchain (go 1.25) for a repository that declares a non-Go application and carries no go.mod; the Go version is only meaningful when go.mod exists.
- iss-2609260149247384gitutil.ArchiveTree passes its revision to git ls-tree as a positional argument without --end-of-options, so an option-shaped revision is parsed as a flag; the sole caller passes HEAD today.
- iss-2609260149248713The artefact kinds binary and application behave identically in every launch verb (KindBinary is referenced nowhere outside the reader, and the Go leg keys on go.mod), and neither the launch page nor the intent's Decisions says so, so a reader expects the choice to change what the release does.
- iss-2609260149249724The artefact-kind reader decodes with plain encoding/json: a duplicate top-level key takes the last value ({"kind":"wasm","kind":"binary"} reads as binary) and lockstep object entries decode case-insensitively ({"PATH":..,"JSON_POINTER":..} accepted) while the top level refuses Kind.
- iss-2609260149249835A declared lockstep path is contained lexically only, so a committed symlink inside the repository that points outside it is read through: launch reads a file out of the tree and surfaces its parse error or the version value at the pointer. The path must be resolved and a target outside the repository refused.
- iss-2609260221563975intent plan's comment and surface claim a refusal leaves the record byte-identical with no spec minted, but the spec is minted before the intent write: with planned/ read-only, intent plan refuses (exit 2) and leaves an orphan spc file under specs/open/ that a retry reuses. Self-healing, not atomic; the claim overstates it.
- iss-2609260221565656The staging hooks and the guard hook print stderr diagnostics that bypass Run's masking: session-end (cli.go warn) and subagent-stop (hook_subagent.go warn) print msg raw while the --json reason is Sanitize'd, so a transcript_path carrying ESC or RLO reaches the terminal raw; guard hook failOpen and its dropped-repo-layer lines print %v and scrubPaths(err) unmasked, so a committed .abcd/guard.json whose entries map key carries ESC reaches stderr raw through the JSON type error. iss-2609012037438844 was resolved as masking at the print site, which is false until every stderr print in internal/surface/cli that bypasses Run masks too.
- iss-2609260221577624hook session-end's not_captured --json result omits session_id, where hook subagent-stop's not_captured result includes it, so a caller cannot tell which session a session-end failure lost from the result line alone.
- iss-2609260221578565barerender's exception list gives statusline the reason 'with no payload there is no row to render', which is false: bare abcd statusline with stdin at /dev/null renders a row and exits 0, so it is not an exception to the bare-render property.
- iss-2609260234039115The brief's press release carries the Forward-looking discipline bullet twice under What's In Scope, and the two copies contradict each other: the first (re-added by c4fc433e) says /abcd:intent grill is a sibling sub-verb of refine and that /abcd:intent consistency shipped in spc-29, while the second (from 7c3fe74c) says grill, consistency and shape are designed and not yet built. Neither refine nor grill is a registered sub-verb, and spc-29 is a predecessor-store id. Which bullet stands is the product thinker's call, since the page is the headline product in the product thinker's words; the stale copy should then be removed.
- iss-2609260319483365The race lane runs internal/surface/cli at the edge of go test's default 10-minute per-package timeout on the macOS runner, so a slow runner ejects an unrelated pull request from the merge queue. PR #717 was ejected by merge_group run 36212607621 (job check (macos-latest), step Test (race, internal)): panic: test timed out after 10m0s and FAIL github.com/intentdriven/abcd/internal/surface/cli 600.120s, with no test hung; the package's total wall time crossed the default. The same package under -race on macOS took 417.9s (run 36211489533), 472.0s (36211390371) and 567.9s (36209973364), and 324-355s on ubuntu. ci.yml's race step, release.yml's verify race step and the Makefile preflight all run go test -race ./internal/... with no -timeout, so the ceiling is the implicit default rather than a budget sized from measurement. The job ceilings around the step are as tight: the macOS check job took 19.0, 21.4, 25.9 and (failing) 28.1 minutes against timeout-minutes: 30, so lifting the package timeout alone moves the failure to the job cap, where it arrives with no goroutine dump; and release.yml's verify job, ubuntu only with an uncached toolchain, took 13.2 minutes of its 15 on 2026-09-24 (run 35963282477, cli race 302s), since when the ubuntu race step has grown from 9.8 to about 12 minutes, so the next release's verify job is at risk of the same cancellation.
- iss-2609260543090196abcd guard warns instead of blocking a dash-glued substitution word after timeout when no duration follows: `timeout --$(x) pkill -f node` and `timeout -$(x) pkill -f node` come back as unrecognised-launcher (warn), while the same word behind sudo, env, xargs, nice, exec, doas, stdbuf, su or git blocks, and `timeout 5 pkill -f node`, `timeout --$(x) 5 pkill -f node` and `timeout 5 --$(x) pkill -f node` all block. Found by the v0.11.0 docs-currency gate (dc-4) and confirmed by the changelog composer against bin/abcd-darwin-arm64 built from ae116575.
- iss-2609260552246303`abcd history list|show|staged --help` say "Writes nothing" and commands/history.md:15 says they perform zero writes, while the store resolve seam (internal/core/history/location.go) creates the user-level store chain and moves a legacy corpus on first resolve, which commands/history.md:29 itself admits: the help and the page contradict each other and the behaviour. Found by the v0.11.0 brief-surface cross-check (x-036, x-037).
- iss-2609260552247252commands/lint.md:11 says the lint command performs zero writes and names only the temp-dir site render, but `abcd lint site` renders the site into `--out`, default ./site under the working directory, when that directory holds no index.html: a bare run in a repository leaves a new directory. Found by the v0.11.0 brief-surface cross-check (x-045).
- iss-2609260552247395commands/launch.md:152-153 tells a user that a failed release shows up as auto-release's detect job failing on the archive-pin gate, but auto-release runs no `launch archive` since 2026-09-25: the gate is release.yml's verify job, so the page sends the reader to the wrong job. Found by the v0.11.0 brief-surface cross-check (x-007).
- iss-2609260552249742commands/disembark.md argument-hint offers a bare `<source-repo> <dest>` form, but only `abcd disembark pack <repo> <dest>` exists: typing the advertised form fails with `unknown command "<repo>" for "abcd disembark"`. Found by the v0.11.0 brief-surface cross-check (x-006), reproduced by the classifier.
- iss-2609260552250826The inbox refuses a path occupied by a symlink or a file with an error not wrapped in ErrRefused (internal/core/report/inbox.go:176), so the refusal exits 1 against the documented exit-2 refusal contract in commands/inbox.md:66; a promotion can also exit 1 after its capture was already written. Found by the v0.11.0 brief-surface cross-check (x-065).
- iss-2609260552251398`abcd capture resolve` refuses an unknown id and a transition conflict at exit 1 while the same verb's other refusals (a lone word, malformed grounds) exit 2 as commands/capture.md documents, so the refusal exit code is inconsistent within one verb (internal/core/capture/workflow.go). Found by the v0.11.0 brief-surface cross-check (x-099).
- iss-2609260552254288`abcd ahoy install` seeds a committed .abcd/docs-lint.json from abcd's own writing-guide rules into a target repository when it has none (internal/core/ahoy/apply.go, defaults/docs-lint.json), while the prepare-this-repo chapter (15-prepare-this-repo.md:125-127) says lint-config JSON the tool supplies is applied and never committed: the installer and the criterion disagree and one of them has to give. Found by the v0.11.0 brief-surface cross-check (x-044).
- iss-2609260552256401commands/inbox.md:22-23 says the text forms open with an `untrusted:` line, but bare `abcd inbox` opens with a header first and an empty inbox prints `abcd inbox - nothing waits` with no untrusted notice at all, so the framing a reader is told to rely on is second or absent. Found by the v0.11.0 brief-surface cross-check (x-064), reproduced by the classifier.
- iss-2609260552256523`abcd report`: on an exit-1 failure after the editor ran (inbox not creatable, id draw exhausted, temp file not creatable) the kept editor draft is named only for ErrRefused errors (internal/surface/cli/report.go), so the text survives but the user is not told where it is; commands/report.md:53 documents only exit 2. Found by the v0.11.0 brief-surface cross-check (x-063).
- iss-2609260709386741site.yml probes for the site verb by grepping the ROOT help listing (./abcd --help | grep -qE '^[[:space:]]+site[[:space:]]', four places: the production render step, its check step, the preview build step and the preview check step). Since the grouped root help landed (#711, merge a3cdf26e) abcd --help lists only the human-facing verbs and site appears only under abcd --help --agent, so every site run on a binary built after a3cdf26e refuses with 'this binary has no site verb': the preview job has failed on every push to main since (run 36225049347 on 22997314 and the eight before it), and the production render the release chain calls after publishing v0.11.0 refuses the same way, leaving abcdev.app unrendered for the release. The probe must read the agent listing where the binary has one and the flat listing where it does not (v0.6.2 to v0.10.0 carry site but refuse --agent as an unknown flag), and still refuse, in one line, a binary built before the site slice.
- iss-2609260856423957abcd site setup reports an existing environment on custom deployment policies as current, or adds the missing rules and reports it written, with no restriction step, even when it also holds a rule broader than the default branch and tags v* (a branch policy `*`, for example). setupEnvironments marks an environment unrestricted only when it is not on custom policies or admits protected branches; it reads the existing policies only to find the missing ones, never to find the extra ones, so an environment that admits every branch through a custom rule passes as restricted and the deploy environment's secrets can be reached from unreviewed workflow content.
- iss-2609260904161412credential.SetMachine and oracle's writeProviderBlock read, modify and rename ~/.abcd/credentials.json and ~/.abcd/config.json with no lock, so concurrent ahoy connect runs lose a key or a provider block while each reports it wrote the file.
- iss-2609260904163830The OpenAI-compatible client scrubs only the literal key from a provider's error text: a 4xx body that echoes the key JSON-escaped in a field other than error.message (for example {"detail":"bad key sk-abc\/def+ghi"}) falls to the raw body, the scrub misses the escaped form, and the key reaches the error and stderr. The provider-reported model is recorded and quoted in the denylist refusal unscrubbed as well.
- iss-2609260904167076The openaiapi package doc says the client reads no environment, but its nil Transport is net/http's DefaultTransport, which honours HTTPS_PROXY, HTTP_PROXY and NO_PROXY, so the doc misstates the adapter's network path.
- iss-2609260908572219Ingest --keep-original writes the kept original by path after every vetting has lapsed: storeOriginal Lstats the leaf sources directory and calls fsutil.WriteFileAtomic on <repo>/.abcd/memory/sources/<hash><ext> after WritePages has released the store lock and its validatedMemoryDir walk, and the store handle Ingest opened is not used for it. The Lstat guard binds the leaf, not an ancestor, so a .abcd/memory swapped for a directory symlink between WritePages and storeOriginal lands redacted source material outside the repository while Ingest reports status=ingested with kept naming the in-repo path the file is not at. Neither the store-handle record iss-2608291814572914 (reads, plus the locked writer as the residual) nor iss-2609252100150846 (the coverage index) covers it. Fix: after WritePages, open a store handle and write sources/<hash><ext> through fsutil.WriteFileAtomicInRoot, keeping the symlink refusal as root.Lstat("sources").
- iss-2609260926130217abcd intent consistency ingest files every finding in the ledger before it creates the report, and when the report create or write fails the error names only the report path, not the issue records already filed with that report as their evidence, unlike the filing-failure error beside it, which does name them.
- iss-2609260926130480abcd intent consistency pins its report to HEAD (review_of_commit) but reads the brief and the intents from the working tree, so an uncommitted or untracked edit to a brief page or an intent is quoted in an append-only report under a commit that does not hold the quoted text at the cited path:line, and nothing in the report says so. itd-28's dirty-tree policy for review pins is to tag dirty: true and not block; the consistency emit neither tags nor refuses.
- iss-2609260926323349itd-48 shipped the consistency pass (Role 2) and nothing tracks the five spc-33 deferrals it was the routed home for: spc-33:A1 (Role-2 mechanical half, cross-doc lint codes), spc-33:A2 (Role-2 pre-commit hook, blocking-vs-advisory policy), spc-33:A3 (Role-3 pre-commit scheduling, whose shape role now belongs to the kinds lint in itd-34), spc-33:A4 (chunked corpus review, dormant until a report shows bundle_overflow: true) and spc-33:G1 (a stable reconciliation key for consistency findings across re-runs). This record is their home until one is planned; A3 goes with itd-34, the rest are follow-ups of the shipped pass.related itd-2609291923559186
- iss-2609260927214634site setup compares the environment's deployment branch rules against a default branch derived by scaffold.deriveBranch (origin/HEAD, else the checked-out HEAD, else main), not the forge's default branch, so on a checkout with no origin/HEAD run from a feature branch a correctly restricted environment is told to remove its rule for main. The advice is wrong but nothing is written; the spec's 'default-branch name read from the forge' does not describe the code.
- iss-2609260927217168site setup reads an environment's deployment branch policies with per_page=100 and no pagination (forge.go:112), so a broad branch rule past the 100th policy is invisible to the restriction check and the environment can read as restricted when it is not. Reaching it needs an admin who already put over 100 rules on one environment; the environments and secrets reads at :84 and :145 share the shape.
- iss-2609260928152365The site header always links /docs/ (compose.go:334), so a managed repository set up with site setup and no docs build serves a navigation link that 404s on every page. The renderer's page shapes were out of the sitesetup lane's scope; the link should follow whether a docs tree is rendered.
- iss-2609260932372448A spec step that waits on another intent has no marker, so the build loop opens a lane on it: spc-2609202134338445's step 3 (the process driver) waits on itd-2609201916056194, and `build` takes the first unlanded step and briefs a lane there, which can only report the dependency. A blocked:/after: marker would change the first-unlanded-step rule and the ready row's count, which is a product design point, not an implementer's; routed to the product thinker.
- iss-2609260932374727settledMarkRe (internal/core/intent/questions.go:30) admits `resolved:` or `deferred:` anywhere in an open-question item, so an item such as 'Which id wins once the split is resolved: the old or the new?' reads as settled and build starts past a real question. No record trips it today (every intent scanned); the tightening is a label at the item's start or after a closing bold plus dash, not mid-sentence.
- iss-2609260933592838gitutil.ArchiveTree reads export attributes with `git check-attr --cached` (the index) while `git archive` reads them from the archived tree, so the two disagree when a .gitattributes change is staged but not committed: the launch listing can include or omit a path the released archive does the opposite with. `check-attr --source=<rev>` (git 2.40 or later) reads the same tree git archive does.
- iss-2609260935465554The brief's context page (01-product/02-context.md, the /abcd:intent bullet) lists consistency among the /abcd:intent sub-verbs remaining design targets, while itd-48 has shipped it and the press release says it ships.
- iss-2609260948440803Local-tier writes by path: memory lint writes its run-log report by path into the local tier and follows a symlinked ancestor out of the checkout. Lint (internal/core/memory/lint.go, lintReportDir and the write after it) joins .abcd/.work.local/logs/memory/lint-<ts> onto the repo root, os.MkdirAll-s it, and writes report.json and report.md with fsutil.WriteFileAtomic by path. Nothing vets .abcd/.work.local or logs/ first, and a committed symlink beats .gitignore (git add -f), so a checkout that ships .abcd/.work.local as a symlink gets the directory chain and both reports created at the link's target: probed at 35d5cf5f with .abcd/.work.local linked to a directory outside the repo, Lint returned nil and logs/memory/lint-<ts>/report.json and report.md were written in the outside directory. The contained pattern for this same tier already exists: mode.SetAt (internal/core/mode/store.go) opens an os.Root on the checkout, root.Lstat-refuses a .abcd/.work.local that is not a real directory, and writes with fsutil.WriteFileAtomicInRoot. Two sites the review named alongside were checked at 35d5cf5f and are NOT in this class: intent/audit.go's review request and dead-letter writes vet .abcd/.work.local/reviews level by level with fsutil.EnsureRealDirAll, and history/location.go's moveFile writes under a chain Resolve proved real with fsutil.EnsureRealDir, so both refuse a symlinked ancestor; each keeps only a vet-by-path-then-write-by-path swap window.
- iss-2609260958580553The OpenAI-compatible client admits a plain-http base URL to LOCALHOST (or any case other than lower) through its case-insensitive loopback check, but net/http's proxy exclusion compares the host with localhost case-sensitively, so with HTTP_PROXY set the call is proxied and the bearer key crosses the proxy in cleartext, against the package doc and the adapters chapter, which say a call to this machine is never proxied.
- iss-2609260958587561The machine credential store is less strict than its sibling the rules loader about ~/.abcd: credential.SetMachine writes credentials.json and its lock through a ~/.abcd symlinked to an existing directory (a dotfiles checkout), where the rules loader refuses rules.json behind a symlinked ~/.abcd, so a secret can land in a dotfiles repository; and the store's lock files are created 0644 while a pre-existing 0755 ~/.abcd is never tightened, so any local user who can open a lock (a read-only descriptor holds LOCK_EX) can stall every connect for its five-second wait.
- iss-2609260958588580The OpenAI-compatible client's error echo leaks a key written with ordinary ASCII runes as JSON \u escapes when the body is not decodable JSON: a plain-text body, or a JSON body cut at maxErrorBodyBytes, falls to providerSaid's raw-text fallback, which only resolves HTML references before the scrub, and keyForms carries \u escapes for non-ASCII runes alone, so {"detail":"bad sk-<key> cut at the bound reaches stderr while the same body as valid JSON is scrubbed.
- iss-2609261004260522lab sweep is not fail-closed (AC3): state/probes/ is skipped whole, so a retracted claim in a probe's record.md Observation is never listed; a document over the 4 MiB read cap is listed as not swept yet the sweep still passes; and a document with a NUL in its first 8000 bytes is skipped silently, not even listed. Sweep every probe file but the five capture files, list every document not swept by path, and fail the sweep when corrections exist and any document was not swept.
- iss-2609261004261615lab preflight isolation.hooks reads core.hooksPath raw with git config --get and judges the unexpanded text: a %(prefix)/... value (git expands it to its install prefix) is treated as snapshot-relative and passes as resolving inside the lab, a false PASS on the operator-state route; the ~user branch is a hand-rolled special case of the same gap. Judge the path git itself expands (git config --type=path --get) and refuse any expanded path outside the lab.
- iss-2609261013469387ahoy's hooksPathArmed reads core.hooksPath raw with git config --local --get and joins a non-absolute value to the clone, so a ~/ spelling of the committed .githooks directory (which git expands to the same directory) reads as unarmed, and the status line advises re-arming a clone whose name guard already runs. Sibling of iss-2609261004261615: judge the path git expands (--type=path).
- iss-2609261016494611The armed receipt gate is satisfied by a forged PROMOTE reached through a symlinked commit directory. checkReceiptGate (internal/core/lint/lint.go) reads each receipt with fsutil.ReadGuarded on the unresolved path `.abcd/work/reviews/<sha>/<gate>.json`, and holds only receipts_dir inside the repository once links are followed. O_NOFOLLOW refuses a symlinked leaf, but the kernel follows every ancestor, so a committed `.abcd/work/reviews/<sha>` that is a link to a directory outside the tree, holding a well-formed PROMOTE receipt, yields zero receipt_gate findings: the release gate passes on a receipt the tree does not hold. The release-gate manifest read has the same shape: a symlinked `.abcd/development/release-gate` directory hands the gate an out-of-tree manifest whose hash a forged receipt can echo. iss-2609012037127981 was resolved with grounds that the gate is never satisfied by a receipt reached through a link, so that resolution over-claims.
- iss-2609261019593167Two lint reads trust a path the repository does not hold, siblings of the receipt gate's symlinked commit directory (iss-2609261016494611), found on its sweep. (1) loadProseBaseline (internal/core/lint/prosecitations.go) reads the prose-citation baseline at the committed config's baseline path with no containment at all: a path that climbs out with '..', or one whose directory is a link out of the tree, is read, and every id the out-of-tree file names stops firing, so prose_citation_resolves passes on an exemption list the tree does not hold. (2) ReadReadingOutstanding (internal/core/lint/readingoutstanding.go) refuses a link at every directory below the issue store and not at the store root itself, so a symlinked store root carries the whole reading walk out of the tree and the outstanding board reports on records the repository does not hold.
- iss-2609261034583909Eight resolved records name, in their resolution notes, a test no longer in the tree; each was true when written, and RS006 reads only records entering a terminal folder, so none is refused, but a reader following the note finds nothing. Verified at b7646ff1, with the commit that removed each test: iss-184 names TestTokenizeRejectsUnterminatedHeredoc (16d50feb renamed it TestTokenizeFlagsUnterminatedHeredoc and changed the behaviour: an unterminated heredoc is a verdict, not ErrUnparsableCommand, so the note's part (2) is stale too); iss-2608301808193750 names TestIsAbsentValueIsASpellingTestNotANullTest (3eb4b549 replaced the spelling predicate with a class-based one, TestAbsenceIsDecidedByClassNotBySpelling, so the note's 'deliberately NOT widened' is superseded); iss-2608311632382737 names TestPreflightRunsBothEvalLanes (the test is TestPreflightRunsEveryTaggedEvalLane, which derives the lanes from the Makefile; the one clean rename of the eight); iss-2608311632439831 names TestComparativeRefusesToAssemble (3b62c967 made the comparative position assemble from the widening run's items, so the refusal the note describes no longer exists); iss-2609012039117381 names TestBinaryHooksFallBackToAPathBinary and iss-275 names TestGuardShimFallsBackToPATH (c637a734 removed the PATH rung those tests pinned: the shims run only the abcd the machine recorded); iss-354 names TestWorkflowGoVersionsMatchSubstitutions (removed in df377ee6, replaced by TestEverySetupGoResolvesTheToolchainFromGoMod under iss-2609090951291799); iss-2609090951291799 names TestWorkflowGoVersionsMatchSubstitutions only to say it was replaced, which stays accurate. Six of the eight need an amendment note stating what superseded the test and the claim, not a rename, so the set is not a mechanical fix.
- iss-2609261036354146scribe ingest authenticates nothing about the parked context and manifest pair: a scribe that rewrites context.json's supplied dispositions and recomputes the manifest's context hash passes the verbatim check against text it wrote itself, while manifest.supplied.dispositions_sha256 is recorded and never read
- iss-2609261036355193scribe ingest never holds a disposition's state to the supplied text: a researcher line 'rdi-X: rejected — <ground>' ingests as state accepted with the verbatim ground, so the ruling itself is the one field the scribe can author, against the spec's out-of-scope rule that a state the material does not carry is refused, never supplied
- iss-2609261036355918scribe ingest promotes the manifest beside the run even when no record landed, so a payload of refusals or outstanding items alone locks the run against every later scribe session over it
- iss-2609261036363114scribe ingest decodes its payload with plain encoding/json, so a duplicate key at any depth takes the last value: {"state":"rejected","state":"accepted"} decodes as accepted rather than being refused
- iss-2609261036363663scribe assemble refuses a symlink at an allow-list directory and inside it but not at its ancestors (.abcd, .abcd/work, .abcd/work/issues): os.Root follows an in-root link, so a committed issues -> docs/shadow link carries shipped-tree content into the scribe context under ledger paths
- iss-2609261036366114scribe ingest --json renders refusals[].reason, refusals[].subject and the fidelity flags, which are scribe free text, raw: the text render neutralises them through termsafe and the JSON render leaves bidi and C1 controls in place (the iss-359 class)
- iss-2609261039132350A principle whose statement is written as an H2 heading (## The rule) is projected by projectField's heading leg before the labelled-paragraph leg, so the whole section travels to a reading, its Why and Bounds included, under a manifest naming the field The rule; the lint judges only the labelled paragraph, so no gate refuses the shape and the floor's statement-alone promise breaks on a file shape.
- iss-2609261039134673principle_claims judges only the **The rule.** paragraph while the projection sends the H1 title above it and verifyPrincipleItem scans both, so a typed principle whose title cites a record (# Title citing itd-79) passes record-lint and then refuses the whole reading assembly: the two readers of a principle's statement disagree about what it is.
- iss-2609261039139464A principle statement's citation check reads links as inline `[label](target)` only: a bare URL, an autolink `<https://...>` and a reference-style `[label][ref]` travel into the bundle raw and the lint is silent on all three, while the manifest's exclusion row asserts record handles and links in a principle stay behind.
- iss-2609261055135912The consistency ingest takes the dirty mark from the issued request alone: validateConsistency (internal/core/intent/consistency.go) reads the dirty and dirty_path lines of the request and never recomputes them, though it re-reads the tree for the receipt check anyway. A request hand-edited to dirty: false over an uncommitted corpus therefore ingests rc=0, and the append-only report pins review_of_commit with no dirty mark while its findings quote text that commit does not hold.
- iss-2609261056373310scribe assemble reads the ledger as it stands in the working tree, uncommitted records included, while itd-2609020625402599's scope condition (cond-2609020626046719) says the context is assembled from committed ledger content; which one moves is a ruling owed: amend the condition to the working tree, or have the assembler read committed content (and refuse or report uncommitted records)
- iss-2609261106286306The inbox's not-a-real-directory refusal names no level: errInboxNotRealDir (internal/core/report/inbox.go) says 'the inbox path is not a real directory' whatever level fsutil.EnsureRealDirAll refused — the home directory, ~/.abcd, ~/.abcd/inbox or ~/.abcd/inbox/promoted — and drops the *os.PathError path the earlier message carried. With ~/.abcd a dotfiles symlink, abcd report and abcd inbox promote say the inbox path is a symlink, the user looks at ~/.abcd/inbox, which does not exist, and is stuck. The refusal should name the refused level, home-redacted, and keep exit 2.
- iss-2609261106287078The inbox readers follow a symlinked ancestor the inbox writers refuse: peekInbox (internal/core/report/inbox.go) checks the inbox leaf with fsutil.IsRealDir, which lstats the leaf only, so with ~/.abcd a symlink abcd inbox, abcd inbox show and the session-start count read through the link while abcd report and abcd inbox promote refuse it through fsutil.EnsureRealDirAll. The comment on the refusal claims every verb refuses a symlinked level, which is true only of a symlink at the inbox leaf. Readers and writers should refuse the same paths, as the rules loader refuses ~/.abcd/rules.json behind a symlinked ~/.abcd.
- iss-2609261106287627A refused or unreadable inbox is silent at session start and on the board: inboxGreeting and boardInbox (internal/surface/cli/report.go) call report.Count and discard its error, so an inbox abcd refuses to read prints nothing where a count belongs, which reads as an empty inbox. Loud staging asks for one line naming the refusal, sanitised and home-redacted, in place of nothing.
- iss-2609261108448674ahoy install falsely refuses the local tier of a checkout reached through a symlinked path, and its refusal names no level. stepLocalTier (internal/core/ahoy/statusline_apply.go) proves .abcd/.work.local with fsutil.EnsureRealDirAll from a.cwd, and a.cwd is filepath.Abs(os.Getwd()) (internal/core/ahoy/apply.go, internal/surface/cli/cli.go), the shell's logical working directory. EnsureRealDirAll proves its BASE real before any level below it, so `cd ~/proj` where `~/proj -> ~/src/proj` makes `abcd ahoy install --yes --adopt` exit 0 with "note: refused to create .abcd/.work.local/: something that is not a real directory (a symlink, or a file) stands at that path" while no symlink stands at or below the checkout's .abcd, and while .abcd/.work.local itself stands as a real directory (the banlist step created it earlier in the same run). The refused level is the checkout path the user entered through, which the message does not name; it sends the user to .abcd/.work.local instead. abcdDirHazard (internal/core/ahoy/apply.go) Lstats only <cwd>/.abcd, so it neither catches nor explains this. Reproduced on a scratch repository with a real .abcd, entered through a symlink, under a temp HOME. The fix resolves the checkout root through its symlinks before the proof (the way internal/surface/cli/cli.go's strayStoreNotes resolves cwd), so only a symlink at or below the checkout's .abcd is refused, and names the refused level repo-relative. The sibling of the inbox refusal's unnamed level.
- iss-2609261115023216The decisions-append gate's ledger diff (internal/core/lint/decisionsappend.go, analyse) pins --unified=0 and the diff algorithm but not the other hunk-shaping options a repository's own config supplies. A repo-config diff.interHunkContext above zero folds neighbouring -U0 hunks into one with context lines between them, and the old-line arithmetic (removed line k is old line a+k-1; an addition sits after a+b-1) then counts across the context: two separate DA002 findings collapse into one at the wrong span. diff.indentHeuristic=false likewise slides an ambiguous hunk, which moves the line a finding names. Config is not in the tree and CI's is trusted, and the shell gate had the same exposure, so the effect is on a local run over a hostile or merely unusual config. Fix: pin --inter-hunk-context=0 and --indent-heuristic (git's default, which the rules and their cases were written against) on the diff.
- iss-2609261117268064TestEveryRangeScopedGateResolvesABaseOnEveryEvent's delegation exemption (internal/core/lint/rangegatebase_test.go, baseGuardingGates and delegatesBaseGuard) is a substring test over the whole step body: a ci.yml step that keeps the literal go run ./cmd/record-lint decisions-append "$BASE_SHA" and also hands BASE_SHA to a second, unguarded command (appended with &&, on a line of its own, or with the literal only in a comment or an echo) still earns the exemption, so the test stops asking that step to refuse the all-zeroes placeholder. Fix: the step earns it only when its whole run script is exactly an allowed gate invocation.
- iss-2609261121375292The reviews-charter gate passes three summaries the board reads as unpinned: scripts/check-reviews.sh RD001 tests the summary with [ -f ], which follows a symlink, while reviews.Read maps a symlinked 00-summary.md (fsutil.ErrNotRegular) to no pin; RD004 reads a summary of any size while reviews.Read caps it at maxSummaryBytes (1 MiB) and shows a larger one unpinned; and bash read drops a NUL byte from the frontmatter line, so a pin line carrying one passes RD004 while reviews.Pin refuses it. Each is gate-green and board-unpinned, the looser polarity; the gate should refuse all three so the board and the gate agree about every folder.
- iss-2609261121428530The status board's reviews heading tells the reader to 're-run those marked !' (internal/surface/cli/board_reviews.go), but on this repository every flagged row is a release receipt, which nobody re-runs: a receipt gates the release it names, RD002 forbids removing it, and every past release's receipt is permanently past the threshold. The imperative is untrue for a receipt, and the text render grows the bare board by one permanently flagged row per release. The receipt's staleness should be worded truthfully (the release it gated is N commits behind), the imperative kept for a dated review, and the text render (not --json) capped so past-release receipts collapse to one summary line.
- iss-2609261133371466record_schema skips a symlinked declared bucket silently: scanRecordStores (internal/core/lint/schema.go) tests e.IsDir() on the store root's entries, which is false for a symlink DirEntry, so a declared bucket such as open/ or resolved/ that is a link falls to the .md suffix test and is dropped with no finding. A forged record behind the link is not read (nothing out of tree is trusted), but the gate reports nothing about a whole lifecycle state it never checked, the same silent-skip class the seam finding closed. The reading walk and capture's allocator already refuse a symlinked open/ loudly.
- iss-2609261140284421A principle whose H1 title is written in setext form (the title line underlined with ===) travels to a reading without its title: principleTitleRe in internal/core/lint/principles.go:127 matches ATX headings only, so the projection sends the statement paragraph bare, and a cold reader gets a sentence with no name. Both readers agree, so no gate disagrees; the promise that a principle is readable cold does not hold for that file shape.
- iss-2609261152282753record_schema skips two symlink shapes in a record store with nothing said: (a) in a bucketed store, a symlinked entry at the store root with an undeclared name and no .md suffix (e.g. foo -> dir) is neither reported as an undeclared bucket nor read, because a symlink DirEntry is not a directory and falls to the markdown suffix test; (b) inside a declared bucket, or in a flat store, a symlinked subdirectory is skipped the same way, while a real subdirectory draws the undeclared-subdirectory finding. Either one hides a lifecycle state from every check. The sibling of iss-2609261133371466, which named only a DECLARED bucket that is a link.
- iss-2609261205176571scribe ingest's per-line state check splits the supplied dispositions on LF alone, so a text whose lines end in CR, U+2028 or U+2029 is one line and the check collapses to a whole-text test: '{0}: rejected ... CR {1}: accepted ... CR' wrote {0} accepted (probed by review2-scribe; CRLF is unaffected). lineCarries in internal/core/scribe/ingest.go must split on CRLF, CR, LF, U+2028 and U+2029.
- iss-2609261205178776scribe ingest's state check grants a state to every item a line names: lineCarries in internal/core/scribe/ingest.go reads the whole line that mentions the item, so a line such as 'rdi-2: accepted, unlike rdi-1' carries 'accepted' for rdi-1 too, and a payload filing rdi-1 as accepted passes the check the researcher's own line contradicts (probed by review2-scribe: {1}: accepted ... (unlike {0}) wrote {0} accepted). The state must be held to the part of the line that belongs to the item.
- iss-2609261205185463scribe ingest lists a run's reading items through a directory whose own link status it never judges: runItems in internal/core/scribe/ingest.go refuses a symlinked .abcd, .abcd/work, issues root or status directory through capture.RefuseRedirectedLedger, but a symlinked .abcd/work/issues/readings or run directory is followed by os.ReadDir, so the listing is drawn from outside the ledger (probed by review2-scribe: nil) where scribe assemble refuses the same link. The readings directory and the run directory are to be Lstat-refused by the primitive capture's own ledger walk uses.
- iss-2609261206436289The verification matrix's capture-resolve row says a note, an impact and grounds are all required, while grounds are optional and recorded when given (the v0.11.0 brief-surface cross-check's x-098, beside x-099 in the same row)
- iss-2609261206437257The site renderer links a repository file on the forge through a hard-coded blob/main path (internal/core/site/compose.go siteHref and seven sibling sites in compose.go, csl.go, explorer.go and graphpage.go), so a managed repository whose default branch is not main serves forge links that 404; the build reads no forge, and blob/HEAD names the default branch whatever it is
- iss-2609261208193041record_schema still passes silently over one link shape at a record store root: a link whose name ends in .md but does not match the record filename pattern (for example notes.md pointing at a directory). A real directory with that name is reported; the link is not, because telling whether it points at a directory would mean following it, which the walk never does. Reporting every link at a store root other than README.md, without following it, closes the shape.
- iss-2609261215159796abcd intent plan --bundle checks that no other record carries the bundle name against a corpus loaded before the intent mint lock and never re-checks it under the lock (internal/core/intent/bundle.go PlanBundle), so two concurrent plans of disjoint drafts under one name both succeed: four records name one bundle across two specs, the bundle lint passes, and each spec's close ships only its own pair. reclassify has the same shape at lower stakes: changeKind's 'named by another record' check and supersede's survivor set are computed from the pre-lock corpus, so a concurrent supersession of the only other member leaves a bundle of one with no history line.
- iss-2609261215160156abcd <spc-N> on a bundle's shared spec reads the first member alone (describeSpec in internal/core/record/record.go): Links names only the intent: back-link, the closed branch's 'stays planned until' and 'the linked intent is' lines read that one member, and the readiness gate runs on it alone, so member 2 is never mentioned and, after member 1 is superseded, the page names a superseded record as the linked intent.
- iss-2609261215168271The bundle spec close (reconcileBundle in internal/core/intent/bundle.go) pre-flights no destination, so a shipped/<name> collision on the second member moves the first member before the rename refuses; the rollback restores it byte-identical, but the doc comment's claim that every other refusal fires before anything moves is false. PlanBundle has the per-member Lstat pre-check this close lacks.
- iss-2609261218301461abcd intent plan writes a draft's kind from the corpus loaded before the intent mint lock (Plan in internal/core/intent/lifecycle.go reads it.Kind and it.SpecID from the pre-lock corpus while the bytes it rewrites are read under the lock), so a reclassify landing in the window that makes the draft a bundle-member is overwritten: the planned record carries kind: standalone beside bundle: <name>, a pairing no verb otherwise writes.
- iss-2609261218318807abcd spec close decides the impact stamp from bytes read before the intent mint lock (Reconcile in internal/core/intent/lifecycle.go and reconcileBundle in internal/core/intent/bundle.go call resolveShipImpact pre-lock, then write the stamp onto bytes read under it), so an impact recorded in the window by abcd intent plan --impact is overwritten by --impact instead of refused as a disagreement, and the record ships with a judgement it never carried.
- iss-2609261232176189abcd intent plan on a planned record with no spec (linkPlannedSpec in internal/core/intent/lifecycle.go) writes the record's kind from the corpus loaded before the intent mint lock while rewriting bytes read under it, so a reclassify landing in the window that makes the record a bundle-member is overwritten: the record carries kind: standalone beside bundle: <name>. The draft branch of Plan had the same shape (iss-2609261218301461); this is its in-place twin.
- iss-2609261232464351Operand paths in lifeboat (embark, pack, graveyard, synthesis) and the site output directory are proved with a single-level IsRealDir, so a symlinked ancestor of the operand is followed while the leaf check passes; the multi-level fsutil.EnsureRealDirAll / ProbeRealDirAll walk the inbox and the local tier now use is the canonical proof. Sweep each operand site: prove every level below the operand's declared base, or say why the operand is trusted as given.
- iss-2609261232477655ahoy install reports its status as clean while also printing a refusal note for a step, because a later step (the banlist scaffold) creates the local tier before the final status check runs, so the note and the status disagree in one run's output. The status should reflect every step's refusal, or the note should say the refusal was overtaken.
- iss-2609261241117925The forge list read holds no total across pages: internal/core/site/forge.go listAll reads total_count afresh on every page and never compares it with page 1's, so a list that shrinks between two page reads (page 1 total 150 serving entries 0-99, one entry deleted, page 2 total 149 serving the old 101-149) returns 149 entries with no error and the old entry 100 is never seen. If that entry is an existing environment, setup reads it as absent and on confirm PUTs the endpoint that replaces its whole protection set. The read should hold page 1's total and fail closed on a later page reporting a different one.
- iss-2609261241119343The capture write's --found-at refusals exit 1 though they are the caller's input with nothing written: internal/core/capture/foundat.go checkFoundAt returns plain errors for a path that leaves the checkout or does not exist in it, so abcd capture --found-at ../outside and --found-at does/not/exist.go exit 1, while commands/capture.md and brief 06-capture say a flag value outside its shape or naming nothing exits 2 on the capture write alike. They should unwrap to capture.ErrRequestRefused; a path that could not be checked for another reason is a fault reading the checkout and stays exit 1.
- iss-2609261241121312An unreadable ledger status directory reads as an unknown issue id: internal/core/capture/alloc.go findIssue continues past an os.ReadDir error, so with open/ unreadable (chmod 000) resolve, wontfix and defer print 'unknown issue id ... not found in any status directory' and exit 2, a refusal of the caller's input, when the ledger could not be read and the exit should be 1. The same swallow sits in issPresent (the mint's occupancy check reads an unreadable directory as holding nothing), checkOneStatusPerID (list and status read it as empty) and the orphan-placeholder sweep. An absent status directory stays tolerated; any other read error should be a fault.
- iss-2609261241126008The site's commit-history links still name the main branch: internal/core/site/explorer.go and graphpage.go build commits/main/ forge links, which 404 on a repository whose default branch is not main, while iss-2609261206437257's resolution says every forge file link names blob/HEAD. The history links should go through the same helper family and name commits/HEAD/, which the forge resolves to the default branch. Found while fixing it: the record page's link for a relative non-markdown target (explorer.go, the directory or file beside a record) builds <repository>/tree/main/ or /blob/main/ the same way, so it goes through the helper too.
- iss-2609261254247117relink.Repoint rewrites the link text in every record naming a moved path as a read-modify-write outside the intent mint lock, on every verb that moves a record (intent plan, spec close, intent reclassify): a concurrent edit to a linking record between the read and the rename is lost. The move itself is judged under the lock; only the repointing that follows it is not.
- iss-2609261312108500ahoy connect's provider-block write re-reads ~/.abcd/config.json under its lock with plain json.Unmarshal (internal/core/oracle/connect.go writeProviderBlockLocked), so a config.json that names a key twice, or two spellings of one, is collapsed last-wins and rewritten without the other spelling. LoadAPI refuses such a file through layered's jsonstrict walk before the call, but the rewrite judges the bytes it re-reads under the lock, and those it reads with the silent decoder: a file edited between the check and the lock is laundered. The sibling of iss-2609260120380520 on the credential store.
- iss-2609261325441711capture reframe's whole write reads a multi-commit rebase differently from a --no-ff merge or a squash of the same rewrite: two rebased commits that move the construal and then the glossary give changed=[glossary] with before at the post-construal state, where --no-ff and squash give changed=[construal glossary]. The first-differing-triple rule of spc-2609020626048705 produces it, and commands/capture.md and brief 06-capture.md claim only squash equivalence. Either a line on the page naming the rebase case or a spec ruling on what previous distinct state means across a rebased series; not decided here (review2-reframe OBS-A).
- iss-2609261327506636The drain's history-walk notice (internal/surface/cli/intent_drain.go, runOwedDrain) prints site.LoadHistory's error to stderr through termsafe.Sanitize alone, bypassing scrubPaths, so git's quoted stderr, which can name an absolute path inside the repository (a corrupt loose object is reported with the file it is stored in), reaches the terminal unredacted: the one print in the drain front door no redactor touches. Found by review3-drain as a nit.
- iss-2609261403493536mode.CanSet leaves a .mode-probe-* file behind forever when the local tier turns unwritable between the probe's create and its remove (a chmod during the hook's window, or a kill between the two): CanSet reports 'removing the probe' once, the file stays, and nothing ever sweeps it. Review2 of the badge lane reproduced it: 40 probes against a chmod-flapping tier left 7 probe files. Remedy: sweep stale probe files at the top of CanSet.
- iss-2609261412505956ahoy install drops the session store's failures silently: stepHistory (internal/core/ahoy/apply.go) ignores bootstrapHistory's error and historyRoot's, so a session store abcd could not create (a file where ~/.abcd belongs, or no HOME) leaves no note, against the ahoy brief chapter's rule that an install write it could not make is a note naming the file and the reason, never a silent omission (review2-ahoy item 1)
- iss-2609261423210391itd-135 ac-6 promises the Beta badge is absent at a v1 release with no copy change, but no test builds the site against a v1 release: internal/core/site/build_test.go asserts the badge at a 0.x release (line 1087) and its absence with no release at all (line 1138), so the v1 half of the criterion rests on isPreOne (internal/core/site/build.go:572) with nothing watching it. Wanted: a build test at a v1.0.0 release asserting no class="beta" span renders.
- iss-2609261423214723itd-138 ac-1 promises that the template under site-src/ that generates /install.sh also renders README's one-liner, so agreement between the two is structural. Delivered: README.md:106 carries a hand-written sh -c one-liner that nothing renders; TestInstallSurfacesAgree (internal/core/site/installsurface_test.go:158, reading README at line 308) holds it to the template's release prefix, checksum lookup and verifier by assertion, so a drift fails the build but the one-liner is still authored twice. Wanted: either the README block is rendered from site-src/install.sh.tmpl, or the intent's audit records the by-assertion form as the accepted narrowing.
- iss-2609261423222935itd-69 ac-1 and ac-2 promise a checker that runs with --tree public and --tree dev. Delivered: launch.CheckLockstep (internal/core/launch/lockstep.go:51) takes the tree as a Go parameter and has no front door — dry-run and ship call it with TreeDev over the source tree (internal/core/launch/dryrun.go:114, ship.go:80) and only the payload render calls it with TreePublic over its own output (internal/core/launch/render.go:444). A public checkout — a marketplace install, a release source archive — cannot be checked for manifest lockstep from the CLI or the plugin surface at all. Wanted: a read-only verb or flag that runs CheckLockstep with a chosen tree against a named root and exits with its 0/1/2 code.
- iss-2609261447331434ahoy offers trufflehog as an optional dependency (the deps.trufflehog_missing gap, 'trufflehog enables deep secret scanning when scan.deep=true', fix hint 'brew install trufflehog') although nothing in abcd runs trufflehog: no adapter exists and scan.deep is read by no scanner. The gap asks a person to install a tool abcd never uses, which the explain-then-install mode (itd-63) would turn into an executed install of a program that does nothing for them.
- iss-2609261447395216ahoy install asks 'Private repo + trufflehog present — confirm deep secret scanning' and persists scan.deep in .abcd/config.json, but no scanner reads scan.deep and nothing runs trufflehog, so the answer changes nothing: a person told they enabled deep secret scanning has not. Either wire a trufflehog adapter behind the scanner seam or stop asking (and say the value is inert where it is already set).
- iss-2609261454332615The identity gate reads the author as GIT_AUTHOR_* then user.name/user.email, but git gives the role-specific author.name/author.email config keys precedence over user.* (git 2.22+). A repo-local author.name = Test User therefore authors every commit as Test User while identity.EffectiveIdentity, ahoy's git_identity gaps, abcd ahoy --identity and the self-contained .githooks/pre-commit guard all report the pinned identity as matching. Reproduced with git 2.52: user.name Pin Human plus author.name Test User commits as Test User <pin@example.com>. The same precedence applies to the committer (GIT_COMMITTER_* then committer.name/committer.email then user.*).
- iss-2609261457353277itd-74 ac-5 promises the public family present after ahoy scaffolding; where the docs-lint config path is gitignored (TestPublicFamilyUnderPublicVisibility) install writes no public family and reports the gap as unresolvable, leaving that repo with no CI-enforced banned-names family
- iss-2609261457358637itd-74 ac-1 promises the public banlist gates README, docs/ and the shipped artefact; the banned_tokens family walks only the docs-lint roots (docs, README.md) and the payload render reuses those roots, so a banned public token in commands/, agents/ or skills/ ships ungated
- iss-2609261457365969itd-28 ac-1 promises review_of_commit written by the tool; no abcd path writes a dated review folder, so the pin is a charter-template obligation on the author whose absence RD004 refuses, and the narrowing was settled by the implementer in Decision 3 rather than by the product thinker
- iss-2609261457366568itd-2609212137128014 ac-5 promises halt-and-record on a gate refusal during a lab as a rule the verb enforces; the verb enforces it only for its own preflight and sweep gates and the harvest's citation gaps, while a refusal by the world's own gates during the mutate stage or a STOP condition is the discipline's rule with nothing mechanical behind it
- iss-2609261534097255implement receipt refuses the very receipt the awaiting lane named when the checkout is reached through a symlinked path: the CLI joins a relative receipt path onto os.Getwd (the symlinked spelling, e.g. /var/... on macOS) while the loop's root is git's resolved toplevel (/private/var/...), and loop.samePath compares the two spellings lexically, so the correct receipt reads as 'not at the path given' and the lane cannot advance. samePath should compare the real paths.
- iss-2609261536147903Planned intents and disciplines still cite specs of the retired predecessor store unqualified, and such an id at or below spc-70 resolves to a live spec on another subject (spc-12, for one, is live as the disembark grounding spec): itd-48, itd-50 and itd-53 name spc-12, spc-28, spc-29, spc-31, spc-33, spc-43 and spc-52 for the fidelity reviewer, lifecycle hook and cleanup work (which of these are predecessor ids is itself the reading this record owes); itd-24 names spc-66 as the phase-audit receipt; itd-1 and itd-37 name spc-12 as the manual reviewer. The specs charter (Two spc-N Namespaces) rules that every predecessor citation carries the '(predecessor store)' qualifier; iss-239 applied it to the draft corpus only. Each site needs a reading to tell a predecessor citation from a live one, which is why the sweep was not folded into iss-239.
- iss-2609261604485703The tool installer's 15-minute bound is not a bound: runArgv in internal/core/tools/install.go kills the step's own process group on timeout and then waits for cmd.Wait, which waits for the stdout/stderr copier; a descendant that re-groups (setsid/setpgid) survives the group kill, and if it holds the pipe the wait never returns. The comment claims the kill reaches everything the step started, and nothing in the code, the ahoy brief chapter or the command page names the re-group limit.
- iss-2609261604492132The gitleaks install explanation the person consents on says Homebrew 'sends nothing anywhere', which is untrue: brew install may first update its taps over the network, downloads the package, and by default sends Homebrew's install analytics. The Effects text is the sentence the install question is answered on, so it must state what the install does to the machine and the network.
- iss-2609261604498137The ahoy install 'changed:' line reaches the terminal unsanitised, and itd-63 put external process output on it: the verify program's first line (and a failed step's output tail) enters tools.Result.Output raw, flows through Summary() into the ahoy result's changes and notes, and cli.go prints the changes without termsafe, so an escape sequence or bidi control in a program's output rewrites the report.
- iss-2609261604499090The tool installer carries a second CI detector (internal/core/tools/install.go reads CI != "") beside the canonical one in internal/core/implement/load.go (ciRunner: GITHUB_ACTIONS=true, or CI other than empty, false or 0); the copy misses a runner that sets only GITHUB_ACTIONS, and two detectors drift. One primitive should serve both, with the installer keeping its stricter refusal of any non-empty CI.
- iss-2609261614268567The pre-commit identity guard (.githooks/pre-commit) reads the author and committer from git config only and never from GIT_AUTHOR_NAME/GIT_AUTHOR_EMAIL or GIT_COMMITTER_NAME/GIT_COMMITTER_EMAIL, which git ranks above every config key. A machine identity set in the environment, the shape a harness or CI runner uses, therefore commits past the only pre-commit enforcement in a pinned repository: GIT_COMMITTER_NAME=Claude GIT_COMMITTER_EMAIL=noreply@anthropic.com git commit lands a Claude committer with the hook exiting 0. git also exports the resolved GIT_AUTHOR_* to the hook, so git commit --author and git -c author.name get past it in the same way. The comment claiming the committer is held to the pin overclaims.
- iss-2609261614306830The Go identity reader (internal/core/identity/identity.go gitConfig) runs git config under gitutil.ScrubbedEnv, which drops GIT_CONFIG_PARAMETERS and the GIT_CONFIG_COUNT/KEY_n/VALUE_n form. git commit honours both, so under git -c committer.name=X (or author.name=X when abcd is not run from a hook) abcd ahoy --identity reports the configured identity as ok while git stamps X. This is the hook use commands/ahoy.md documents. The reader must see the configuration git commits with. The scrub's stated reason, stopping an injected GIT_CONFIG_* from forging the identity, does not hold for this reader: it already honours GIT_AUTHOR_*/GIT_COMMITTER_* from the same environment.
- iss-2609261614450166The redaction probe scanner.ProbeIdentity (internal/adapter/scanner/identity.go) builds the set of identities to redact from user.name/user.email plus GIT_AUTHOR_*/GIT_COMMITTER_* only. It never reads author.name/author.email or committer.name/committer.email, which git ranks above user.* for the identity it stamps, and it reads under gitutil.ScrubbedEnv, so a git -c user.name persona (GIT_CONFIG_PARAMETERS or the GIT_CONFIG_COUNT form) is never seen either. An identity that authors or commits the caller's work through any of those sources is missing from the matcher set and would be stored in clear. The fix folds them in as additional names to redact, the way the GIT_AUTHOR_* values are, so nothing displaces the configured identity. It is the same blind spot the identity gate had (iss-2609261454332615, iss-2609261614306830), on the redaction side.
- iss-2609261631120364The filing-time match reads an unreadable open/ or resolved/ ledger directory as an empty candidate set: capture/match.go matchCandidates discards scanLedger's result for the directory, and scanLedger treats any ReadDir error as an absent ledger, so a capture or intent create reports 'compared N' or 'no record to compare' instead of the unread outcome the intent store's own failure takes. The same absent-or-unreadable conflation makes capture list and capture status count an unreadable status directory as zero records with nothing in the skipped roster.
- iss-2609261631132673record-lint does not report an issue record the ledger reader skips for a value its schema check refuses: duplicates: [bogus] or blocked_by: [bogus] is lint-green while capture list skips the record and abcd <id> names the refusal. record_schema re-derives parts of the reader's judgement (required and unknown fields, the filename agreement) and misses the rest, though its store declaration states that a record the reader would refuse is not lint-green.
- iss-2609261631134401The closed spec spc-2609212141417782 says the filing-time overlap function is 'the one the embark ranking uses, moved to the record package' at internal/core/record/match.go. Neither happened: no embark overlap function existed, and the primitive shipped new, at internal/core/record/match (a sub-package, because record imports capture and intent). The closed record states a delivery that did not occur.
- iss-2609261636074260The build loop's worktree step proves each level of the machine-scoped worktree store (~/.abcd, worktrees, <root-sha>) a real directory through fsutil.EnsureRealDirAll but never applies fsutil.CallersAlone, so a pre-existing store level owned by another uid, or writable by group or other (mode 0777), is accepted and the lane's worktree is added into it, where another account could replace the checkout the implementer works in. Each existing level should be held to the caller-alone test the home-scoped declarations and the harness data directory use (iss-2609260057111315), and a level the step creates made 0700.
- iss-2609261636083314The build loop's brief step reads the intent, the spec, AGENTS.md, the decision log and the cited ADRs from the lane worktree's working tree while the brief labels them as read at the lane's base commit, so a brief re-rendered after the implementer edited or committed in the worktree quotes the implementer's tree under the base's label. They should be read from the base commit's objects, size-capped, so the brief always renders the base it names.
- iss-2609261636087420The worktree step's refusal of a malformed run id names the lane id in its lane field, and its refusal of a malformed lane id names no id there, so neither refusal names the id it refuses. Each refusal should carry the id it refuses.
- iss-2609261647358395A JSON string escape beside a secret or a home path hides it from the scanner's raw-line pass, and the transcript store scans raw JSONL. Every bundled token pattern anchors on a leading word boundary, so a token written straight after the \n, \t, \r, \b or \f escape (a GitHub PAT at the start of a line of pasted output, JSON-encoded) has the escape letter as a word byte before it and never matches: ScanText at BASE 211b8853 returns nothing for {"t":"tok\nghp_..."} while the same token after a space is token:github_pat. The identity matchers fail the same way: home_path_other finds no third-party home path that follows a \n or \t escape (the leading anchor reads the escape letter as a path byte) or that precedes a \n or \" escape (the trailing boundary set has no backslash), and a non-ASCII real_name written by an ASCII-only encoder (Python json's default \u00e9) never matches the configured name. The fix reads a line's JSON-decoded layers the way the percent-decode pre-pass reads its percent-decoded copy, mapping each hit back to its raw span. Detector: a token after a \n escape, a home path between \n and \" escapes and a \u-escaped real_name are each a finding on the transcript path.
- iss-2609261658553101The repolint privacy-hygiene rule and the harness_leak lint rule read each committed line raw, so the JSON-escape spellings the scanner reads through its decoded views (jsonescape.go) pass both: a third-party home after a \n escape, a home written with the solidus escape, a Windows home with doubled separators, and a token or a session URL written straight after a \n escape (the patterns anchor on a leading word boundary, and the escape letter is a word byte). A committed JSON fixture, export or transcript carrying any of them is not refused. Reading the views in the lint is not contained: Go interpreted string literals use the same escapes, so the views would surface every test string that puts a \n escape before a /home root and a name in committed Go source, and the waivers on those lines do not all exist. The CI gitleaks history scan covers the token half; the home-path and session-URL halves have no other gate. Detector: privacyLeak and harnessLeakOnLine report each of the four spellings on a committed line.
- iss-2609261659041553The literal caller-home backstop (SweepCallerHome and SurvivingCallerHome, internal/adapter/scanner/residual.go) reads the home only as written, so an escaped spelling of it is invisible to the one stage the store-before-commit redactors keep independent of the detector: the solidus escape (\/ between segments), its \u002f form, and a separator written as an escape run. Stage one and the stage-two rescan read those spellings through the scanner's JSON-escape views since fix/drain-scanner-identity, so a leak needs both detector passes to miss before the backstop matters; but the backstop exists for exactly that case, and against an escaped home it is not a backstop. Detector: with HOME under the /Users root, SweepCallerHome collapses the solidus-escaped and the \u002f spelling of the home to the tilde, as it does the literal one.
- iss-2609261659051539A short single-token real name in a JPEG's or TIFF's EXIF Artist tag (IFD0 tag 0x013B) is still dropped by the payload byte scan as chance noise. The byte scan keeps a short name only where a person metadata key stands as text within reach before it (metadataPersonKeys in internal/adapter/scanner/scanner.go: a PDF /Author, XMP dc:creator, a PNG text Author, an OOXML cp:lastModifiedBy), and EXIF stores the Artist tag as a binary IFD entry whose ASCII value sits at an offset with no key text beside it; a UTF-16 PDF string (/Author with a FEFF byte-order mark) is out of reach the same way. Closing it needs the IFD read structurally, the way container.go walks PNG chunks: find the Exif header, read the TIFF byte order, walk IFD0 and scan the Artist (and XPAuthor) value with the text rules. Residue of iss-2609090934372160. Detector: a short banned name in a camera-written EXIF Artist tag, with no XMP packet beside it, is a real_name finding in the payload scan.
- iss-2609261726015043record-lint's release-gate derivation reads CHANGELOG.md out of a git tree without a bound: changelogAt (internal/core/lint/releasegate_derive.go) runs an unbounded git cat-file blob and holds the whole blob in memory, where every other CHANGELOG read in lint and core/changelog is capped at 4 MiB (maxChangelogBytes, changelog.MaxChangelogBytes). TestLintReadsNothingUnguarded did not see it because its scanner names filesystem opens and reads only (os, io/fs, io/ioutil, an Open/ReadFile method); a file's content read out of git through gitutil.Run passes it. Found sweeping lint for unbounded record reads while integrating review2-match's pre-existing note (readBucket's first read, already guarded at this tip by b48fd584).
- iss-2609261737325810Review of integ4 reported that abcd capture defer prints 'ledger of <absolute cwd>' on stdout unscrubbed. Reproduced: the line is captureLedgerRoot's checkout banner (iss-2609202053570475), on stderr, printed by every capture verb and by the record dispatcher; --json carries the same identity as its ledger member. It is home-redacted through fsutil.RedactHome, so under the real HOME it reads ~/..., and it is absolute only for a checkout outside HOME, which is how the review's temporary-HOME scratch run saw it.
- iss-2609261753285273The rules root resolver's home exclusion compares path strings (root.go dir != home in the walk, top == home after it), so a HOME spelled as a case variant of the on-disk path (the home spelled with a lower-case first component where the case-insensitive APFS volume stores it capitalised) is not recognised: filepath.EvalSymlinks keeps the caller's case while git reports the on-disk case, and the version-controlled home is adopted as the repo root, its .abcd read a second time as the repo layer. Compare by file identity (os.Stat plus os.SameFile) through one helper at both sites.
- iss-2609261753290536The foreign-owner refusal note decides whether the working directory's .abcd is read with os.Stat, which follows a symlinked cwd/.abcd, while readRepoLayer Lstat-refuses a symlinked .abcd; in that edge the note tells the user the working directory's configuration IS read when the loader refuses it. Use Lstat plus IsDir so the note and the loader agree.
- iss-2609261811321435The linearity fixture json_unicode_escaped_own_homes in internal/adapter/scanner/meter_test.go is the literal home path, not its unicode-escaped spelling: the u002f escapes were folded back into slashes when the fixture was written, so TestScanLineWorkIsLinear never holds the JSON unicode-escape decode of a dense line of escaped homes to the cost bar its name claims, and the shape duplicates own_home_paths. Detector: the fixture's line carries the six-byte backslash-u002f escape, assembled so no tool can fold it again.
- iss-2609261827066511The payload byte scan never matches a value written as UTF-16 text behind a byte-order mark, whatever its length: a PDF text string that opens with FE FF (the /Author, /Creator or /Title of a document with a non-ASCII field) or a little-endian string that opens with FF FE interleaves a zero byte with every letter, so the caller's real name, home path and email in it raise nothing and the file publishes. This is the UTF-16 half of iss-2609261659051539, split from its EXIF half, which needs an IFD reader; it reaches long values too, not only the short names that record names. Detector: the caller's name, home path or email written as byte-order-marked UTF-16 in a skip-listed file is a hard_fail finding in the payload scan, and a short name there is kept only where a person key stands within reach, as in plain bytes.
- iss-2609261831352258A PDF text string written in hex (a FEFF-led run of hex digits between angle brackets) or with octal escapes (a backslash-376, backslash-377 opening inside parentheses), the forms several common PDF writers use for a non-ASCII document field, is read by neither the payload byte scan nor its UTF-16 view: neither spelling puts the UTF-16 bytes in the file, so the caller's name in such an /Author or /Creator raises nothing at any length. Reading them is a decode of the string syntax ahead of the UTF-16 view (hex pairs, and the PDF literal-string escapes), in the shape of the percent and JSON-escape views, not a format parser. Detector: the caller's name in a UTF-16 /Author written in hex or with octal escapes is a real_name finding in the payload scan.
- iss-2609261835118276The consistency ingest and the reading ingest copy host-delegated prose into lint-bound records with no prose-citation check: capture.IngestConsistency files each finding's summary, quotes and explanation as an issue record, and the reading ingest writes reading items into the rdi store, and both stores are read by record-lint's prose_citation_resolves, so a finding or item citing a record id that names no record is written and then refuses the whole tree. The verdict ingest holds its rendered block to the gate before writing (intent.SetProseCitationGate over lint.UnresolvedProseCitationsInRecord, iss-2609231036448320); these two writers take no such check. capture cannot import core/lint (lint's tests import capture), so the fix is the same front-door seam, asked over the text each writer renders.
- iss-2609261848326365The lifeboat verbs carry absolute directories into their --json and text reports: PackResult.Dest (disembark pack), EmbarkPlan and EmbarkResult LifeboatDir and TargetDir (embark probe, embark from), LessonsResult.LifeboatDir (disembark graveyard), and PrinciplesResult, PressReleaseResult and ReviewResult LifeboatDir (disembark principles, press-release, review). A lifeboat or target directory under the home names the developer, and the iss-81 rule is that machine output never carries a developer-identity path; the site verbs' OutDir fields had the same shape (iss-2608291957114882).
- iss-2609261848338673launch ship --json reports the release payload's destination as an absolute path in payload.dest, and the text report prints it on its payload line: PayloadRenderResult.Dest (internal/core/launch/render.go) is the symlink-resolved destination, so a destination under the home names the developer in machine output, against the iss-81 rule the site and lifeboat verbs are held to.
- iss-2609261850045839make preflight runs its Go steps (go build, go vet, go test, the race lane, and every go run and go test its prerequisites make) on the go found on PATH, which is go1.27.1 on this machine, while CI builds and tests with the toolchain go.mod declares (go 1.26.7) through setup-go's go-version-file. iss-2609081953452204 closed exactly this skew for gofmt alone, by resolving the format gate through the declared toolchain; the build and test half was left on PATH. On 2026-09-26 pull request 728 failed CI on a test whose assertion depended on the go 1.27 encoding/json error wording, after a clean local preflight: the push gate judged the tree with a toolchain CI does not use, so a green preflight vouched for nothing on that point. Fix: run preflight's Go steps under the declared toolchain, resolved by the same resolver the format gate uses rather than a second one, and refuse loudly, naming the skew, when it cannot be fetched, exactly as the format gate refuses. Detector: a test holding every Go step under preflight to the declared toolchain.
- iss-2609261900095459The reading floor admits a YAML alias used as a key in a frontmatter block, so an excluded key travels past the redaction under a manifest asserting its refusal. `k: &a origin` followed by `*a : X` (or `m: {*a : X}`) is admitted, and a YAML reader resolves it to {origin: X}. The anchor refusal in unresolvableFrontmatterShape fires only at line start or after a block indicator (nestedBlockEntry); an anchor in value or flow position is admitted, and nothing inspects `*` at all. Same class as iss-2608301237450573.
- iss-2609261905354450The reading status render probes an ingest stage's commit marker with an unbounded os.Lstat over the joined path, while its staged-runs probe reads through an os.Root over the repository. The two disagree on a symlink: with .abcd/development/readings symlinked outside the checkout, a stage whose run is parked makes Describe refuse (path escapes from parent), while a stage alone is classified as a leftover or an orphan by a marker read outside the repository. Both probes should go through the one root.
- iss-2609261909101409The UTF-16 byte view (internal/adapter/scanner/utf16.go, utf16TextRune) ends a run at a surrogate, so a character outside the Basic Multilingual Plane, an emoji written as a surrogate pair, cuts a byte-order-marked UTF-16 string in two, and a name after it is never read when fewer than two code units stood before the pair: an emoji, a space and a name behind a byte-order mark yields no view at all, while the same name before the emoji is found. Detector: the caller's name after an emoji in one byte-order-marked UTF-16 string is a real_name finding in the payload scan.
- iss-2609261909106167The private-banlist guard in .githooks/pre-commit reads every staged blob raw under LC_ALL=C, so a private name written with JSON string escapes passes it: a \uXXXX spelling of any letter, non-ASCII or plain ASCII, or a \/ inside a pattern, puts bytes in the blob that no ERE written for the plain spelling matches, and a JSON transcript, export or fixture is the natural carrier. The store-before-commit redactors and the lint rules read the scanner's decoded views (lineViews: the percent view and the JSON escape layers); the hook, the one enforcement point of the private layer, reads only the text as written. Detector: a keyed banlist entry for a fake name refuses a staged JSON file that spells the name with \u escapes or percent-encoding, exactly as it refuses the plain spelling.
- iss-2609261909108726A PDF text string written in hex, a FEFF-led run of hex digits between angle brackets, is not read by the payload byte scan: the hex spelling never puts the UTF-16 bytes in the file, so the UTF-16 view (utf16.go) cannot reach the caller's name in such an /Author or /Creator at any length. Reading it needs no escape grammar: the hex pairs decode to bytes with an offset map, and the decoded bytes feed the existing UTF-16 view. This is the hex half of iss-2609261831352258, split from its octal-literal half. Detector: the caller's name in a UTF-16 /Author written as a hex string is a real_name finding in the payload scan, and a short one is kept only where a person key stands within reach.
- iss-2609261924541555The macOS check job exceeds the merge queue's 30-minute cap once the cli lane's worked-example tests land: on PR #728 (integration head d850f06f) run 36262653588 was cancelled at 30.3 minutes while internal/surface/cli was still running under the race lane, where main's macOS runs take 23 to 28.5 minutes. The job's timeout-minutes equals the queue's check_response_timeout, so the queue fails the group rather than waiting. The cli package's test wall time, above all under -race, is the lever: it must come down by at least the three minutes the leg is over without weakening what the tests prove.
- iss-2609261935343851intent audit ingest is not under the intent mint lock: IngestVerdictBytes, reingestVerdict and deadLetter (internal/core/intent/audit.go) resolve the receipt, validate and write the shipped intent as a read-modify-write guarded only by a per-file atomic write, and deadLetter writes two files (the retained payload and the record); every other intent writer holds withIntentMintLock. Two concurrent ingests on one intent, or an ingest beside a condition disposition, each write the bytes they read: the later write erases the earlier one and both exit 0 (a verdict replaced while reporting a fresh ingest, or a dead-letter written over a verdict that had just landed).
- iss-2609261935407925The fidelity-review emit is not under the intent mint lock: emitAuditWith (internal/core/intent/audit.go), reached from the spec-close ship move, the bundle close, abcd intent audit and the audit drain, reads a shipped intent, parks the OWED stub and writes the record back as a read-modify-write outside withIntentMintLock. A condition disposition or verdict ingest landing on the same record between the emit's read and its write is erased, and both verbs exit 0.
- iss-2609261935407995intent.AddRelatedIssue (the intent half of capture promote --intent, any bucket including shipped/) and intent.Link (abcd intent link, planned/) rewrite the intent's frontmatter as a read-modify-write outside the intent mint lock (internal/core/intent/lifecycle.go): a hold, condition disposition, verdict ingest or review emit landing on the same record between the read and the write is erased, and both verbs exit 0. Every other intent writer holds withIntentMintLock.
- iss-2609261941039204capture migrate --apply rewrites intent records (the related_issues back-edge, any bucket including shipped/) under the ledger lock only, not the intent mint lock (internal/core/capture/migrate.go, Migrate): an intent writer holding withIntentMintLock (a hold, a condition disposition, a verdict ingest, a review emit, a related-issue edge) landing on the same record between migrate's scan and its write is erased. The intent package exports no seam for another package to take its lock, the same gap iss-2609261254247117 names for relink.Repoint.
- iss-2609261943168303recordid's filename grammar compiles a fresh regexp on every call: idRe (behind FilenameNumRe) runs regexp.MustCompile each time, and both per-file readers call it once per record file, the resolver's fileID in internal/core/recordid/resolve.go and peers' fileID in internal/core/peers/read.go. Every resolver scan and every peers scan, which the bare board runs on each render, therefore recompiles the same pattern once per record in the checkout: 29% of the CPU of the bare-board tests in internal/surface/cli, and several times that under -race, where it inflates the macOS check leg that iss-2609261924541555 records running past the merge queue's cap. The grammar is a pure function of a fixed family prefix, so one compiled pattern per prefix answers identically.
- iss-2609261950061900memory lint reports its run-log directory and the store it read as absolute paths: LintResult.ReportDir and LintResult.StorePath (internal/core/memory/lint.go) are joined onto the repository root, so memory lint --json carries report_dir and store_path naming the developer's home whenever the checkout sits under it, against the iss-81 rule; the text report prints ReportDir too.
- iss-2609261950066257The bare board reports its directory as an absolute path in machine output: abcd --json carries dir as filepath.Abs of the working directory (core.Status, internal/core/core.go, embedded in the board envelope by internal/surface/cli/cli.go), so a checkout under the home names the developer in --json, against the iss-81 rule the site and lifeboat verbs are held to. The text board prints the same field on its first line.
- iss-2609261950077063launch archive --json reports the archive it wrote as an absolute path: PluginArchive.Path (internal/core/launch/archive.go) is the --out directory made absolute by the front door and joined with the archive name, so archive.path names the developer's home whenever --out sits under it, against the iss-81 rule; the text report's written line prints the same value. Found in the drainPaths sweep of path-bearing --json fields.
- iss-2609261954288630launch --dry-run --json and launch ship --json name every payload file absolutely: IncludedFile.ResolvedPath (internal/core/launch/bundle.go) is the file's absolute on-disk path and is tagged resolved_path, so the bundle's files list in the dry-run report and in a ship's payload.bundle carries the checkout's absolute path once per file, naming the developer's home whenever the checkout sits under it, against the iss-81 rule. Found in the drainPaths sweep by running the read-only --json verbs from a checkout under the home.
- iss-2609262011046013The consistency review request carries no findings-JSON shape and names no place to read one. consistencyPromptBody in internal/core/intent/consistency.go states the five classes and the rubric, while the findings shape (_type, receipt_id, verifier, policy, and findings carrying class, severity, summary, explanation and two ends of path and quote) is published only in the Role 2 section of agents/intent-auditor.md, so a reviewer working from the request alone learns the shape from ingest refusals. It is the Role 2 sibling of iss-2609181121305984 on the fidelity review request, confirmed while fixing that record; the same remedy applies: the request states the shape rendered from the struct the ingest decodes, never a second copy.
- iss-2609262011091645The fidelity review request's delivered line still leaves the diff range to the host: auditPromptBody in internal/core/intent/audit.go writes 'the diff/commit range that realised ALL of spc-… (host supplies the range)', and an orchestrator hand-composes the base-to-merge range into the auditor's brief. This is the third addendum of iss-2609181121301638, left open when that record's scope-condition identities and criterion count were fixed, because it needs a design call the other two did not: the range is knowable from the specs' close commits and the merge commit, but a value read from git inside the hashed prompt body breaks the ingest's byte-for-byte prompt_hash recomputation unless the emit pins it (in the receipt marker, say), while a range stated outside the prompt, beside the Routing section, is unattested. Wanted: the request states the delivered range, attested or plainly marked as not.
- iss-2609262032177818ahoy's registerRepo returns silently when the session store's index cannot be read: loadHistoryIndex's error (an unreadable, oversize or malformed ~/.abcd/history/index.json) skips the repository's registration with no note, unlike stepHistory's three store failures, which each leave a note naming the store and the reason
- iss-2609262104070666The consistency ingest's refusal for findings whose policy hashes the request never issued tells the auditor to echo the two values the request's Provenance block states, and never names the re-emit. For a request emitted by an earlier binary (before the findings shape joined the prompt body) the auditor DID echo them, so the remedy it gives cannot succeed: the only way through is to re-emit with abcd intent consistency and run the pass again. The sibling refusal in the fidelity ingest (checkIssuedPolicy) names the re-emit; the two should share one derivation of that wording.
- iss-2609262107472569itd-53 fidelity audit: the press release promises a standing list of shipped intents whose latest fidelity review is missing OR not-met, and decision 2 names the owed listing as that report; the delivered listing (bare intent audit / itd-2609150819445595) reads the review marker state only, so an intent whose ingested verdict was NOT_MET reads INGESTED and leaves the list, and the unmet half survives only as the page-instructed capture per verdict (receipt rcp-d2372b1cb47f)
- iss-2609262123574454The implement loop's lane receipt reader (internal/core/implement/loop/receipt.go readReceipt) decodes the receipt strictly by hand, refusing an unknown field and a second document, but reads a repeated key last-wins: a receipt carrying "exit_code":1,"exit_code":0 (or a case twin such as EXIT_CODE) verifies as a passing definition of done. Every other trust-boundary JSON reader refuses a repeated key through internal/core/jsonstrict; this one was written before jsonstrict reached its base, so its strict decode is an inline copy that lacks the check.
- iss-2609262143209970An intent verb's link repoint (plan, spec close, bundle plan and close, reclassify, through repointUnderLock in internal/core/intent/lifecycle.go) rewrites every markdown record linking the moved path, issue and reading records included, under the intent store's lock alone: a ledger writer (a resolve, a link, a disposition) landing on a linking ledger record between the repoint's read and its write is erased, and the same holds for a spec record against a spec writer. The intent package cannot take the ledger lock (capture imports it), so closing this needs a registered ledger-lock seam taken OUTSIDE the intent lock (ledger, then intent, the order capture's transition and migrate take), and a stance on a tree with no ledger, which taking the lock would create.
- iss-2609262143265180abcd embark writes intent records into the target repository outside the intent store's lock (internal/core/lifeboat/embark.go: classifyEmbark judges each target path, then writeEmbark writes the set): an intent created at a path the classification found absent, between the classify and the write, is replaced without a conflict. The window is a same-id create during an embark, so it is narrow, but it is the one intent-record writer the drainL sweep found outside intent.WithMintLock.
- iss-2609262148072415memory lint's run-log report.md (renderLintReportMD, internal/core/memory/lint.go) renders a finding's file, message and suggestion through termsafe.Sanitize alone, so a page name or a pii.json pattern name carrying an HTML comment opener or link syntax reaches the markdown report live; the memory renderers fixed for iss-2609020539188868 and the lifeboat renderers fixed for iss-2609251355497247 route the same kind of field through termsafe.CleanProse and set a path off with termsafe.CodeSpan.
- iss-2609262156124513history reconstruct proves its --out directory with a leaf-only fsutil.IsRealDir (internal/surface/cli/history_reconstruct.go, writeReconstruction) and then writes the artefact and its telemetry by path, so an --out reached through a committed symlink above the leaf inside a checkout writes both files at the link's target; the lifeboat operands are proved against a symlinked ancestor with gitutil.ProveOperandDir (the operand-paths record captured on main after this branch was cut), and this is the same operand class outside lifeboat.
- iss-2609262211082803The reading-ledger capture verbs (disposition, admit, surprise, reframe) and capture mentions exit 1 on refusals of their own input, while capture migrate exits 2 on every fault: both contradict the capture page and brief claim that every refusal of a ledger verb's input exits 2 and exit 1 is left to a fault (iss-2609260552251398). Found when the drain1 lane met the reading-ledger verbs at the integ6 re-merge.
- iss-2609262218059995A capture transition's link repoint (repointMovedIssue in internal/core/capture/workflow.go) waits up to 5 s for the intent store's lock INSIDE the ledger lock, and the ledger's own acquisition budget (lockTimeout in internal/core/capture/alloc.go) is also 5 s, so an intent hold of 5 s or more makes a third process's ledger writer (a capture, a resolve, a link) fail with ErrAllocatorContention while the transition itself only reports a RelinkError. capture migrate --apply waits on the intent lock inside the ledger lock the same way. Bounded, not a deadlock: the two waits chain into a spurious failure on a slow machine.
- iss-2609262218306589abcd embark writes issue records into the target repository's ledger outside the ledger lock (internal/core/lifeboat/embark.go: classifyEmbark judges each target path, then writeEmbark writes the set): an issue captured at a path the classification found absent, between the classify and the write, is replaced without a conflict. The ledger-side twin of iss-2609262143265180, which names the intent half.
- iss-2609262218309668A link repoint rewrites spec records that link to a moved path with no spec lock, and no spec writer takes one either: the spec store's only lock is the mint's (withMintLock in internal/core/spec/store.go). spec.Close renames a spec open/ to closed/ while a concurrent repoint (an intent plan, a capture resolve) that read the spec at open/ writes it back there through an atomic rename, which lands the spec in both status folders; a spec edit landing between the repoint's read and its write is erased. Closing it needs a spec-store writer lock every spec writer takes, ordered against the ledger and intent locks.
- iss-2609262231500173reading assemble proves only a relative --out against a symlinked ancestor: writeArtefacts treats every ABSOLUTE --out as outside the repository (inRepo := !filepath.IsAbs(outDir) && ValidRelPath(rel)) and hands it to os.MkdirAll as given, so --out naming the checkout's own local tier absolutely, or climbing out and back in (../<repo>/...), is followed through a committed symlink at any level and the assembled input and manifest land at the link's target. Absolute is not outside; the sibling verb history reconstruct proves every spelling with gitutil.ProveOperandDir.
- iss-2609262235543552gitutil.ProveOperandDir documents an absolute operand but does not enforce it: handed a RELATIVE path, the .git marker walk stops at '.' and never reaches the checkout, so from a subdirectory of a checkout 'alink/x' with alink a symlink out of the checkout is ACCEPTED, and '../link/x' is refused naming the checkout '..'. Every current caller absolutises first, so the gap is latent; the function should absolutise its own input so no caller can bypass the proof.
- iss-2609262237352137The lifeboat markdown renderers' escapeLeadingMarker (internal/core/lifeboat/mdrender.go) leaves a leading left square bracket alone, so a principle, press-release subhead, body or quote shaped like `[label]: http://example.com` is emitted as a CommonMark link reference definition: the value itself renders as nothing, and a `[label]` shortcut reference in any other field (the cleaner breaks only the link-text adjacencies) renders as a live link to the attacker's destination. ideate's blockText already escapes the bracket for the same reason.
- iss-2609262237415400The lifeboat markdown renderers' escapeLeadingMarker (internal/core/lifeboat/mdrender.go) backslash-escapes a leading backtick unconditionally, the defect ideate's blockText was fixed for. termsafe's HTML-tag rule exempts a code span, so a value opening with a balanced span that quotes a details tag keeps the tag unbroken; escaping the opening backtick kills the span and republishes the tag as live inline HTML in principles.md or press-release.md, concealing what follows (the site renderer refuses the result as an unclosed code span). Only an unbalanced leading run opens a fence and needs the escape.
- iss-2609262241109876ideate's blockText (internal/core/ideate/render.go) escapes an ordered-list-shaped idea by putting the backslash before the digits, and CommonMark treats a backslash before a non-punctuation character as literal: an idea reading '1. first' renders as a backslash followed by '1. first', so the verdict record shows text the idea never had. The escape belongs before the '.' or ')' delimiter, as the lifeboat block escaper places it. Found while aligning the two block escapers.
- iss-2609262257227538The pair acquisition's ledger rest does not outlast the ledger writer's poll interval it was chosen to outlast. WithLedgerThenMintLock's comment says fsutil's lock-poll backoff tops out at 100ms and pairLedgerRest is 150ms to exceed it, but acquireFlock doubles the backoff after the sleep while it is below 100ms, so 80ms becomes 160ms and the real poll ceiling is 160ms: a ledger writer sleeping 160ms can miss the whole 150ms window the pair leaves the ledger free. No test pins the ceiling or the rest, so either can move and break the guarantee silently.
- iss-2609262259360005The kill-by-search and by-owner readings (iss-2609251640452031) left spellings of a kill by name or selector unseen. The ordinary ones are read on fix/drain-guard (4cc129009): a brace or paren group ({ pgrep make; } | xargs kill), a search inside a shell string (kill $(sh -c 'pgrep make')), a kill inside a shell string xargs runs or one that reads the pipe (pgrep make | xargs -I{} sh -c 'kill {}', pgrep make | xargs bash -c 'kill "$@"' _, pgrep make | sh -c 'xargs kill'), a kill behind xargs and an unknown launcher (pgrep make | xargs myrunner kill, now a Tier 2 warn), a selector value attached with a byte other than a letter or digit (pkill -tpts/3, pkill -ubob.smith), and pkill -Ubob or -Gstaff attached, read once pkill's signal word is read as a signal first.
- iss-2609262309556167The site renderer reads any block whose first line starts with three backticks as a fence, without the rule mdrecord's block walk applies: a backtick fence's info string may not contain a backtick. So a line that is a balanced code span, not a fence, is mis-rendered: '``` ```' and '```x```' render as an EMPTY command block (the value's text is lost), and '``` x ```' and '```` ``` ````' fail the whole render with an unsupported-construct error. The two block escapers that leave a balanced leading code span unescaped (termsafe.OpensBalancedCodeSpan, CommonMark-correct) inherit the defect: lifeboat's escapeLeadingMarker (introduced on this branch at 4df17e706; at f9b06e720 all four inputs rendered as paragraphs) and ideate's blockText, which has carried the same pre-existing shape since d4b825630. No injection (the info string is attribute-escaped) and no concealment of neighbouring fields. The root is mdrender's fence opener (render.go RenderBlock's first-line and per-line checks, and site compose's code-tab test) spelling its own opener instead of mdrecord's; the fix routes it through mdrecord's one opener predicate.
- iss-2609262322244502The site renderer's inline code span closes on the first occurrence of the opening run's text, not on a run of exactly the same length as CommonMark requires, and it trims every space from a multi-backtick span rather than one from each side. So a span opened by two backticks and holding a, three backticks, b (a CommonMark code span) is refused as an unclosed code span and fails the whole page; this record cannot quote the input literally, because the site renders every ledger record and would refuse it, and a span holding only a space renders empty. termsafe.OpensBalancedCodeSpan and mdrecord's findBacktickRun both pair runs by exact length, so a value a block escaper leaves unescaped as balanced can still be refused by the renderer: loud, not silent, and no text is published wrongly. Confirmed on a scratch copy while fixing iss-2609262309556167; the tree holds three code-span pairers (termsafe closingRun, mdrecord findBacktickRun, mdrender Inline) where one canonical primitive is wanted.
- iss-2609262342345159spec.Close on a tree with no spec store plants an empty .abcd/development/specs/ before failing 'not found': Close takes the store lock through withStoreLock, whose ensureDir creates the store to lock it, contradicting the rule the spec store states beside WithStoreLock (a verb that writes no spec must not plant an empty store). spec.Discard has the same shape. Unreachable through any in-tree verb today (both Close callers load the spec first), but the writer itself must not plant the store.
- iss-2609262350446885Two more code-span pairers than the three iss-2609262322244502 names pair backticks one at a time rather than by run. lint's stripInlineCode (GL002 synonyms, links_resolve, citations) pairs single backticks inside longer runs, so a span opened by two backticks reads as two empty spans with live prose between them: a glossary synonym quoted in a double-backtick span is flagged as live prose and a link quoted in one is checked, while a word between a single backtick and a double run no span holds is blanked. lab's parseCorrections closes a quoted literal on the next single backtick, so a retract literal quoted in a double-backtick span because it holds a backtick is read as empty and refused as noise. Both are loud or over-strict rather than silent. Found by the one-pairer guard while fixing iss-2609262322244502.
- iss-2609270028388291The kill-by-search reading loses a pipe that feeds a group or a command string from outside it. A pipe INTO a brace or paren group feeds every command in the group, but the tokenizer hands it only to the commands before the first separator inside, so a process search piped into a group whose later command is an xargs kill (after a sleep, a read, or an and-list) allows silently while the one-command group blocks. In the same class, payloadInput hands a command string only its running shell's pipe, so a here-string or a process-substitution redirect carrying a search into a shell string whose xargs kills allows, while the same redirect into a plain xargs kill blocks. Found by review-drainG2 (tokenize.go group open/close, payload.go payloadInput).
- iss-2609270028432249The xargs wrapper grammar in the guard lacks the BSD value flags -J, -R and -S, so on the macOS xargs a search piped into an xargs that uses one of them before a kill reads the flag's value as the launched command and warns as an unrecognised launcher instead of blocking as kill-by-search. Pre-existing; found by review-drainG2 (match.go wrapperValueFlags for xargs).
- iss-2609270036253187Two more paths by which a process search's output reaches a kill are not read by kill-by-search: an unquoted here-document whose body holds a command substitution, redirected into an xargs kill (a here-string of the same substitution blocks), and a command substitution inside a command that reads a pipe, which inherits that pipe as its standard input (an xargs kill in the substitution reads the search piped into its command). A third, a search handed to a shell string as a positional parameter the string's kill reads, is not read either: it is a pid carried through a variable, the half [dcn-2609250000000016](../../decisions/dcn-2609250000000016-correction-to-the-two-entries-above-on.md) (c) defers with iss-2609251824244354, unless it is read the way xargs's input to a string is ([dcn-2609270000000001](../../decisions/dcn-2609270000000001-the-kill-by-search-reading-follows-a.md)), which is a call for the next guard lane. Found while fixing iss-2609270028388291.
- iss-2609270036259517A stream piped into a brace or paren group reaches only the group's commands before its first separator as a stream, so a shell that reads its script from standard input placed after a separator inside a piped group allows under interpreter-reads-stream, while the same shell as the group's first command blocks. Same root as iss-2609270028388291 (the group's input is not handed to every command in it), found while fixing it.
- iss-2609280932480608An abcd-owned dangling PATH entry that sits EARLIER on PATH than the owned copy ahoy adopts is never repaired: install acts only on the adopted target (effectiveBinTarget skips dangling entries), so the symlink.dangling gap the earlier entry raises stays in Remaining on every run and ahoy install can never report clean. The install-time shadow note for it is also wrong in two ways: it says the dangling link 'is what runs when you type abcd' (a link that resolves to nothing runs nothing; the shell skips it) and ends 'abcd never clobbers a binary it does not own' about an entry it classifies as its own. Reproduced (lane drainH, 2026-09-28): a stranded plugin-update link in one PATH directory ahead of a one-liner-installed owned copy in ~/.local/bin, on a warm cache and on a cold one; the warm-cache half is the same at base 0f9d652a. Needed: decide whether install removes an owned dangling entry that is not its target (it destroys nothing, and uninstall already removes owned entries), and give the shadow note owned-entry and dangling-entry wording.
- iss-2609280944560197The pre-commit name guard decodes one JSON escape layer per run of backslashes and never re-reads its own output, so a backslash spelled as the unicode escape of U+005C (or as %5C) decodes to a literal backslash that is not read again as an escape: a banned name hidden one layer behind such a backslash (the escaped backslash followed by u0075 and the rest of the name) commits, while scanner.DecodedViews reads it through its second layer (maxJSONDecodeLayers is 3). The carrier is a hand-crafted file, since no mainstream encoder writes a backslash that way; the hook comments claim the guard reads what the scanner's redactors read, which overclaims by exactly this case. Both hook copies (.githooks/pre-commit and internal/core/ahoy/defaults/pre-commit) carry the decode.
- iss-2609280945018822The pre-commit name guard's awk decode of escaped spellings is superlinear in LINE length on macOS awk 20200816: 19 MB of escaped JSON over 105k lines decodes in 1.9 s, but the same bytes as one line take 65 s in awk and 88 s for the commit (the verify of fix3-drainS3). A minified single-line JSON export or asset pays it; the hook still completes and reports, so it is never silent. Both hook copies (.githooks/pre-commit and internal/core/ahoy/defaults/pre-commit) carry the decode.
- iss-2609281017573862The ~/.abcd/path-entry and cache-attestation readers do not refuse a symlinked ~/.abcd, unlike the rules loader: fsutil.ReadDeclaration lstats the FILE (regular, this uid, not group- or other-writable, O_NOFOLLOW re-open) but follows a symlinked parent directory, and the hook shims' find -maxdepth 0 -type f -user ... ! -perm -0020 ! -perm -0002 check likewise follows the parent. The two readers agree with each other, but AGENTS.md states the rules.json rule as refused behind a symlinked ~/.abcd, so a dotfiles-symlinked ~/.abcd hosts a path-entry record that vouches for which binary the hooks run while the rules loader in the same home would refuse its rules.json. Found by review-drainH (LOW, pre-existing, shared with cache-attestation); related to iss-2609260958587561 (the credential store's copy of the same gap) but not covered by it.
- iss-2609281045487620A file named in a docs-lint or record-lint config's roots that is not markdown is read as nothing and reported clean: the per-root walk keeps only .md files, so a root such as .abcd/rules.json passes the does-not-exist check, contributes zero documents, and every rule the config arms reads none of it while the lint exits 0. Confirmed by a test on a scratch copy (roots [docs, rules.json] with a ban matching the JSON: no finding, no error; DocumentsInRoots counts it as zero). Found while widening the role ban past the documentation, where the spec's 'roots widened to .abcd/rules.json' would have silently checked nothing. Wanted: a non-markdown file in roots is a configuration error that points at a token's extra_roots, the way a missing root already is (GitHub #360).
- iss-2609281129171021The ahoy history registry (~/.abcd/history/index.json and its lock) is created and written through a symlinked ~/.abcd: historyRoot joins the home directory and withHistoryLock and bootstrapHistory call os.MkdirAll, which follows the link, so on a machine whose ~/.abcd is symlinked into a dotfiles checkout the registry of every managed repository, remote URLs included, lands in that repository. Its sibling stores refuse a symlinked level through their create-then-prove seam (transcripts, voyage, lab, inbox, runs use fsutil.EnsureRealDir/EnsureRealDirAll/IsRealDir), and every file abcd trusts in ~/.abcd refuses the link through fsutil.HomeScopeLink (iss-2609281017573862, iss-2609260958587561). The registry is a store, not a trust declaration, and refusing it changes ahoy install's registration on such machines, so it was left for its own ruling: route it through fsutil.EnsureRealDirAll on ".abcd/history" below the home directory and say what the install does when the registry cannot be created.
- iss-2609281134544802The shell guard reads a parameter expansion as an unknown word (iss-2609251824244354, lane drainG3) for the flags and program names its value can spell, but not as data an earlier command carried into the variable, and four classes stay unread: (1) a pid list a search printed into a variable (p=$(pgrep make); kill $p, or pgrep make | while read p; do kill $p; done), the plain-variable half [dcn-2609250000000016](../../decisions/dcn-2609250000000016-correction-to-the-two-entries-above-on.md) (c) parked on iss-2609251824244354; (2) a stream path in a variable handed to a shell or source as its script (bash "$f" after f=<(curl ...)); (3) shell text a variable holds, run through eval "$X", sh -c "$X", or placed in a string a shell runs, whose value may hold a separator or quotes (eval "$X" allows, as it did before the reading); (4) pkill or killall as a variable's value standing as the program with an operand ($P make), and a variable-named bare interpreter inside a string. Reading each would refuse ordinary commands: the false-positive sweep of 4,315 inputs showed 22 new program-name-unknown blocks ("$GO" build, exec "$BIN", $EDITOR notes.md) and 15 new interpreter-reads-stream blocks (bash "$SCRIPT") before these readings were left out. Classes 1 and 3 carry the same cost, from the sweep's everyday-variable lines, each of which allows today: a reading of class 1 cannot tell a pid a search printed from one the script recorded, so it would refuse kill "$pid", kill -TERM "$PID" and kill -- -"$pg" (a background job's pid, a pidfile's, a process group's); a reading of class 3 cannot tell a hostile string from a composed one, so it would refuse eval "$cmd", the line that runs a command a script built up. Each class is a block, warn or allow call the product thinker has not ruled on.
- iss-2609281204381700The implement loop's run-state reader, readStateIn in internal/core/implement/loop/state.go, decodes state.json with DisallowUnknownFields only: a repeated key is read last-wins (encoding/json binds case twins to one field too) and anything after the first JSON document is ignored, so a file that is not the one the loop wrote can pass as the run's state. state.json lives in the primary checkout's .abcd/.work.local/run/<id>/, the directory an implementer is sent to write into, and the loop reads lane status and each lane's awaited receipt path from it. The lane receipt reader was fixed for the same class (iss-2609262123574454) by routing it through jsonstrict.Decode; readStateIn should take the same one primitive, with a repeated key and a trailing document each refused under test.
- iss-2609281229109140The append primitive's symlinked-leaf refusal has a race: fsutil.openAppendIn opens through os.Root, where O_NOFOLLOW is inert (os.Root follows an in-root leaf symlink on ELOOP), so the refusal rests on the pre-open Lstat and the SameFile check against the opened descriptor, and SameFile is skipped when the pre-open Lstat saw nothing. A symlink planted between an ENOENT Lstat and the open is followed and appended through; the comment claims every open carries O_NOFOLLOW as though that refused it. Needs a same-uid racer in a microsecond window.
- iss-2609281310017733The symlinked ~/.abcd rule is enforced by path, not by descriptor, so a same-uid race can still slip a link in between the check and the use. fsutil.HomeScopeLink Lstats each directory below home (internal/fsutil/home.go), and the reader then opens the file by its full path (ReadHomeDeclaration, then ReadDeclaration's own Lstat, open and SameFile), while the writers check and then MkdirAll, lock or create by path (credential.SetMachine, oracle writeProviderBlock, ahoy writePathEntry, writeMachineRouting, wireStatusLine, and the history registry's EnsureRealDirAll after historyRoot). A process running as the same uid that swaps ~/.abcd for a symlink after the Lstat reads or writes through the link. It is the same residual the rules loader's Lstat carried, and it needs the caller's own uid, so it widens nothing an attacker at that uid could not do directly; it is recorded so the rule's guarantee is stated at the strength it actually has. os.Root would not close it: it follows a symlink that stays inside the root, and a dotfiles ~/.abcd usually points inside home. The airtight form uses only the standard library (syscall on darwin and linux, no new dependency): open home, then syscall.Openat(homefd, ".abcd", O_DIRECTORY|O_NOFOLLOW), then Openat(dirfd, leaf, O_NOFOLLOW) (O_CREAT with O_EXCL or O_NOFOLLOW for writers, Mkdirat for a missing level), and judge and read or write through those descriptors. Left open by the fix round that routed every reader and writer through HomeScopeLink (branch fix/drain-symlinked-home); not built there.
- iss-2609281314564762The two CI gate scripts test membership and matches by piping printf into grep -q under set -o pipefail, and that pipeline is a race whenever printf needs more than one write: grep -q exits at its first match, printf's next write takes SIGPIPE, the pipeline returns 141, and the test reads as no match. Under load the race loses at a few KiB; past one pipe buffer (64 KiB) it loses every time. Measured: a 50 KiB id list missed 0 of 30 runs and a 70 KiB one 30 of 30; a here-string missed none. In scripts/check-issue-resolution.sh the RS001 membership test against the ids entering a terminal folder, RS004's declared-id test, and RS005's shipped test all take this shape, so two full-history runs of the gate over the same range at the same commits differed by 47 violations (39 RS001 refusals of records that did enter resolved/, seven RS004 refusals of ids a 190-line Refs: block declared, one RS005), and the base-listing membership test the lane adds for iss-2609012047551175 would read a record terminal at the base as absent on a real ledger, failing open. In scripts/check-attribution.sh check_text pipes a whole commit message or pull-request body into grep -q for the tool-footer, Co-authored-by and trailer checks, so a body longer than the buffer whose banned line is matched before the last write can pass. Fix: feed grep from a here-string, which bash writes in full before grep reads, so no writer is left to take SIGPIPE.
- iss-2609281329007423A checkout, worktree or store path outside HOME is printed whole by the surfaces that redact through fsutil.RedactHome alone: RedactHome turns a path under HOME into ~/rel and leaves every other absolute path untouched, so a sibling worktree in /private/tmp or on another volume reaches abcd peers (--json path, not_read, skipped, the peer-held refusal), the implement check's contention detail, history ingest's destination and orphan cwd, and implement status's lane worktree as a full local path in output a person pastes elsewhere. The display rule that fixes it (under HOME the home-relative form, outside HOME the directory's base name) is stated inline twice, in scrubPaths and in the capture verbs' ledgerIdentityOf, and in no primitive a new surface can reach, which is why each new surface re-derives RedactHome alone.
- iss-2609281514435020The merge queue fails a group whose macOS check job runs past 30 minutes, cancelling pull requests whose code is fine: #728 was cancelled at 30.3 minutes, #730 twice at the cap, and #733 once. The check job's timeout-minutes and the main ruleset's merge-queue check_response_timeout_minutes are both 30, while the macOS leg of a source change measures 23 to 30 minutes, so ordinary runner variance cancels a passing run, and nothing warns before the cancellation arrives. Ruling Z (2026-09-28, the technical facilitator) raises both limits to 45 minutes and asks for a warning once the macOS check passes 35 minutes, so a speed lane opens before any cancellation.
- iss-2609281546130900Every scanner.New spends four git execs reading the caller's identity: ProbeIdentity (internal/adapter/scanner/identity.go) runs git config --get-all user.name, --get-all user.email, -z --get-regexp over user/author/committer name and email, and --get remote.origin.url, each a separate process under the scrubbed env, although the first, second and fourth read the same configuration the third lists. The review of the ciFast lane counted about 2,193 such execs per cli test run; the cost lands on every CLI verb and hook that builds a scanner. One NUL-delimited listing under the same env yields everything the four did.
- iss-2609281613094952The status board prints the checkout's absolute path with no redaction at all: core.Status sets Dir to filepath.Abs(cwd) (internal/core/core.go:46), bare abcd renders it raw as its first line ('abcd — <dir>', internal/surface/cli/cli.go:285) and abcd --json carries it whole as dir. Under HOME it prints /Users/<account>/..., and outside HOME the full path, in the output a person pastes most often. The board should name the checkout by the display rule fsutil.DisplayPath states (home-relative under HOME, the directory's base name outside it), the sibling of iss-2609281329007423, which routed every other checkout and worktree display but not this one.
- iss-2609281627055603The reading corpus's exclusion floor closes its frontmatter block earlier than the canonical reader: blockCloser (internal/core/reading/project.go) closes on any column-0 line opening with three dashes, so a column-0 `----` or `--- x` ends the floor's block while frontmatter.IsDelimiter, frontmatter.Fields and a YAML reader read on to the real `---`. The keys between the two closes are frontmatter to the canonical reader and invisible to excludedKeyInFirstBlock and unresolvableFrontmatterShape, so an excluded key there reaches the corpus under a manifest asserting its refusal. Probe: a block opened by `---`, holding `foo: 1`, then `----`, then `secret: x`, then `---` — floor close is line 2, canonical close line 4, Fields reports secret, and excludedKeyInFirstBlock does not refuse it. The allowlist reason in delimiter_canonical_test.go (the floor 'refuses more, never less') is false for this shape.
- iss-2609281654467661The macOS keychain home's write and read have never run against the real security tool. Set stores a value through 'security -i' with the value hex-encoded behind -X on one stdin line (internal/core/credential/keychain.go), and Resolve reads it back with find-generic-password -w; a MaxValueBytes value (4096 bytes) makes that line about 8 KiB. Only the test binary's fake keychain (store_test.go TestMain) has proven the -X in, -w out round trip. If security's non-terminal line reader splits or truncates a long line, the read-back check after the write refuses loudly and echoes nothing, but a wrong item stays in the keychain for the person to remove by hand. One real-machine round trip is owed: a value of MaxValueBytes set through the keychain home, read back byte for byte, then the item removed. Surfaced by the review of the credential store lane (review-cred finding 5, unverified).
- iss-2609281715083637The macOS check spends time the tests do not need in two places. Every atomic write the tests make flushes to stable storage (fsutil's WriteFileAtomic family and the history-index bootstrap call File.Sync, which Go runs as F_FULLFSYNC on macOS, about 8.8 ms per synced write on this disk), though no test asserts anything a flush makes true; and the race step names ./internal/... in import-path order, so go test starts internal/surface/cli, the slowest package under -race, among the last on the three-core runner and the step waits on it as a tail.
- iss-2609281736483740The status board's first line prints the checkout's display name without termsafe.Sanitize, while every other board value is sanitised. Bare abcd writes 'abcd — <dir>' from fsutil.DisplayPath(st.Dir) straight to the terminal, so a checkout whose directory name carries an ESC sequence or a bidi control (U+202E) reaches the terminal raw: a crafted clone directory can recolour, retitle or reorder the board a person reads and pastes. Named FOR THE REVIEWER by fix2-drainRedact after it routed the line through DisplayPath.
- iss-2609281911015826itd-63 criterion 4 (the safety gate's missing-scanner case routes through the explain-then-install mode) is NOT_MET at ceb4b6dbb: no safety gate exists on main, itd-62 (pluggable-safety-gate) is still in intents/drafts/, so nothing surfaces the prerequisite the criterion names. The spec's close note substitutes the history store's armed-gitleaks refusal (internal/core/history/history.go calls tools.Missing), which is transcript capture, not the gate. The shipped record names a first consumer that does not exist; when itd-62 is planned its missing-scanner path must call tools.Missing/tools.Install rather than print a bare command, and itd-63's References/Why should stop asserting that the safety gate already blocks on a missing scanner.
- iss-2609281911024185itd-2609212137116617's press release says a new issue is matched against the record at filing, but only the capture verb and the quoted-text intent create run the filing-time match. The ledger's other writers file without it: inbox promote builds a capture.CaptureRequest with no Match (internal/core/report/inbox.go captureRequest), and IngestConsistency and IngestReading (internal/core/capture/consistency.go, reading.go) write issue records outside matchAndLink (internal/core/capture/workflow.go). The unattended paths the intent's Grounds name as the reason for the match are exactly the ones that skip it, so a double promoted from a peer report or filed by a consistency pass is never linked at filing. Either these writers pass the layered match config through CaptureRequest.Match, or the record narrows its claim to the two verbs.
- iss-2609281911024838itd-63 criterion 2 diverges for gh: the explain-then-install mode's install half is offered for gitleaks alone. ahoy.DependencyTools is {gitleaks} (internal/core/ahoy/detect.go), so ahoy install never puts gh to the question and --install-tool gh is refused by installToolNames (internal/surface/cli/cli.go), while ahoy remote and site setup refuse a missing gh with tools.Missing (internal/core/ahoy/remote.go) and show the Homebrew step the person must then run by hand. A required tool the registry knows how to install is explained but never installed on a yes, so for gh the criterion's 'the install runs only on an explicit yes' never arises. Either a gh dependency gap joins DependencyTools (offered only when a verb that needs gh is in play), or the record states that the mode installs gitleaks only.
- iss-2609281931185016ahoy's stepRules (internal/core/ahoy/apply.go stepRules) writes the empty .abcd/rules.json skeleton through writeRepoJSON (an atomic rename, no re-check) after the interactive prompt phase, so a rules.json written after detection set rules.missing (detect.go) is replaced by the empty-domains skeleton and the receipt says it wrote rules: a silent loss of a hand-written override, with the whole prompt phase as the window.
- iss-2609282105240081`abcd banlist list` with no flags prints output byte-identical to bare `abcd banlist`, the alias shape the naming chapter (02-constraints/04-naming.md) forbids, and no exception lists it. Found by the v0.11.1 crosscheck (x-115); sub-verb registered at v0.11.0.
- iss-2609282105240689The bare `abcd lint` help (commands/lint.md frontmatter, abcd --help, docs/reference/cli/commands.md) says it checks the conventions with every target included, but repolint.DefaultRules excludes the outbound target, so a reader believes the bare run checks outbound text when it does not. Found by the v0.11.1 crosscheck (x-045); same text at v0.11.0.
- iss-2609282105241960`abcd update --json` on the absent refusal prints the dispatch-refusal receipt (with an empty origin key, update.Report's Origin has no omitempty) and then the root error envelope: two JSON documents on stdout where a machine reader expects one. Found by the v0.11.1 crosscheck (x-051); unchanged since v0.11.0.
- iss-2609282105242542The guard's bundled registry (internal/core/guard/defaults/guard.json) has one rm entry, rm-rf-after-cd-chain, so a bare `rm -rf *` or `rm -rf /` checked with `abcd guard check` returns allow and exit 0, while the guard chapter's headline promises the catch. Found by the v0.11.1 crosscheck (x-047); registry unchanged since v0.11.0.
- iss-2609290000171068itd-2609212130146198's press release promises that an agent cannot ask the human anything until it has said whom it is asking, but the delivered guard (criterion 2) covers only the host's question tool: a stop that asks in prose at the end of a turn is not gated, so the badge can still read abcd-managed while an answer is owed, which is the Mechanism's own falsifier. The intent's scope confines the guard to the question tool, so the press release overclaims; either the promise narrows to the tool or a stop-time gate closes the prose path. Found by the fidelity audit at 52c2236a5 (internal/surface/cli/guard_question.go questionTools).
- iss-2609290033521472Host-payload refusals outside ideate still quote the refused value into the error text. Found on the sweep for iss-2609090951295881, which fixed the six ideate sites: lifeboat synthesis_review.go quotes an out-of-set mode, prompt_version and verdict with a bare %q (no redaction, no sanitising beyond Go quoting); intent audit.go quotes an out-of-enum criterion verdict, a malformed criterion id, a _type and a receipt id the same way (its dead-letter RECORD is redacted, the returned error is not). Each field arrives in a host-composed payload beside free text the verb does redact, so a token or home path pasted into a closed-set field is printed verbatim to the terminal and transcript on refusal. The reading ingest routes its quoted values through echo(); whether that redacts or only bounds is unverified. Fix direction: the ideate describeRefused shape (length, never the value), shared rather than copied. Detector: for each payload verb, a closed-set field carrying a sentinel must be refused without the sentinel in the error.
- iss-2609290043245353The reading ingest's refusals echo payload-chosen values unredacted. echo() in internal/core/reading/ingest.go cleans a value (termsafe.CleanProseLine) and caps it at maxEchoedBytes (120), but runs no privacy redaction, and 17 call sites use it: the output's _type, run_id, manifest_sha256 and position among them, beside values the manifest (abcd-written) supplies. A reading output whose closed-set or id field carries a token or a home path is refused with up to 120 bytes of it in the error, which reaches the terminal and the transcript. Found on the sweep for iss-2609290033521472, which fixed the same shape in lifeboat review and intent audit with termsafe.DescribeRefused and the audit redactor. Fix direction: per site, describe a payload value (DescribeRefused) or route it through the reading's own payloadField redactor (redact.go), leaving manifest-sourced values as they are. Detector: a reading output carrying a sentinel in each quoted field is refused without the sentinel in the error.
- iss-2609290055092630fsutil.RedactRoot and the scanner's home sweep still disagree on the LEADING boundary for a home of two or more segments under a longer root: SweepCallerHome sweeps '/Volumes/T7/srv/qzhome/x' to '/Volumes/T7~/x' (iss-324: a longer root does not make the name someone else's), while RedactRoot, and so RedactHome, the CLI error scrub and the install receipt, leave it whole because the byte before the root is a path-segment byte (iss-2609230641546141 chose that to stop '/private~/wt/a' mangles). The identity survives in CLI output wherever a message names a home under a backup volume or mount. Closing it needs a choice between the two rules for the '~' polarity (the '.' repo polarity has no counterpart); found while unifying the trailing half under iss-2608292037564347.
- iss-2609290144116254The intent consistency ingest's refusals echo payload-chosen values unredacted. validateConsistency in internal/core/intent/consistency.go quotes the findings payload's _type with a bare %q (line 804, the same shape iss-2609290033521472 fixed in the audit ingest), and quotes a hash value (873), a finding's class and severity (938, 941), an end's path (993) and quote (1000) through oneLine, which cleans and caps but runs no privacy redaction. Each refusal returns to the surface, so a token or home path pasted into one of those fields reaches the terminal and the transcript. Found on the sweep for the audit.go _type fix (fix2-drainSec). Fix direction: describe a closed-set value (termsafe.DescribeRefused) and route path and quote through the verdict-prose redactor, deciding per site whether the echoed value is needed to find the fault. Detector: a findings payload carrying a sentinel in each quoted field is refused without the sentinel in the error.
- iss-2609290218032954Four more host-payload ingests echo payload-chosen values into their refusals, cleaned but never redacted: the class iss-2609290043245353 and iss-2609290144116254 fixed in reading and intent consistency. (1) scribe ingest (internal/core/scribe/ingest.go) passes 21 values through its own echo(), which sanitises and caps but does not redact: the output's _type and run (177, 180), an undeclared key (343), a disposition's item id, state and free text (481-516), among them. (2) release changelog ingest (internal/core/release/ingest.go) quotes next_tag (328), an out-of-set section (532) and a malformed record id (560) through termsafe.Sanitize alone, and the section is uncapped. (3) Five strict decoders return encoding/json's message raw, which names an undeclared field by the payload's own key: ideate record.go:248, lifeboat graveyard_lessons.go:83, synthesis_pressrelease.go:157, synthesis_principles.go:217, synthesis_review.go:275 (release ingest.go:478 sanitises the same message). A token or a home path in any of them reaches the terminal and the transcript. Fix direction: per site, describe a closed-shape value (termsafe.DescribeRefused), redact a name the reader needs through the canonical scanner, keep a value abcd wrote. Detector: each payload carrying a marker and a home path in each field is refused without either in the error.
- iss-2609290259108077The credential store's working-tree check misses a home directory that is itself a symlink into a git checkout. workingTreeAbove (internal/core/credential/store.go) climbs the lexical path of ~/.abcd, so when HOME is a link such as ~ -> <repo>/home, the target's parents (<repo>/.git) are never examined; Set with the abcd home then writes credentials.json, a value, inside the checkout, where a commit could carry it. The dotfiles layout AGENTS.md names (a symlinked ~/.abcd) is refused already; this is the account's own home layout, same uid. Judging the tree on the home's resolved path (filepath.EvalSymlinks) as well as its lexical path closes it without refusing a home for being a link. Surfaced by the security review of integ/land-14 (review-integ14 LOW (a)).
- iss-2609290300313698The credential index can split between two ~/.abcd directories under a same-uid swap of one real directory for another between Set's walk and the index's re-walk. Set opens ~/.abcd once by descriptor and writes the index through that held root (store.go setIndex, WriteFileAtomicInRoot), but readIndex under the index lock re-walks ~/.abcd by path (fsutil.ReadHomeDeclarationDenying). If ~/.abcd is renamed aside and a different real directory swapped in between the two walks, the index read comes from the new directory while the write goes to the held one: the held directory's index becomes the new one's entries plus the new name (its own entries lost), and the live ~/.abcd does not record the new name. Names, homes and pointers only, never a value: SetMachine re-walks for its read and its write, so the value and its store stay together in the live directory. Same uid, who can edit either file directly. Surfaced by the security review of integ/land-14 (review-integ14 item 4, LOW (b)).
- iss-2609290300462829The implement loop's lane receipt refusal returns the strict decoder's message raw, the class iss-2609290218032954 fixed in scribe, release, ideate and lifeboat. The receipt is written by the implementer agent, so it is a host payload, and internal/core/implement/loop/receipt.go:179 formats jsonstrict.Decode's error with %v: an undeclared field or a repeated key is named by the receipt's own spelling, and a token or a home path in that key reaches the terminal and the transcript. receipt_test.go:193 pins the raw key (unknown field "verdict"), so the fix updates that pin. Fix direction: pass the message through scanner.RedactRefusal with the repository root, failing closed to a description. The run state (state.go:274) is out of the class: the loop is its only writer. Detector: a receipt carrying an undeclared key with a home path in it is refused without the path in the error, still naming the key.
- iss-2609290300464268The memory page ingest echoes payload-chosen values into its refusals, the class iss-2609290218032954 fixed in scribe, release, ideate and lifeboat. A DistilledPage arrives host-produced (memory ingest --pages-json, memory ask --page-json), and internal/core/memory/schema.go quotes its values with %v or %q, sanitised at most and never redacted: a source class (154), an ingested_at (170), the declared classes (299), the undeclared keys themselves (425), type, domain and slug (436-442), and the assembled filename (491, 531). A token or a home path in any of them reaches the terminal and the transcript. Fix direction: describe a closed-shape value with termsafe.DescribeRefused, and name an undeclared key through scanner.RedactRefusal. Detector: a page carrying a marker and a home path in each field is refused without either in the error.
- iss-2609290321312087The shell guard's arg_values operand compare lost a variable's written spelling when main began writing a parameter expansion as the unknown-value mark: rm -rf $HOME, "$HOME", ${HOME} and $HOME/.* allowed, rm -rf $PWD stopped warning, and rm -rf "$BUILD_DIR"/* and rm -rf $OUT/ blocked as deletes of the root because the variable was read as empty text. The tokenizer needs to carry each word's written spelling of its variables to arg_values without changing what any other matcher reads.
- iss-2609290405381338The release cut writes a well-formed secret or the caller's own identity into public release text. launch ship --changelog-json accepts a host-composed payload whose changelog entries[].text and press_release headline text pass through checkProse (size, structure, CleanProseLine) and the outbound policy (session URL and tool footer only), then writes them to CHANGELOG.md and RELEASE.md unredacted: a GitHub token, an AWS key or the caller's own home path in a line is written to the working tree as public release text, to be committed and published. Found by the security review of lane drainEcho2 (INFO: changelog write path). The launch dry-run scan would refuse the same hard_fail finding in the bundled CHANGELOG.md later, but only after the file is written, and a person reviewing the diff may commit it first. Fix direction: at the cut, scan the rendered changelog section and release page with the canonical scanner and refuse any hard_fail finding with a reason naming the kind and the line, never the matched text; a degraded scanner is a stop, as checkOutbound's is. Detector: a payload carrying a well-formed token in a changelog line or a headline is refused, nothing is written, and the refusal does not carry the token.
- iss-2609290405451613The release cut accepts a third party's home path, and any other identity finding the scanner grades warn, in public release text. After the hard_fail refusal of iss-2609290405381338, a changelog entries[].text or press_release headline carrying another account's home path (home_path_other) or a GitHub username (github_username) is still written to CHANGELOG.md and RELEASE.md as it stands, because the cut refuses at the bar the launch scan applies to the same files, hard_fail only. Refusing these too is a policy choice, not a mechanical fix: the store-before-commit redactors (history, memory, ideate) redact every identity kind and refuse any that survives, whatever its severity, but github_username fires on the repository owner's name standing as a bare word (a URL and the owner/repo slug are exempt), which a release note may legitimately carry, and the scanner grades that kind review-only, warn, for that reason. Ruling owed to the product thinker: whether public release text is held to the launch bar (hard_fail only, as now), to the store-before-commit bar (every identity kind, accepting refusals of the owner's bare name), or to a middle bar (third-party home paths refused, usernames allowed). Found by the security review of lane drainEcho2 and split from iss-2609290405381338 by lane drainEcho3. Detector, once ruled: a payload carrying a third-party home path in a changelog line is refused or accepted as the ruling says, and the refusal does not carry the path.
- iss-2609290411321963The memory writer's page-filename refusal quotes the token it refuses. judgeFilename (internal/core/memory/redact.go, called from writer.go at the write boundary) refuses a page whose host-chosen type, domain or slug carries a hard_fail secret, and its message names the whole filename raw: a slug of ghp_ and forty characters is refused with the token in the error, so it reaches the terminal and the transcript, the class iss-2609290218032954 and iss-2609290300464268 closed elsewhere. The echo is deliberate and pinned: TestWriteRefusesASecretShapedFilename and the separator-spelling cases in writer_filename_test.go assert the refusal names the page, because the filename is the write's identity and the operator needs to know which page to repair. scanner.RedactRefusal cannot square the two: an underscore is a word character, so a token joined behind topic_auth_ has no word boundary and is not redacted in the joined name, and a token can straddle the type, domain and slug separators. Found by lane drainEcho3's sweep for iss-2609290300464268. Fix direction: seal, byte for byte in the joined name, every span the hard_fail findings over filenameJudgeTexts matched, and keep the rest of the name. That keeps both requirements, the page named and the token not echoed, so it needs no ruling; describing the whole name would give up the identity the test pins. Detector: a page whose slug, or a spelling across the separators, is a well-formed token is refused, nothing is written, and the refusal names the page with the token sealed.
- iss-2609290419119456The shell guard allows recursive deletes of the home directory spelled three ways its arg_values compare does not read: a backslash-newline inside the variable's name (rm -rf $HO<backslash-newline>ME, which bash reads as $HOME and the guard spells ${HO}ME), a variable inside a brace expansion (rm -rf {$HOME,x}, rm -rf $HOME/{.*,}), whose words carry no written spelling, and a parameter expansion of HOME with an operator (rm -rf ${HOME%/}, ${HOME:-x}, ${HOME#}, ${HOME/x/x}, ${X:+$HOME}), whose value can be the home but whose spelling is not one of the words the entry names. rm-rf-root-or-home promises to block a recursive delete of the home wherever it stands, and each of these deletes it. Present at main a018e7ca2 and at 8cd7f88f4.
- iss-2609290426544292rm-rf-root-or-home reads a default expansion by its variable only: rm -rf ${DIR:-$HOME} and rm -rf ${DIR:-/} delete the home or the root when DIR is unset and allow, because a word's written spelling holds one text and the default's own word is the other value it can print. An alternative nested more than three deep (${X:+${X:+${X:+${X:+$HOME}}}}) and ${PWD:0:1}, which prints the root and warns as $PWD, are the same class. Named in 17-guard.md's residuals.
- 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.
- iss-2609290518278152fsutil.ReadDeclaration refuses a home-scoped declaration as replaced between its vetting and its read when another abcd process of the same user atomically renames a new version into place inside the lstat-to-open window, so two abcd processes on one machine (two sessions, or a hook and a verb) can make one refuse its own ~/.abcd/config.json, rules.json or credentials index; the merge-group macOS leg of PR 744 failed TestConcurrentConnectsKeepEveryKeyAndBlock on it.
- iss-2609290521415701The shell guard's tokenizer panics with index out of range when a here-document is pending and a substitution opened on the same line is left unterminated: cat <<E <(x, cat <<E $(x and cat <<E with an open backtick, each followed by a newline and the line E. The newline inside the substitution reads the pending bodies and resets docOwners to nil, while the enclosing command's curDocs, restored when the unterminated substitution is closed at the end of input, still indexes it, so flushSegment's docOwners[k] panics. The hook fails closed (a panic exits 2, which the hook passes through as a block), but abcd guard check prints a Go stack trace instead of a verdict, and a panic is not a verdict the guard can explain. Present at main 285455056 and at 2fa327bb5.
- iss-2609290541525428scanner.RedactRefusal does not seal a token glued behind a word character. The scanner's bundled secret patterns anchor their start on a leading word boundary, and '_' and every letter or digit are word characters, so a token that sits right after one has no boundary and is never matched: the implement loop's laneFileGap (internal/core/implement/loop/receipt.go) returns the receipt's path as notes_ followed by a GitHub PAT and .md, does not exist, with the token raw, and memory's ValidateDistilledPage (internal/core/memory/schema.go) returns unknown key(s) [notes_ followed by the token] raw, while notes- and sub/ spellings seal. A letter on both sides (x, token, y) is missed the same way. Every RedactRefusal caller shares the gap (scribe, release, ideate, lifeboat, reading, intent, memory, implement loop), so a host payload's key or path carries a credential to the terminal and the transcript through a refusal. It is the refusal-side twin of the page-filename gap iss-2609290411321963 closed with filenameJudgeTexts. Found by the security review of lane drainEcho3. Fix direction: in the primitive, not the callers; re-find the secret patterns with their leading boundary removed, through the scanner's own linear adjacency machinery, and seal every glued match byte for byte through Redact; fail closed as before. Detector: a refusal naming a key or a path in which a well-formed token sits behind an underscore or a letter carries the token sealed.
- iss-2609290551363398The canonical scanner's ScanText does not find a secret token glued behind a letter, a digit or an underscore, so the launch scan, the memory writer's page-name bar (judgeFilename) and every store-before-commit redactor share the blind spot. Every bundled secret pattern opens on a leading word boundary and a word character before the token removes it: judgeFilename accepts topic_auth_x followed by a GitHub PAT and y, .md, because no underscore suffix of filenameJudgeTexts starts at the token, and the history, memory and capture redactors leave the same spelling raw in what they store. scanAllPatterns' adjacency probes recover a token that abuts a token already found, never one that abuts ordinary text; its own comment names the limitation as accepted. Found by the security review of lane drainEcho3 (INFO), beside iss-2609290541525428. Measured before deciding: the glued sweep that closes the refusal gap, run over all 4605 tracked text files of the repository, adds 0 findings to ScanText's 13 hard_fail secret findings, the launch dry-run's finding count stays 1, and the sweep costs 7 to 10 per cent of the bounded scan's time. Fix direction: run the glued sweep inside scanText, so every consumer inherits it. Detector: ScanText reports a token glued behind a letter, a digit or an underscore at its own byte span, and the memory writer refuses a page whose slug carries one.
- iss-2609290625381759The shell guard reads a here-document that a command substitution opens and never reads (x=$(cat <<E), a line, then E) as pending after the substitution closes, so the lines after it are the document's body and allow. bash 5 reads them so, but bash 3.2 and /bin/sh, the /bin/bash and /bin/sh of macOS, drop the document at the close and RUN those lines: echo $(( $(echo <<echo) 1 )) followed by echo B, echo and echo C prints 1, B, an empty line and C there. So echo $(cat <<E) x followed by rm -rf ~ and E allows, and heredoc_test.go pins echo $(( $(cat <<EOF) )) followed by git clean -fd and EOF as allow. Present at main 285455056 and at d53e21cf3.
- iss-2609290625482831The shell guard's rm-rf-root-or-home compares an operand to its arg_values as one exact word, so a root or home operand written with repeated slashes, a trailing double slash, a /./ segment or a /../ segment under the root allows: rm -rf //*, rm -rf $HOME//, rm -rf ~//*, rm -rf /./* and rm -rf /../* all allow, while rm -rf /* and rm -rf $HOME/ block. The kernel reads each as the root or the home (a slash run is one separator, . is the directory itself and the root is its own parent). rm-rf-working-directory has the same gap (rm -rf .//* allows). Present at main 285455056 and at d53e21cf3.
- iss-2609290630234596record-lint's agent_contract rule defaults its prompt-version log to <agents_dir>/CHANGELOG.md when the config names no changelog path, which is inside the directory a harness loads whole: a repository that takes the default gets a spurious CHANGELOG agent, the iss-110 defect this repository fixed by moving its log to .abcd/development/agents/ and configuring the path. The default either moves outside the loader's root or becomes a required key; either way the agent_contract tests that write agents/CHANGELOG.md with a bare rule follow.
- iss-2609290656480443fsutil.ReadHomeDeclaration vets the declaration file's own mode and owner and refuses a symlinked directory on the way to it, but never vets the mode or owner of those directories: a ~/.abcd that every user can write (0777), or one another account owns, holding a 0600 file of the caller's still reads DeclarationOK. Anyone who can write that directory can rename or hard-link a file of the caller's shape in under a declaration's name (rules.json, trusted-roots, path-entry, credentials.json, config.json), so the leaf guards judge a file the caller did not put there. The guard rests on abcd's own writers creating ~/.abcd at 0o755/0o700; a directory made by hand, or re-moded, is never judged.
- iss-2609290656491358statusline.ReadSettingsFile vets ~/.abcd/statusline.json with its own os.Lstat and fsutil.CallersAlone, then reads it through fsutil.ReadGuardedInRoot, whose own Lstat and os.SameFile tie the bytes to a second look at the path that checks neither mode nor owner. A file renamed over statusline.json between the two looks (group- or other-writable, or another account's) is read and honoured, including the previous_command the harness runs on every refresh. It is the vet-then-read-by-a-second-look shape iss-2609251537550065 closed in fsutil.ReadDeclaration, kept by hand in one reader instead of going through the canonical home-declaration read.
- iss-2609290703091174Open question for the product thinker: should abcd refuse to read its own settings from a ~/.abcd folder that the owner's group can write to? Today it refuses a folder every account can write, and one another account owns, but reads from a group-writable one (0775). Refusing would protect a machine where the group really is shared with other people. It would also newly refuse ordinary installs on Debian and Ubuntu, where the login umask for a user whose group is private to them is 002, so the documented 'mkdir -p ~/.abcd' makes a 0775 folder whose group is only its owner. abcd's own writers create ~/.abcd at 0755 or 0700, so only a folder made by hand is affected. Two readings already disagree: the declaration file itself is refused when group-writable, and the worktree store (implement/loop ensureStore) refuses a group-writable ~/.abcd level. Deferred out of iss-2609290656480443's fix until ruled.
- iss-2609290743362554The scanner's glued-token sweep (glued.go, iss-2609290541525428) runs on the raw line only: decodedLineFindings and viewFindings (percent.go) scan the percent-decoded and JSON-unescaped views with the bounded patterns alone, whose leading word boundary cannot hold behind a word byte. A glued token whose own bytes are escaped (a percent-encoded letter of its prefix, or a JSON unicode escape of its first byte, behind an underscore or a letter) therefore survives ScanText, Redact and RedactRefusal raw. Reach is narrow, since no encoder escapes an ASCII letter of a token, but the decoded layers exist to close spelling variants. A second half: ScanText gives no signal when the sweep cannot be built in full (a configured pattern whose leading boundary carries a quantifier); only RedactRefusal reads the sweep's completeness, so every other consumer runs a silently narrower sweep, and Unavailable does not say so.
- iss-2609290745243990rm-rf-root-or-home reads a parent segment only at the root: rm -rf ~/../* deletes the home, and rm -rf ~/../../*, $HOME/../../*, /tmp/../* and /etc/../* delete the root, bare and in sh -c, yet each allows, because cleanSeparators takes out only a leading /../ and never folds a .. after a named directory, the home or a tilde. A root or home delete is allowed.
- iss-2609290825240166itd-2609221017023290 ac-3 promises that the store's write path runs the scanner and refuses a write that would land in a tracked path, and adr-2609221017021499 ruling 4 says the scanner runs on any file the write path touches; the delivered store scans the index (~/.abcd/credential-homes.json) alone, writes ~/.abcd/credentials.json, the file that holds the value, unscanned by construction (internal/core/credential/credential.go SetMachine), and refuses only the abcd home's value write inside a git working tree while the index is still written there (internal/core/credential/store.go Set, ruled at review in 278e266d8 and stated on commands/ahoy.md). The invariant the intent guards, no value in a tracked path or the harness's settings, holds and is tested; the record's wording does not match what ships, and a scan of the value file is unsatisfiable, since a real key is exactly what the scanner flags. The ADR and the intent should say the index is what is scanned and the value write is what is refused, or a ruling should say why the wording stands. Fidelity audit verdict: ac-3 MET_WITH_CONCERNS.
- iss-2609290825319136itd-2609221017023290 ac-2 promises a walkthrough that offers the three homes with the keychain recommended in the prose above the choice; its press release says abcd asks the person once per service where the secret should live, and spc-2609221017544877 scope 2 says the CLI asks on the terminal and the plugin page asks through the host's question tool. Delivered, the CLI's abcd ahoy credential <name> explains and lists the homes with a setup command for each and writes nothing, and the choice is a --home flag on a second invocation (internal/surface/cli/ahoy_credential.go newAhoyCredentialCommand); the CLI never asks. Only the plugin page asks, through the host's question tool (commands/ahoy.md, the credential section). A non-interactive CLI is consistent with every other abcd verb and with the value arriving on stdin only, so this may be the right shape, but the spec and the press release say otherwise and no recorded decision says the CLI's ask was dropped. Either the record says the CLI takes the home as a flag, or the walkthrough asks. Fidelity audit verdict: ac-2 MET_WITH_CONCERNS.
- iss-2609290845269642abcd lint's privacy-hygiene rule reports 102 findings on main (88 errors, 14 warnings) in this public repository's committed tree, and nothing gates it. Classified by the privacyLint lane of autonomous run A: 11 are class A, a real value from a real machine: two test files (the ahoy receipt-fold test and the fsutil redact-root fold test) build their fixture paths under the authoring machine's actual home directory, whose account name is a generic one the scanner itself lists as generic. 71 are class B, synthetic values whose shape carries the meaning and that carry no waiver: redactor and detector fixtures that need a non-persona, non-reserved value (a token unique enough that an absence assertion means something, a prefix collision, a traversal escape, a non-reserved address), and records, comments and research observations that illustrate such a case. 3 are class C, synthetic placeholders in comments and one test whose shape carries nothing, so a persona home serves equally. 17 are class D, not personal identifiers at all: public cloud metadata endpoints the URL guard must name, the Homebrew-on-Linux system prefix, the CI runner's system home, RFC section numbers read as IPv4, a hex fragment read as IPv6, and Go selectors read as LAN hostnames. Git history keeps every class-A value; rewriting published history is a decision for the person, not a lane. The missing gate is iss-2608231000561060.
- iss-2609290925320493The shell guard reads a ** path segment as a name, not as the * every shell without globstar expands it to: rm -rf /**, ~/**, $HOME/**, ${HOME}/** and ~/../** are allowed, although bash 3.2, bash 5.3 and /bin/sh each expand ~/** to the home's entries and ~/../** to the home's siblings with the home among them (echo only), so /** deletes what /* deletes and ~/../** deletes the home. A run of * in a glob matches what one * matches, and with globstar set ** matches more, never less.
- iss-2609290925333487The shell guard reads a dot-glob path segment as a name, although bash 3.2 and /bin/sh (no globskipdots) let a segment written with a leading dot match the name .. and expand ~/.?/*, ~/.[.]/*, ~/.[!x]/*, ~/.?*/* and ~/.*/* to include ~/../* (the home's parent's entries, the home among them) and /.?/* and ~/../.*/* to the root's entries; every one is allowed. bash 5.3 leaves them literal. echo alone showed the expansions.
- iss-2609290925338019TestHomeSpellingsStayLinear's parent-segments shape cannot see the lexical fold: cleanSeparators, foldParents and literalSegment tally no work, so a fold that copies its stack per pop (quadratic) passes the pin whose name says it holds the spelling linear.
- iss-2609290925346181rm -rf $PWD/../* is allowed while rm -rf ../* and rm -rf $PWD/* warn (rm-rf-working-directory): the same parent directory, spelled through $PWD, is not folded, since the lexical fold of .. reads only targets that begin at the root or the home. ./../* and x/../../* (the parent too) are allowed the same way.
- iss-2609290929129725rm -rf /*/ and rm -rf ~/*/ (and $HOME/*/, ${HOME}/*/, ~/.*/) are allowed, although /*/ globs every directory under the root and ~/*/ every directory in the home, so each deletes what /* or ~/* deletes less the plain files: rm-rf-root-or-home names /, /*, ~, ~/ and ~/* but no trailing-slash glob, while rm-rf-working-directory names */ and ./*/ for the working directory. Found while pinning ~/**/ for the ** reading.
- iss-2609291032194222The status line's waiting:<role> badge must show only while that role is actually being addressed. After a computer crash ended every session of autonomous run A, we reopened the repo and saw 'waiting:facilitator', which was wrong: no session was waiting on anyone. The mode is a bare word in .abcd/.work.local/mode (set to 'facilitator' at 09:23Z 2026-09-29, before the crash), and it is tied to no session, so it outlives the session that set it and keeps claiming a question is owed. A crash, kill or rotation never runs 'mode managed', so the badge goes stale exactly when a person comes back to check.
- iss-2609291118049254capture resolve and capture wontfix have no way to set the typed duplicates link, so a record closed as a duplicate carries the relation only in wontfix_reason prose. A machine reader of the ledger sees a wontfix, not a duplicate (found by review-triageMinorC: four duplicate closures in lane triageMinorC, iss-2608290811463906, iss-2609170640135192, iss-277, iss-91). Add a --duplicates <id> flag (issue or intent id) to wontfix, or a duplicate sub-verb, writing the field the ledger already defines.
- iss-2609291157309818fsutil.ReadHomeDeclaration still refuses a home-scoped declaration as replaced between its vetting and its read when a concurrent abcd renames a new version into place inside the lstat-to-open window: the re-vetting fix for iss-2609290518278152 (b342b2b29) went into the path-based ReadDeclaration, and the integration merge that landed it (24e78506b) kept the descriptor-based readDeclarationIn from a07ad672f, which every home-scoped reader (layered.Load, oracle, credential, rules, statusline) goes through and which refuses a replacement on sight; so iss-2609290518278152 regressed and TestConcurrentConnectsKeepEveryKeyAndBlock failed the Linux CI leg of PR 748 with ErrDeclarationSwapped from ~/.abcd/config.json
- iss-2609291233390280The guard reads a dot-led glob segment with a bracket expression as unable to match .., so rm -rf ~/.[[:punct:]]/*, ~/.[[:print:]]/*, ~/.[![:alnum:]]/*, ~/.[[=.=]]/*, ~/.[].]/*, ~/.[!]]/*, ~/.[--.]/*, ~/.[\!.]/*, $HOME/../.[[:punct:]]/*, /.[[:punct:]]/* and ~/.[[:punct:]]/** allow, bare and through sh -c or bash -c, while bash 3.2 and /bin/sh expand each to the entries of the directory holding the home (or the root). dotGlob decides through path.Match, which has no POSIX, equivalence or collating classes, refuses a set whose first member is ] or -, and sees \! after the tokenizer has removed the backslash, so an escaped ! reads as a negation. Pre-existing at the round's base 4e8cbd387; found by verify-fix6-guardGlob item 1.
- iss-2609291233468970The guard's glob compare (globMatches) reports no match for a bracket expression path.Match cannot read, so a globbed command name, subcommand, flag or setting spelled with one allows where bash expands it to the dangerous word: r[[:lower:]] -rf /, /bin/r[[:lower:]] -rf /, ba[[:lower:]]h -c 'rm -rf /', git clea[[:lower:]] -fd, git clea[].n] -fd and git reset --har[[:lower:]] allow, and bash 3.2, /bin/sh and bash 5.3 each expand r[[:lower:]] to rm and ba[].s]h to bash when such a file is in the working directory (the case GHSA-3w99-pgv4-8g55 closed for plain sets). The tokenizer also removes a backslash before the compare, so r[m\]] (a set holding m and ], which every shell expands to rm) reads as r[m] followed by ]. Pre-existing at the round's base 4e8cbd387; confirmed while fixing the dot-glob finding from verify-fix6-guardGlob.
- iss-2609291246244867The history registry's locked rewrite took its lock through one walk of ~/.abcd/history and loaded and wrote index.json through two further walks (registerRepo: withHistoryLock, loadHistoryIndex, writeHistoryIndex each opened the directory afresh), so a same-uid swap of ~/.abcd/history once the lock was held sent the load and the write to a directory whose lock was never taken. The same shape as iss-2609290300313698, found while sweeping that pattern.
- iss-2609291313276243The glossary entry for step (.abcd/development/brief/glossary/core/step.md) says the loop's step interface, abcd implement step, uses the same word for the same thing as a spec's steps: the next piece of the current spec. The loop does not work that way: implement step performs one stage of the current lane (worktree, brief, implement, validate, land), and a lane lands one spec step, so the state file, the JSON payloads (step, performed, refusal.step) and the command pages already use one word for two things and qualify the spec's as spec step. itd-2609212103565953 criterion 5 asks the command page to describe them as one word for one thing, which cannot be written truthfully until someone rules which of the two keeps the word (rename the lane's stages, or change what implement step means) or restates the criterion.
- iss-2609291409053602The scanner still masks the repository owner's public GitHub handle when it names a sibling repository of the same owner, e.g. <owner>/<sibling> written in a record of <owner>/<repo>. isOwnRepoSlug (internal/adapter/scanner/identity.go) exempts the owner only in the repository's own owner/repo slug, so a managed repo that publishes to a sibling repo loses the handle in every record naming it, and each one is restored by hand. Extend the exemption to the remote's owner followed by '/<any repo name>', since that owner is public by the same argument; the owner alone and other owners stay masked. Reported from a managed repository that publishes to a sibling repository of the same owner.
- iss-2609291430223385TestEightConcurrentShortLivedProcessesDoNotWarn flaked in a lane's make preflight when the machine load was about 200 on 16 cores: /bin/ps was killed, so the test failed in code the lane did not touch; the rerun passed. A gate that fails on machine load, not on the change, costs a 10-15 minute preflight rerun and teaches lanes to rerun red. Make the test tolerate a killed or timed-out ps (skip with a stated reason, or retry once), or bound what it spawns.
- iss-2609291610432030The transcript store never narrows what an earlier binary laid out wider: a chain level that already exists keeps its mode (fsutil.EnsureRealDir creates at 0o700 and leaves an existing directory alone, internal/core/history/location.go, Resolve), and a record already on disk at 0o644 stays at 0o644 until Migrate happens to rewrite it. Capture now writes every new record 0o600 (iss-2609012029343438), which protects nothing already stored: on a machine where an earlier layout created ~/.abcd/transcripts or a level below it 0o755, every record captured before the fix stays readable by other local accounts. The remedy is a narrowing pass on the store's own levels only (the base, the root-sha level and records/, never ~/.abcd or a checkout's .abcd/.work.local), each opened O_NOFOLLOW|O_DIRECTORY, owner checked with fstat against this account, and narrowed with fchmod on the descriptor, the shape of fsutil's unexported tightenLock for lock files. No exported fsutil primitive does that for a directory, so it is a new primitive plus a stance change for EnsureRealDir's never-narrow contract, not a mode constant.
- iss-2609291653241690exifView follows only the Exif sub-IFD pointer 0x8769 (internal/adapter/scanner/metaview.go:161-166) and never the MakerNote 0x927c, so a camera owner's name a vendor writes there (Canon's MakerNote tag 0x0009 OwnerName, in the TIFF byte order with header-relative offsets) is not read as a person tag: a short single-token owner name in a JPEG's or TIFF's Canon MakerNote is dropped as chance. A name of eight or more bytes, or one of several words, is still caught by the raw ASCII scan. Found by review-scanMeta (fixture 'Canon MakerNote OwnerName' scans clean at the integration tip).
- iss-2609291731336469The transcript store refuses every history verb, reads included, when its records leaf is owned by another uid, and says so with write wording: Resolve's owner check (internal/core/history/location.go:223) reports 'not owned by this account; refusing to write transcripts into it' even for history list. The realistic hit is a root container over a bind-mounted checkout with the local store declared, where reads and hook capture both refuse. Precedent runs both ways: rules/root.go and fsutil.go refuse foreign-owned reads, home.go admits a root-owned home. Fix-later shape from the review: on a foreign owner, skip the narrowing with a Note on a read and refuse only a write.
- iss-2609291803334904The status block's next-up head can name a READY intent abcd build next would not pick. The head is read in the pick order and passes over a held intent and one in a lane, but build next's candidates also pass every other pre-start check (open questions, the claim sections, blocked_by, the spec's steps, the peers), which the block does not run: a READY intent with an open question or an unshipped blocker, and the highest score, is marked next up on the board and the site while build next excludes it. statusblock cannot import the loop (loop imports peers, peers capture, capture site), so the fix hands the pick's candidate set in from the front doors the way the lane reader is, at the cost of a peers read on every bare board.
- iss-2609291925134691When an agent asks the person a question through the interactive question tool, the example that makes the question answerable must be visible IN the question: in the question text and in each option's preview. Prose written before the tool call is not visible while the question shows. On 2026-09-29 the person twice answered 'explain in laypersons terms' / 'show me the example, I can't see it' because the example sat in prose above the question.
- iss-2609291925136841Evaluate whether CLAUDE.md can be removed safely now that Claude Code reads AGENTS.md natively. Today CLAUDE.md duplicates the AGENTS.md router. Check every place that relies on CLAUDE.md being present: the harness's own loading in the main session, sub-agents and plugin contexts; abcd's ahoy/prepare-this-repo scaffolding and lint rules that expect CLAUDE.md as a bridge; docs that name it; and managed repos abcd sets up. Only remove it if every consumer reads AGENTS.md.related itd-2610030814013772
- iss-2609291925149138The status-line role label (waiting: product thinker / waiting: facilitator) must always name the person the CURRENT question is for. An agent set 'product thinker' at the start of a mixed interview and left it while asking technical-facilitator questions, so the badge was wrong. Assess each question's addressee first, then set the label, then ask.
- iss-2609291925387011The live check of abcd site setup against a real hosting provider is owed to a person. itd-2609061543533170 shipped on tests against a simulated provider, and the product thinker ruled on 2026-09-29 that each paid service (live site setup, the API adapter, the decision adapter) may close on tests against a simulated service, with the live paid check recorded as owed and done later by a person. Owed: in a managed repository, with a real hosting credential configured, run abcd site setup and confirm that the host is created and routed through the provider adapter, that the reported live address serves the rendered site, and that nothing beyond the one host is created or billed; record the result on this record and resolve it.related itd-2609061543533170
- iss-2609291925393913The live check of the OpenAI-compatible API adapter against a real paid provider is owed to a person. itd-2609081951381895 may close on tests against a simulated OpenAI-compatible service under the product thinker's ruling of 2026-09-29 on paid services (live site setup, the API adapter, the decision adapter), with the live paid check recorded as owed and done later by a person. Owed: with the person's own key stored through abcd ahoy connect, send one step through the adapter to a real aggregator and confirm that a model the provider block lists answers, that a model it does not list is refused before anything is sent, and that the provider's billing shows only the listed model; record the result on this record and resolve it.related itd-2609081951381895
- iss-2609291925398978The live check of the decision adapter against the real paid decision model is owed to a person. itd-2609221009495079 may close on tests against a simulated service under the product thinker's ruling of 2026-09-29 on paid services (live site setup, the API adapter, the decision adapter), with the live paid check recorded as owed and done later by a person. Owed: run one typed judgement through the decision adapter against the real decision model with the person's own key, and confirm the verdict is received, recorded and measured as the lab expects, with nothing billed beyond that one judgement; record the result on this record and resolve it.related itd-2609221009495079
- iss-2609291925582287The oracle refusal for a route whose agent's role setting does not point at the routed connection still says which model such a route asks for is not yet decided, and its doc comment says the record does not yet decide it. The product thinker ruled on 2026-09-29 (BR1) that such a route is refused, naming the one setting to add, as built in e1c4e38ad and 35100512e, so the refusal is now the decided behaviour and the words not yet decided tell the person a ruling is still coming when none is. The fix is wording only: drop the not-yet-decided clause from the error in internal/core/oracle/resolve.go (take) and the comments in resolve.go and tier.go, keeping the named setting, and adjust any test that pins the old sentence.
- iss-2609291942515955itd-111 acceptance criterion 8, as amended at the close, says the product thinker's 2026-09-29 ruling (an agent's check on macOS plus the Linux CI run stand in for the per-platform check by a person) is recorded in .abcd/work/DECISIONS.md under that date, but no line of DECISIONS.md carries it at 8ffb6d069 or on main: the three 2026-09-29 entries concern the pre-commit sources refresh, a guidance principle and the five-agent ceiling. The shipped intent cites a ruling the ledger does not hold. Either the ruling is appended (the staleClose pull-request body says a separate rulings lane appends it) or the amendment cites where the ruling actually lives.
- iss-2609291942520919itd-111 acceptance criterion 6 (after provisioning fetched a new pinned binary, the next session reports the version transition performed) is delivered as a per-repo comparison: ahoy.VersionTransition (internal/core/ahoy/vintage.go:220-234) compares core.Version against meta.setup_version in the repo's .abcd/config.json, written by ahoy install, and reports no transition when either side is a dev build. spc-22 stated the reference would be recorded beside the plugin-cache metadata. So a repo never set up by ahoy install, or a dogfood dev build, sees no transition report after provisioning fetched a new binary, which is the scenario the criterion describes. Either the plugin-cache record the spec named is the reference to consult, or the narrowing is recorded on the criterion.
- iss-2609291942529461itd-111 acceptance criterion 2 promises that abcd ahoy install run through a stale binary refuses before any write, but under an explicit --bin-dir the writability probe runs first: install (internal/core/ahoy/apply.go:91) calls resolveInstallTarget, whose dirWritable (internal/core/ahoy/store.go:431) creates and removes a .abcd-write-probe-* temp file in the named directory or its nearest existing parent, and only then (apply.go:157) does staleBinaryRefusal fire. The comment at apply.go:267 says the probe runs without creating anything, which store.go contradicts. Net state is unchanged, but a stale or unknown-vintage binary touches the filesystem before it refuses. Move the refusal above the probe, or amend the comment and the criterion's wording.
- iss-2609292011569133The product thinker's rulings BV1 and BV2 of 2026-09-29 change what the shipped status block promises: the text board gives Later as a count alone (--json and the site keep its rows), and an intent in a lane is listed under Now only, never also under Next or Later. That makes itd-2609212103568351 criteria 1 and 3 and adr-2609212115255771 decision 2 (Next is every planned intent the gate reports READY; Later is the rest) false as written.
- iss-2609292030070275The dependency-bump re-authoring (itd-2609221842494980, spc-2609221843355061) has never run against the live forge, so its first acceptance criterion is proven only offline, against a stand-in App API and a local remote. The person's steps are owed: create a GitHub App with Contents read and write, install it on this repository, store its id and private key as the Dependabot secrets DEPENDENCY_REAUTHOR_APP_ID and DEPENDENCY_REAUTHOR_APP_KEY, and set owner_name and owner_email in .abcd/config/dependency-reauthor.conf. Until then every in-bound bump is refused by name and stays a person's to land. Done when one real dependabot go_modules or pip bump is watched re-authored as the owner, re-checked green by the attribution gate and merged; then the spec closes and the intent ships (Refs: iss-2609221820487644).
- iss-2609292057441479itd-111 acceptance criteria 3 and 5 name command spellings the CLI no longer answers to: AC3 says the vintage report comes from 'abcd version' and AC5 says the explicit release check is 'abcd version --check' (design decision 6 and its open question say the same). Since itd-2609212130136102 consolidated the verbs, the report is 'abcd --version' and the check is 'abcd update --check'; both old spellings refuse with a moved notice naming the new one. The behaviour each criterion asks for is present at the new spelling, so the shipped criteria read true only once the record says which surface meets them. adr-38 tier 2 also cites 'abcd version --check' as an example of an explicit ask; the rule it states still holds.
- iss-2609292159470796Conduct SOTA research to suggest a remedy for an issue or, in an autonomous run, to justify selecting a remedy: a remedy chosen without a prior-art check can repeat a known-bad approach, and a run that picks one leaves no evidence of why it beat the alternatives
- iss-2609292234505986Invariant 19 in the brief names the drain rule as capture.Eligibility, an exported function that no longer exists: commit 81bfda851 unexported it to eligibility, so the invariant cites a symbol a reader cannot find
- iss-2609292320015665rm-rf-root-or-home reads a trimmed expansion as its variable alone, but a suffix trim whose pattern is unknown text or begins with a glob can leave only the leading slash of an absolute path: with X=/a/b, bash 3.2 prints / for ${X%${X#?}} and ${X%%[!/]*}, so rm -rf ${X%${X#?}} deletes the root and allows. Found while fixing iss-2609290426544292, whose written spelling now holds a set of texts; a trim can add / to that set, but reading every trim as the root would refuse the everyday ${DIR%/} and ${f%.*}, so the rule needs the pattern's shape.
- iss-2609292352131344An unknown flag under --json is refused with no JSON envelope on stdout: abcd ahoy --bogus --json (and any verb) prints cobra's 'abcd: unknown flag: --bogus' on stderr, exits 2 and leaves stdout empty, because the flag parse fails before the persistent --json flag is read, so Run() sees json=false. The --json contract ('a refusal is a {"abcd":"error",...} object on stdout too') is broken for every flag-parse refusal; a machine caller passing an old flag (abcd version --check --json after v0.12.0) reads nothing.
- iss-2609292359485570The shared run's bounds use 'step' for a third thing: abcd implement check <lane|release|review|audit|land> asks whether a session 'may take a step', its verdict carries the point under a JSON 'step' field (internal/core/implement/bounds.go, Step/StepLane/StepRelease/StepReview/StepAudit/StepLand), and commands/implement.md and brief 27-implement.md speak of 'the release step' and 'a step that is not a claim'. BU1 (2026-09-29) settled that in the build loop 'step' names a spec's piece and a lane's are stages; the check vocabulary, a point in a shared run where the second session's bounds are checked, was not in that ruling and still says step.
- iss-2609300009506126rm-rf-root-or-home reads an expansion that prints nothing whatever the value is as its variable, so the text around it is never read as the whole word: with X=/a/b, bash 3.2, /bin/sh and dash print nothing for ${X%%*}, ${X##*}, ${X%%/*} and ${X:0:0}, so rm -rf ${X%%*}/ deletes the root and rm -rf $HOME/${X%%*} the home, and both allow. bash 3.2, the /bin/bash and /bin/sh of macOS, also prints nothing for a trim, a replacement or a substring after a scalar's subscript (${X[0]%zzz}/ is /). Found while fixing iss-2609292320015665, the trim that leaves only the root; an alternative's empty text was added by iss-2609290426544292, and these are its siblings.
- iss-2609300009581165rm-rf-root-or-home reads a pattern replacement as its variable unless its pattern is only *, but a replacement whose pattern can match the whole of an absolute path prints its string in its place, and one whose pattern can match all of the path after its leading slash prints / and its string: with X=/a/b, bash 3.2 and /bin/sh print the home for ${X/\/*/$HOME}, ${X/?*/$HOME} and ${X/$X/~}, and / for ${X/${X#?}} and ${X//[!\/]*/}, and rm -rf of each allows. Found while fixing iss-2609292320015665; iss-2609290426544292 read only the *-only pattern and left the rest alone to keep ${DIR/#\~/$HOME} allowed.
- iss-2609300012273350The oracle and credential machine layer is whatever $HOME names: layered.RootsFor (internal/core/layered/layered.go:156) and credential.UserStore (internal/core/credential/store.go:92) both take os.UserHomeDir, which on Unix returns $HOME. An environment a repository can shape (a committed harness settings file whose env block sets HOME into the tree) would let a checkout supply the 'machine' ~/.abcd/config.json, and with it a keyed provider block and the machine routes that keyRoutes admits to spend a key, while the operating-system keychain still answers by the user's login session, so the repository's own route reaches the person's paid key through a machine layer it wrote. keyRoutes did not introduce this; it inherits the trust in $HOME.
- iss-2609300015353414itd-130 criterion 9 reads 'Given stdout is not a TTY, when the update downloads, then no progress output is emitted', but the delivered gate keys progress on stderr, the stream the progress is written to: stdout carries only the receipt in every mode, and progress appears on stderr only when stderr is a terminal. The code is the right reading and the criterion's wording is loose: keyed literally on stdout, it would hide progress from a person watching 'abcd update | tee log' on a terminal while still writing it into a redirected '2>log'. spc-32 line 93 already words the test as 'stdout carries only the receipt'. Found by the itd-130 fidelity audit (receipt rcp-264f7b144576, ac-9 concern), gap 2 of iss-2609012111162089.
- iss-2609300025372991Two shipped intents' Implementing specs sections misstate where their predecessor-store spec ids stand: itd-36 says its frontmatter spec_id records spc-38 as the primary delivering spec, while the frontmatter records spc-2609211905174684 and live spc-38 and spc-39 are itd-136's record explorer and itd-137's relationship chart; itd-4 says its spc-20 to spc-23 do not exist in the native spec store, while the live store holds all four as other specs (banlist, fresh install, stale-binary warning, tier placement). Found while qualifying predecessor-store citations for iss-2609290448510918.
- iss-2609300032219282Superseded itd-47's Implementing specs section says its frontmatter spec_id records spc-27 as the primary delivering spec, while the frontmatter holds spec_id: null, and spc-27 and spc-32 are predecessor-store ids that the live store reuses for the surface-coverage registry and abcd update. The same defect iss-2609300025372991 fixed in itd-36 and itd-4, found in a third intent while qualifying predecessor-store citations for iss-2609290448510918.
- iss-2609300055241043abcd update stages the verified release at the fixed name .abcd.new beside the target and opens it with O_CREATE|O_WRONLY|O_TRUNC, which follows a symlink planted at that name: the file the link points at is truncated and filled with the release bytes, and the swap then renames the symlink into the target's name, so the PATH entry becomes a link to that file. Precondition is write access to the install directory (which already lets one replace abcd), and the open was selfupdate.Apply's before the staging moved into Apply, so not a regression, but the open is owned code now.
- iss-2609300057304812The guard allows rm -rf ${X:-$'/'}, ${X:-$"/"} and ${X:-$'\x2f'}, which bash 3.2, /bin/sh and bash 5.3 all print as / with X unset: spellWord reads a $ that opens no name as a word it cannot read and returns nil, so a default or alternative word written as an ANSI-C or a locale string is never read (review-guardSet MAJOR-1). The same reading misses ${X:-$!/}, which is / with no background job.
- iss-2609300057311045On bash 5 the guard allows rm -rf ${X/"/"*/$HOME} and ${X//"/"*/$HOME}, which bash 5.3 prints as the home: readPattern ends a replacement pattern at a quoted /, as bash 3.2 does, while bash 5 keeps a quoted / in the pattern (review-guardSet MAJOR-3). The same reader takes $"" in a pattern for a literal $, so ${X%%$""*}/ reads as not whole and is allowed though every shell prints /.
- iss-2609300057318410The guard allows IFS=x; rm -rf ${U:-x/x} (and ${U:+x/x}), which every shell splits on the assigned IFS into "" and /, so rm deletes the root; spellWord splits an unquoted default or alternative word on whitespace only (review-guardSet MAJOR-2). IFS=Uv; rm -rf $HOME/x splits the home into / the same way.
- iss-2609300057326778The guard allows rm -rf ${!X:-/} and ${!X-/}, which bash 3.2 and /bin/sh print as / with X unset: spellParameterAt returns the expansion as written whenever the body does not begin with a name byte (review-guardSet MAJOR-4). The same test drops every positional and special parameter, so ${1:-/}, ${@:-/}, ${!:-/} and ${#:+/} are allowed though every shell prints /.
- iss-2609300057462186The guard allows rm -rf /$HOME and rm -rf /${HOME}, which delete the home: the arg_values compare cleans a run of separators inside a path (//*, $HOME//) but not one written before a home spelling, so /$HOME names none of the values. Found in the fix-guardSet sibling sweep; outside the four review findings.
- iss-2609300057467536The guard allows rm -rf $!/ and rm -rf "$!"/, which bash 3.2, /bin/sh, dash and bash 5.3 print as / when no background job has run: the tokenizer reads $! as a number that stays the text it is (simpleParamEnd), so the word is the literal $!/ and names nothing, though $! is empty until a job runs in the background. Found in the fix-guardSet sibling sweep; outside unknown.go.
- iss-2609300109005165A flock lock descriptor opened with a raw syscall.Open and no O_CLOEXEC is inherited across exec by every child the holder starts, so a child that outlives its dead parent keeps the lock held: the next writer gets contention after its whole budget, although the process that took the lock is gone. Shown by a re-exec test: a WithFileLock holder that starts a sleep and is killed leaves the lock ungrantable for 2s while the sleep lives. The descriptors affected are fsutil.WithFileLock's openLockFd, memory's store lock (writer.go) and the directory locks of decide, intent and spec; os.OpenFile and os.Root add O_CLOEXEC themselves, so WithFileLockIn and history's repoLock are not affected.
- iss-2609300110451242Ruling H9 of 2026-09-29 retires the bundled anthropic/* vendor denylist, which changes the reading of itd-2609081951381895 acceptance criterion 3 (a listed model whose prefix matches the vendor denylist is refused at read, and no allowlist entry overrides it) and of adr-2609221009491186 decision 2: with no bundled list the provider's allowlist alone decides, so a listed model of any vendor is served, and only an oracle.denylist entry the repository or the machine writes refuses a listed model
- iss-2609300112146660No check flags a question put to the human whose options carry no example. GRILL rule 11 and the planning interview page (commands/intent.md) say the example that makes a question answerable goes in the question text and each option's preview carries its own concrete example, but nothing verifies a question against that, so the rule holds only while an agent remembers it. This is the eval or lint the remedy of iss-2609291925134691 floated and that record's fix did not build.
- iss-2609300123431381The generated SHELL rules domain recalls on the prose verb kill: the registry's kill-by-search entry contributes the bare head kill to the domain's recall terms, so an ordinary prompt such as 'kill the feature flag, we are not shipping it' injects the whole SHELL block (about 2k tokens, once per session per signature). rm, pkill, killall and git push are shell-only words; kill is an everyday English verb, the class the domain's own fixed aliases already keep out (push, commit, reset). A rules-side exclusion list would be the second source ruling J10 forbids.
- iss-2609300536230889abcd decide writes an empty record: An unattended run then filled each record and wrote the matching DECISIONS.md line by hand, 262 times. One verb should write the proposed decision record and its DECISIONS.md line together.
- iss-2609300536232600No merge-on-green verb: A managed repository needed hand-written scripts to wait for green checks, merge with a merge commit, remove the worktree, delete the branch and trigger the follow-on step. No abcd verb does this.
- iss-2609300536235495No way to supersede a draft spec: A draft placeholder spec was overwritten by the real spec. abcd spec has only close, and abcd intent has link and plan (owner-only). A supersede verb would retire a draft and point to the spec that replaces it.
- iss-2609300536236942No relaunch-at-stage support: Two live replays of finished agents came from resuming a changed workflow script. A relaunch verb would record each unit's stage in the repository and hand a new workflow its arguments, so a relaunch never replays finished agents.
- iss-2609300536237560No run-plan verb: An unattended multi-spec run wrote its plan, order table and defaults by hand, and a scout agent worked out which specs overlap. abcd intent ready checks one intent at a time. A run-plan verb would take the READY intents and propose an order, an agent cap, the overlaps and the defaults to record.
- iss-2609300536238427No record for scoring review findings: An unattended run kept its own scores file (163 rows) and scorer prompt for reviewer findings. abcd reading handles cold readings, not review findings. A scoring verb would make each finding's reviewer, verdict, severity, cost and latency a first-class record.
- iss-2609300536239512No run-brief verb: Every sub-agent prompt in an unattended run repeated the same rules (commit trailer, worktree, privacy checks, no-delete rule). abcd rules renders rule domains for one session, but nothing assembles a brief for sub-agents from the record, so a new rule does not reach every prompt at once.
- iss-2609300536290276abcd capture has no claim verb: A ledger drain kept a hand-written skip list of 13 issues that other sessions owned. A claim would name the session, branch or pull request working on an issue, and a drain would skip claimed issues without a list.
- iss-2609300536290307The guard registry names no recursive delete and nothing wires guard check into unattended runs: On abcd v0.9.0, abcd guard check answered allow for rm -rf /tmp/x, command rm -rf $S/x, rm -r ./scratch and find . -name x -exec rm {} \; (the form without check is refused as unknown). In an unattended run one such command raised a permission prompt that stalled the run for about 111 hours; a registry entry plus wiring the check into sub-agent runs would have failed it in seconds.
- iss-2609300536292775capture --blocked-by takes only issue ids: An issue blocked by a spec had to name its blocker in its body instead, and a run script told agents to add the flag only if the CLI accepts it. The flag should accept spec (and intent) ids.
- iss-2609300651115290rm-rf-root-or-home is bypassed by an IFS named through an expansion: with I=I, `export ${I}FS=x; rm -rf ${U:-x/x}` allows and hands rm "" and / on bash 3.2, /bin/sh, dash and bash 5.3, and so do `eval "I${F:-F}S=x"`, `declare|typeset|readonly|local ${I}FS=x`, `read -r ${I}FS`, `printf -v ${I}FS x` and `: $((IFS=1))`. namesIFS matched the literal text IFS only, and the tokenizer steps over arithmetic.
- iss-2609300651122268rm-rf-root-or-home over-blocks a positional slice: `rm -rf "${@:2}"`, `"${@:1}"`, `${@:2}`, `"${*:2}"` and `"${1:2}"` block, though each prints what the parameters hold, as `rm -rf "$2"` (allowed) does. The substring reading, which adds the root, reached positional and special parameters.
- iss-2609300651127327rm-rf-root-or-home over-blocks an everyday clean line: `rm -rf "${1:-build}"/*`, `rm -rf ${1:-dist}/`, `rm -rf "${1:-dist}/"*` and `rm -rf ${@:-x}/` block, and `rm -rf ./${1:-dist}` warns, though no shell prints the empty value under `:-`. The empty text an emptyable parameter can print was kept under the colon operators.
- iss-2609300651133651rm-rf-root-or-home allows expansions that print nothing beside a root: `rm -rf ${X:-}/`, `${X-}/`, `$HOME${X:-}`, `${A[0]}/`, `${A[@]}/`, and bash 5 `${X^}/` and `${X@P}/` hand rm / or the home, while `${1:-}/` blocks. spellWord read an empty word as no text, and the subscript, case and @ operators returned the value alone.
- iss-2609300711394491The drain-rule offer shifts a piped ahoy install answer stream: the drain-rule category question and the offer itself are inserted mid-order, and the stdin prompter reads one line per question with no terminal gate, so in every adopter repository a scripted stream hands the answer meant for a later question (user-state, the identity pin) to the drain rule, can write an accepted drain eligibility record the script never asked for, and leaves the later question reading EOF.
- iss-2609300711394709abcd drain lets a live deferral through when the checkout holds no release tag: liveDeferralAnchor returns an empty anchor when no tag is found, so every deferred_after reads as lapsed and a record a person carried past this release is eligible. A shallow or tagless clone (fetch-depth 1 fetches no tags) is the unattended drain's likely checkout, and the comment above the function promised the opposite.
- iss-2609300711402515The drain eligibility reader admits a candidate record that states a non-drain key twice: drainrule.Load narrowed frontmatter.Duplicates to drain_ keys, so status: accepted followed by status: superseded loads and applies on the line scanner's first-wins reading, while any YAML reader (last wins) calls the record superseded. The same reader read every store record uncapped (root.ReadFile) and trusted a frontmatter id that disagrees with the file name.
- iss-2609300726419415The colon test of ${@:-w}, ${*:-w}, ${@:=w} and ${@:?} is taken on the parameter count, not on a joined value, but the guard read them as a single empty parameter does (the empty value never printed), a regression from iss-2609300651127327. With set -- "" "" (a script called as clean.sh "" "") bash 3.2, /bin/sh, dash and bash 5.3 hand rm the home for rm -rf $HOME${@:-x} and $HOME${*:?}, and / or /* for rm -rf ${@:-x}/*, ${*:-x}/ and ${@:?}/; all were allowed.
- iss-2609300726507446Structural closure of iss-2609300651115290's class: an IFS assigned through a name built from an expansion still passed the guard in contexts the per-context reading never reached. I=I; : $[${I}FS=1], a[${I}FS=1]=x, : ${a[${I}FS=1]}, declare -i n; n=${I}FS=1, (( ${I}FS++ )), : ${X:${I}FS=1} and x=${I}FS=1; : $((x)) each set IFS in bash 3.2, /bin/sh and bash 5.3, which then hand rm "" and / for rm -rf ${U:-1/1}; all were allowed. Rounds 1 and 3 each listed the contexts that can set IFS and each re-verify found another, so the fix is one fail-closed rule, not another context.
- iss-2609300751191426Rulings CF1 and CF2 of 2026-09-30 are not built: the blocked pre-start check still refuses a blocker whose supersession chain ends at an accepted ADR, and a blocker reclassified as a discipline. The person ruled, through the run's interviewer on 2026-09-30: 'CF1 blocker replaced by an accepted ADR: COUNTS AS SETTLED (the waiting intent may start)' and 'CF2 blocker reclassified as a discipline: COUNTS AS SETTLED (the waiting intent may start)'. At base 85d0bb8eb, followBlocker in internal/core/intent/startcheck.go stops an ADR successor with the problem 'adr-N is not an intent: a decision replaced the blocker, and nothing on the record says that settles the edge', and startBlockedRow counts only a final record in shipped/ as settled, so a chain ending in disciplines/ blocks its dependants for ever. Lane supersededBlocker asked both questions rather than building them; no live edge hits either shape today (itd-72 is superseded by adr-37 and blocks nothing), so nothing is refused wrongly yet.
- iss-2609300756163382The SHELL rules domain teaches only the bundled hazard registry: an entry a repository adds in its own .abcd/guard.json is refused by the guard but never taught before shell work, so the teaching plane and the execution plane of itd-103 part in exactly the repositories that extended the registry. Ruling CK1 (2026-09-29, the product thinker): teach a repository's own guard entries in the SHELL domain, generated the same way as the bundled registry.
- iss-2609300805090515The provider configuration's diagnostics (oracle.APIConfig.Diagnostics: a role outside the roster, a route to an unconfigured provider, and a repository's route to a keyed provider skipped under ruling CD2) reach the person only through 'abcd ahoy --providers' (its board) and 'abcd ahoy credential' bare (stderr). 'abcd ahoy connect' (oracle.Connect loads the configuration and drops them) and the bare 'abcd ahoy' provider-adapter gap (detectProviderAdapter) say nothing, so a skipped route is silent there.
- iss-2609300805371434A provider that reports model "" is accepted: openaiapi's decode records ModelReported empty and returns the answer, so the record cannot show what answered and no oracle.denylist entry can ever match it (internal/adapter/openaiapi/client.go decode).
- iss-2609300812525892Round 5 of iss-2609300651115290's class, a regression the round-4 fix (84ad332c5) opened: the IFS rule keyed on the bytes written beside an expansion, but bash sets the variable an assignment target's VALUE names, so a target written as expansions alone names IFS with no I, F or S byte (reverify4-guardSet finding 1). a=I; b=FS; (( ${a}${b} = 1 )) and x=$a$b; (( $x = 1 )) set IFS to 1 on bash 3.2 and 5.3, and an unquoted default delete after them then hands rm the root; 282908797 blocked both, b993017e8 allows them. Siblings: (( ${x^^} = 1 )), (( ${x@P} = 1 )), a spaced operator in a string arithmetic reads (declare -i n; n="$y = 1"), a substring offset, ${!x:=1}, and a nameref (declare -n r=$x; r=1), which no round read.
- iss-2609300839021188Twelve shipped surfaces have no brief chapter under 04-surfaces/ naming them: the verbs abcd rules, abcd spec and abcd spec close, and the agents cold-reading-comparative, cold-reading-detection, cold-reading-entailment, cold-reading-widening, graveyard-interpreter, press-release-composer, ruthless-reviewer, security-reviewer and sota-researcher. The doc-fidelity gate's layer 1 (itd-60) found them on its first run over this repository; they are recorded in the gate's baseline so spec close stays usable, which reports them on every run and refuses nothing for them.
- iss-2609300841407812A drain run in a checkout holding only an older release tag takes a record a person deferred past a newer one. liveDeferralAnchor (internal/core/capture/eligible.go) reads the checkout's newest local tag as the anchor, and eligibility compared deferred_after to it by equality, so a clone not fetched since the last cut (a stale worktree, a --no-tags remote) read a deferral past the newer tag as lapsed and made the record eligible. A deferred_after that is not a release tag at all (hand-written 'next') was let through the same way. Reproduced on b93f4cdd3 by reverify-drainOwnRule: clone holding v0.1.0 only, record deferred_after v0.2.0 reads eligible.
- iss-2609300841466575The drain rule's decision store is followed through a symlink that resolves inside the checkout, while a record that is a symlink is refused wherever it points. drainrule.Load reads .abcd/development/decisions/adrs through os.Root, which follows a link staying inside the root, so a linked store (or a linked directory above it) loads a rule from a path the checkout does not commit as the store; a store linked out of the checkout was refused only by os.Root's escape check. Named as INFO by reverify-drainOwnRule on b93f4cdd3.
- iss-2609300848016421itd-2609201916056194 (the CLI runner) and itd-2609201916151817 (the implement loop) each declare builds_on the other, so the dependency graph that sequences work (adr-2609212115255771) holds a two-node cycle and neither can be ordered first. The loop's record states its edge (it calls the runner for each lane, decision 5 and its builds_on note); the runner's record gives no reason for its edge on the loop. Found by a read-only sweep of planned and draft edges; record-lint has no cycle rule, so the gate passes it.
- iss-2609300903497125record-lint did not check dependency edges against supersession or cycles: an intent's builds_on or blocked_by naming a superseded intent passed (record_schema checks existence only), and so did two intents building on each other; the base tree carried eleven such stale edges and the runner and loop cycle with record-lint green
- iss-2609300903551032Two more builds_on cycles sit in the intent store beside the runner and loop one: the drafts itd-14 and itd-15 each declare builds_on the other, and the planned itd-2609081951381895 (the OpenAI-compatible API oracle adapter) and itd-2609170822093401 (the oracle choice is one repo-wide value) each declare builds_on the other; record-lint's edge_cycle rule reports both
- iss-2609300905174086Consent gates judge /dev/null a terminal: term.IsTerminal is a character-device test, so stdin redirected from /dev/null (and a closed fd 0, which the Go runtime reopens on /dev/null) reads as a person at a terminal. The tool-install question is printed to stderr, EOF reads as no, and the decline says 'answered no at the terminal' instead of 'no terminal to ask at'; the itd-131 identity offer asks the same way, and the provider-key reader in ahoy_connect.go hand-rolls the same check and refuses /dev/null as 'stdin is a terminal'.
- iss-2609300905225841A program inside the checkout counts as installed: ahoy's onPath is a bare exec.LookPath, so a gitleaks or trufflehog that PATH resolves inside the repository reads as present, and ahoy neither reports the dependency gap nor offers the install, while the installer itself refuses the same resolution as repository content (tools admit). The gh offer on feat/ahoy-offer-gh reads gh presence through the same onPath and inherits the gap.
- iss-2609300916451435A repository guard.json entry's why and successor are unbounded: the SHELL teaching plane injects both word for word, so one committed entry with a 240 KB why pushed every other domain, bundled hazards included, out of the 64 KiB injection budget; guard.Validate checked only that they are non-empty, 03-configuration.md's 'about a hundred tokens' per entry was a hope rather than a bound, and the truncation trailer always blamed .abcd/rules.json even when guard.json filled the budget.
- iss-2609300916459279Under a committed disabled: true guard registry the SHELL teaching plane still opens every lesson with 'Refused by the guard' or 'Warned by the guard', a false sentence because a disabled registry refuses and warns about nothing; this holds for the repository's own entries and for the bundled ones alike.
- iss-2609300916465620noteWithheld compares a rules.json override of a guardrail domain against defaultRuleSet rather than the base Load built, so a SHELL override that omits a lesson taught from the repository's own .abcd/guard.json never names it (the note says WITHHOLDS 17 of its 17 and leaves the repository entry out), and the note calls every withheld entry one 'abcd ships'.
- iss-2609300929557796A repository's .abcd/config.json can still take every command that reads the provider configuration down (ahoy credential, ahoy connect, the providers board): a route in oracle.roles or oracle.judgements whose name is not a plain lower-case name (the review probe used a Cyrillic U+0456 in scribe) or whose value is not <provider>/<model> refuses the whole configuration in LoadAPI, which ruling CD2 of 2026-09-29 (other commands keep working) says a repository route must not do. The refusal also echoed the repository-authored name to the terminal unescaped, so a lookalike letter read as the plain name it imitates.
- iss-2609300939590291Once-only breaks under concurrent session starts: ahoy.TakeUnseenUpdate read the cache/update-shown marker, then wrote it with a create-temp-and-rename, a read-then-write with no claim, so N sessions starting together in one plugin root (an autonomous run does this within a second) each saw no marker and each showed 'abcd updated from X to Y'; a 16-goroutine probe on one seeded cache showed the line 16 times, breaking the ruling CJ1b's once-only.
- iss-2609301000153822Two ADR files claiming one id are read first-wins: recordid's resolver kept the first path in name order for an id two files claim, and record-lint had unique-id rules for intents, issues and specs only, so an accepted 0037-a.md beside a proposed 0037-x.md settled every reader of adr-37 (abcd adr-37 rendered the twin; a start-blocker check reading the status would settle on it).
- iss-2609301002043276The delimiter detector TestNoPrivateDelimiterCompare fails on the tip that carries the drain's own-rule reader: internal/core/decide/decide.go spells four frontmatter delimiter literals against an allowlist of two, because renderStated (added with decide.CreateStated for the ahoy drain-rule offer) cuts the skeleton it just rendered at its close with a private strings.Index search for the delimiter and writes a second block. The lane gates of that change ran only the touched packages, so go test ./... fails at internal/core/frontmatter.
- iss-2609301046113575A comment in the guard's IFS-split test (TestDefaultWordsSplitOnANamedIFSTheWrittenCompareReads, internal/core/guard/guardset_test.go) names a real macOS home directory, the developer account's own absolute path, as its example HOME, so abcd lint's privacy-hygiene rule fails the tree it lands in; it arrived with lane drainTrim and was found by integration 24b-2 before it reached main.
- iss-2609301046433372the loop's records commit claims no assistance for model-written text and skips the commit hooks: land.go stamped the landing's records commit Assisted-by: None and made it through pickGit (core.hooksPath=/dev/null), though its diff carries prose a model composed (the implementer receipt's resolution note and grounds, the audit's verdict ingested into the intent), so the disclosure was false and the commit-msg outbound gate never judged it
- iss-2609301128211767The loop admits a zero-padded issue key: issueIDRe in internal/core/implement/loop/receipt.go is ^iss-[0-9]{1,20}$, so abcd build iss-02609292352131344 opens a run keyed by the padded spelling, which the brief, the DECISIONS lookup, the branch, the PR title and capture resolve all carry, and which drain's == dedupe of runs misses (review-drainLoop finding 1).
- iss-2609301128253254A lane brief quotes text raw between its begin/end comment fences: internal/core/implement/loop/issuebrief.go writes the remedy and the issue record, and brief.go the intent, the spec and the conventions, unescaped, so quoted text carrying an end marker closes its fence early and what follows reads as the brief's own words (review-drainLoop finding 2).
- iss-2609301245517138A retrospective written during an embark is replaced silently: reflect write takes no lock, and embark's writeEmbark writes each planned create through a rename-over (writeIntoLifeboat, fsutil.WriteFileAtomic), so a retrospective reflect write creates between embark's rejudge and its write is replaced by the lifeboat's copy with no conflict.
- iss-2609301251469172the doc-fidelity gate fails open three ways: Record saves a PROMOTE whose failing list names a false brief sentence and Judge lets that match proceed; a new undocumented surface listed in doc-fidelity-backlog.json passes layer 1 as backlog with no chapter, and nothing enforces the claim that the list only shrinks; and Record accepts a multi-line or unbounded sentence, which Apply then replaces across several lines of a chapter
- iss-2609301303434847A handed-back implement-loop run names no way out: handedBackRefusal's remedy (internal/core/implement/loop/handback.go) says only that the loop starts nothing further, and build next's exclusion of the intent (next.go) says 'resume it with abcd implement step', a step that refuses on a handed-back lane. The run stays live by construction (State.Complete is false at handed-back) and no verb clears it, so the person is told of no way to start over.
- iss-2609301307566557abcd implement record --transcript stores each transcript through the history capture but drops the capture's scan gap: in a repository that armed gitleaks where gitleaks is not installed, the run's transcripts are stored with the native scanner only and neither the text render nor --json says so, while history capture names the gap (iss-2608291814575788). The run record's transcript entry carries no field for it.
- iss-2609301519558538Deferred, owed to a person: the live proof of the command-line runner (itd-2609201916056194). Phase 1 and 2 prove every criterion on fake harness binaries only; no ruling admits a live check of the runner (ruling L names the site setup, the API adapter and the decision adapter; H8 lists the three paid-service checks and itd-6's RepoPrompt run), so the intent cannot close. What a person must run: (1) the intent's first proof, criterion 7 live: a ruthless review of a real lane routed roles.ruthless-reviewer.runner=opencode, from a lane the host drives, its return recorded beside a host-run review's and differing only in the route; (2) the claude runner under --bare with --permission-mode dontAsk and --allowedTools, confirming a nested claude does not refuse under an inherited CLAUDECODE, and noting that the headless page (read 2026-09-30) says bare mode never reads OAuth or the keychain, so the claude runner needs ANTHROPIC_API_KEY, a paid API key rather than the person's subscription; (3) opencode run --format json --pure: the event shape (the CLI page does not document it; the adapter assumes step_start/text/step_finish with a sessionID and a part) and whether run mode prompts for a permission, which the timeout bounds and records as a fallback.
- iss-2609301557141123The claude runner takes the model its harness's init event reports unbounded and unshaped into the answer (internal/core/runner/claude.go parseClaude), and the loop writes it into state.json through the route record; a model string over 4 MiB pushes state.json past its read bound, so every later read refuses and the run is bricked, and control bytes travel into the record verbatim.
- iss-2609301557191251The runner's admit (internal/core/runner/proc.go) starts a harness binary resolved on PATH even when the binary, or the directory PATH reaches it through, is writable by group or other: a chmod 777 directory holding claude was admitted, so any account that can write there chooses what the loop runs with the person's credentials.
- iss-2609301858349258The loop armed auto-merge in a project whose rules require no approval: the implement loop's arm step (internal/core/implement/loop/land.go landArm) armed 'gh pr merge --auto' wherever the ruleset mirror named a merge queue, without reading whether any ruleset requires a person's approval, so in a managed repository with a merge queue and no review rule, agent-written code merged on CI alone.
- iss-2609301913458174Concurrent audit ingests file duplicate owed-check issues. Two or more ingests of one failed after-merge audit verdict each ran fileAuditOwed's open-issue scan (internal/core/capture/auditowed.go) outside the ledger lock, saw no carrier, and each filed an issue: four goroutines filed four, none linked. An ingest whose intent write failed after its filing left the same shape, an open carrier no flag names, and a passing re-run resolved only the flagged one, leaving the rest open.
- iss-2609302205483845namesCodeOwners (internal/core/implement/loop/land.go) is looser than the forge's CODEOWNERS parse: it counts any non-comment line as naming an owner and ORs all three CODEOWNERS locations, so a code-owner review arms auto-merge where the forge asks nobody: a line '* @' (an owner-less token), a pattern-only line, and a comment-only .github/CODEOWNERS shadowing a root CODEOWNERS that names an owner each arm (review-amApproval, minor).
- iss-2609302207449478A passing after-merge audit ingest resolves the open owed-check carriers of its receipt only when the intent carries the audit-owed flag, so a carrier left open on an unflagged receipt (an ingest that filed it and then failed to write the intent) outlives the passing audit; and brief 05-intent.md's audit-ingest row still ends '(may capture or resolve one issue)', though a failed ingest may decline extra carriers and a passing one resolves every carrier (reverify-dq1cFlag, minor).
- iss-2609302210137965When abcd site build adds missing interface labels to the repository's ui.json (addMissingLabels, the TG1 ruling) and the build then fails, the error returns an empty Result, so the CLI never names the labels it wrote: the person's file changed and nothing said so, against ADR 2609301720596683's 'the change it takes is visible' (review-tgLabels, minor).
- iss-2609302305500526A ledger verb's refusal of an id the ledger does not hold writes to the tree: in a git checkout with no ledger, capture resolve, wontfix, link, defer, promote and remedy over an id the ledger does not hold each exit 2 as the capture chapter promises (06-capture.md:294-300, 'nothing written') but leave .abcd/work/issues/.iss-alloc.lock behind, creating the directory chain (lock name internal/core/capture/alloc.go:19). abcd's own .gitignore hides it here; in any other repository it shows as an untracked file. Refusals caught before the lock is taken (a missing --impact, a lone word) leave the tree empty. Found by the v0.12.0 release-gate brief-surface cross-check (x-025, checker a05), reproduced by the classifier at b89784c4; standing since before v0.11.1.
- iss-2609302306003610The surface appendix generator labels /abcd:version a host-delegated command page: HostDelegatedSentence (internal/core/surface/appendix.go:84) is emitted for every shipped register row with no registered verb, so the generated appendix of 12-version.md:147 says the command page is host-delegated and has no flags, while commands/version.md runs the binary's root --version flag and record-lint.json's host_delegated list holds only consult, ingest and prepare-this-repo. The generator, not the prose, is wrong, and it re-emits the error on every regeneration. Found by the v0.12.0 release-gate brief-surface cross-check (x-039, checker a11, and its duplicate x-118, checker b00); the generator is new in the v0.12.0 cycle.
- iss-2609302306019245The guard's foldParents comment (internal/core/guard/match.go:883-885) says a trailing . after a .. is folded, but rm -rf ../. is allowed: the fold of a trailing . happens only past a first segment (./../., $PWD/../. and x/../../. warn on rm-rf-working-directory), while ../., ../../., ./. and /. all allow. Harmless in practice, since rm refuses a path whose last segment is . or .., but the comment promises a reading the code does not make and no test in internal/core/guard names ../. at all. Found by the v0.12.0 release-gate docs review of 4d634c4f0 (a HOLD on 17-guard.md:426, whose sentence c8ddb0425 narrowed to ./../.); pre-existing from 4ef5013bd.
- iss-2609302306153318docs fidelity record and docs fidelity --apply disagree on the shape of a verdict's chapter: record checks only that a failing entry's chapter is non-empty (internal/core/docfidelity/store.go:248-249), so it saved a HOLD naming "04-surfaces/17-guard.md", and --apply then refused that same verdict with "the edit's chapter ... is not a chapter file under .abcd/development/brief/04-surfaces" (Apply's one-component chapterNameRe, internal/core/docfidelity/apply.go:31,64). A verdict the recorder accepts cannot be applied, and the reviewer has to re-record it by hand. Found while applying the v0.12.0 release-gate docs review of 4d634c4f0 (the correction landed as c8ddb0425).
- iss-2609302306281487Thirteen v0.12.0 docs-currency findings are deferred past the tag, all minor or nitpick: dc-3 (CHANGELOG.md:37 and RELEASE.md:35 call a role-word ban a bundled docs-lint rule; it is a pattern in this repository's .abcd/docs-lint.json), dc-4 (CHANGELOG.md:21 preamble vs the two breaking bullets filed under Added), dc-6 (commands/ahoy.md:23-24 a status argument the binary refuses), dc-8 (commands/ahoy.md:4 argument-hint omits credential), dc-10 (commands/capture.md:4 argument-hint omits mentions), dc-11 (commands/capture.md:633-635 widening_runs sits under reading_outstanding), dc-12 (commands/docs.md:4,75-118 omit docs fidelity --intent), dc-13 (commands/history.md:4 ingest hint omits the required --into), dc-14 (commands/implement.md:42-54 omit join --model and --reason), dc-16 (commands/ingest.md:4,119 no User input line for its argument-hint), dc-21 (commands/launch.md:4 argument-hint omits receipts), dc-22 (commands/launch.md:1035 names the project abcd-cli), dc-24 (resolved iss-323's resolution says all three salvage entries declare the 120-second timeout; only UserPromptSubmit does since 6a40c898b). Found by the v0.12.0 release-gate docs-currency review (Fable 5.1, tier full) over b89784c4.
- iss-2610010618373016The conventions-file block ahoy writes into a managed repository's AGENTS.md / CLAUDE.md (template internal/core/ahoy/defaults/claude-md-marker-block.md) names two paths that exist only in abcd's own source tree: .abcd/development/principles/ (the OPINIONS paragraph, 'the canonical conventions under .abcd/development/principles/') and .abcd/development/brief/05-internals/03-configuration.md (the closing 'For internals see …' line). Both sit inside the abcd-managed fence, so the adopter cannot hand-fix them: ahoy rewrites the block on drift. Met in practice in a managed repository whose CI pins v0.11.1, relayed by a peer session; that repository holds its own record deferred until abcd ships the fix. The principles half shares its ruling with iss-2608210934566220 (the injected OPINIONS rules' dangling pointers); the 03-configuration.md pointer is independent of that ruling and fixable on its own. Expected: the managed block names only paths that exist in the managed repository, or names them as abcd-repository locations.
- iss-2610020700263496ahoy install discards the explicitly passed --docs-target, --visibility and --oracle-backend values when the scan_deep question is answered out of set, and says neither that it did nor why. stepConfigValues collects every config value and persists them in one write only after the last question is answered; on a private repository with trufflehog on PATH it asks scan_deep, the documented 'yes |' form answers 'y', which is not in true|false, so the step returns nil and nothing is written. .abcd/config.json keeps only attribution and meta; the run ends 'partial' with remaining gaps config.docs_target_missing, config.oracle_backend_missing and config.visibility_missing, the three values the operator passed as flags, never scan_deep; no note says the scan_deep answer was refused; and the receipt's remedy, 'run abcd ahoy install again and answer y to each question', repeats the cause. The neighbouring artefact_kind question treats the same 'y' as its default with a note naming the answer. The bare detection pass cannot preview the question, because config.scan_deep_missing is raised only once visibility=private is persisted, not when it arrives as a flag. Reproduced at tip with: yes | abcd ahoy install --adopt --docs-target agents_md --visibility private --oracle-backend host-delegated --attribution (scratch repo, trufflehog on PATH). Adding --scan-deep false saves all four values and plants the block in AGENTS.md only. On v0.9.0, whose docs target defaulted to both, the dropped docs target is what planted the block into CLAUDE.md as well as AGENTS.md (the default became skip in dae705d5).blocks iss-2610121224332411
- iss-2610020700521421ahoy install writes the home-scope transcript store without previewing it, and under a category that does not name it. The detection preview lists the user-state gaps history.bootstrap_missing and history.meta_missing (meta.json and the index entry) and nothing for the transcript store, yet the install writes ~/.abcd/transcripts/<root-sha>/records. stepHistory bootstraps ~/.abcd/history/index.json when either user-state or safe-autocreate is approved and opens the transcript store on safe-autocreate alone, so at tip a run answering y to safe-autocreate and n to user-state still wrote ~/.abcd/history/index.json and ~/.abcd/transcripts/<root-sha>/records: a person who reads the preview and declines the home-directory category still gets two writes in their home directory. If the safe-autocreate route is intended, the preview and the category question have to say so.
- iss-2610020700529281The managed block ahoy install plants into an adopted repository's conventions file when a docs target is chosen (internal/core/ahoy/defaults/claude-md-marker-block.md) is abcd's own rule-loader section copied verbatim, and it breaks the repositories that receive it. (a) It ends 'For internals see .abcd/development/brief/05-internals/03-configuration.md' and says OPINIONS points at .abcd/development/principles/; both exist only in abcd's own repository, so they dangle in every adopted one. (b) At tip it is 98 lines with em dashes on 10 of them, so a repository whose own AGENTS.md rules bound file length, ban em dashes or require every link to resolve fails its own gate on the block. (c) Its header says /abcd:ahoy 'silently overwrites this block on drift (per itd-3)', citing an abcd-internal record id, so the adopter cannot trim it to fit. (d) It is inserted directly under the H1, ahead of the repository's own opening text. This record is intent-shaped: the ask is a capability, a short pointer variant of the block for adopted repositories (a few ASCII lines, no repository-internal links or record ids) or keeping the long text where consumer repositories never commit it; routing it to an intent is the product thinker's call. Related: iss-2609110944498549 (resolved, the default docs target is skip) and iss-2608210934566220 (the injected OPINIONS pointers dangle in managed repositories).
- iss-2610020704152047ahoy install's .gitignore block repeats .abcd/.work.local/ when the file already lists it outside the block. In a scratch repository whose .gitignore held 'node_modules/' and '.abcd/.work.local/', a private-visibility install at tip appended a fenced block carrying '.abcd/.work.local/' again, so the file holds the same entry twice and the repository's own line is left as the redundant one. The fence writer does not consult the lines outside it.
- iss-2610020704152920banlist.hooks_path_armed reports false, in the bare ahoy status and in --json, when the committed .githooks/ hooks are reached through a global core.hooksPath dispatcher that chains to them: a false negative. hooksPathArmed (internal/core/ahoy/banlist_scaffold.go) reads only git config --local core.hooksPath and compares it to the clone's .githooks, so it cannot see a global hooks path, and it never asks whether the hook actually runs. Reproduced at tip with a scratch global gitconfig whose core.hooksPath names a dispatcher that runs <toplevel>/.githooks/pre-commit and then .git/hooks/pre-commit: 'git hook run pre-commit' ran abcd's name guard and exited 0, yet hooks_path_armed was false and the bare status said '(arm this clone: git config core.hooksPath .githooks)'. Following that advice sets a local core.hooksPath that overrides the person's global dispatcher in this clone, dropping whatever else it chains, so the false negative turns into harmful advice. Related: open iss-2609120447480903 proposes raising a gap on hooks_path_armed=false, which would make this a false gap.
- iss-2610020704163406The comment line of the .gitignore block ahoy install writes into an adopted repository uses an em dash ('# abcd-managed block — do not hand-edit. Run /abcd:ahoy to refresh.'), so a repository whose own writing rules ban em dashes or non-ASCII in committed files fails them on a line it cannot edit, since the block is managed. Reproduced at tip with a private-visibility install into a scratch repository. Sibling of the conventions-file block's em dashes (iss-2610020700529281).
- iss-2610020705158672ahoy install's stale-binary refusal ('abcd ahoy install — refused') exits 0, so a script or agent piping the install sees success while nothing was installed
- iss-2610020718369838The release cut's dry run does not say which targeted intents the cut will move to next. renderCut (internal/surface/cli/ship.go) prints one 'targeted:' line per targeted intent, and the line is the same for a target the cut leaves standing (a tag above the derived next tag) and one it rewrites to next (next itself, or a tag at or below the derived tag); launch.MissedTargets, which decides the move, has one caller, the cut's ingest (internal/core/release/ingest.go), so the move is first visible in the changelog section the cut writes. A reader of the dry run has to compare each target with the derived tag by hand. Not a breach: the intent's criterion 3 is worded to the cut and commands/launch.md matches the code (review-targetNext, MINOR 3).
- iss-2610020722584184A repository's oracle route that cannot apply takes the configuration or the person's setting down: a route in .abcd/config.json naming a model a configured keyless provider does not list refuses the whole provider configuration load (every command that reads it fails), and a route there naming a provider this machine has not configured wins over the machine's own route of the same name, so the role runs on the host and displaces the person's setting. Both disagree with ruling CD2's shape for a repository's route (skip with a diagnostic, the machine's route applying in its place).
- iss-2610020723185314A repository's committed .abcd/config.json can hand a role to a command-line runner (roles.<role>.runner: claude or opencode), so a checkout decides when the person's paid key is spent on its behalf; and the opencode runner is sealed only against plugins (--pure), so the repository's AGENTS.md, CLAUDE.md, opencode.json, project agents and skills still reach the run.
- iss-2610020726165588Bare abcd ahoy remote prints the sub-verb's help and exits 0, while the shipped itd-2609212130136102 acceptance criterion ac-1 says bare ahoy remote answers naming --remote and exits non-zero, and its audit evidence still cites the markMoved stub in internal/surface/cli/cli.go that the v0.12.0 cycle removed. Read against the record this is not a regression: the intent's scope bounds the moved-spelling answers to one release, the product thinker's rulings BT1 and H6 (2026-09-29) removed them in the breaking v0.12.0 cut, iss-2609251324599468's resolution says bare ahoy remote lists its sub-verbs instead of answering with a successor, docs/how-to/upgrade-to-v0.12.0.md documents that it lists them and exits 0, and TestBareIdentityAndAhoyRemoteListTheirSubVerbs pins it.
- iss-2610020726287561The implement loop's composed commits declare Assisted-by: None, a false disclosure for tool-touched text: the pick's record-only commit (internal/core/implement/loop/pickcommit.go pickMessage) and the sync's merge commit (sync.go) carry text the abcd binary computes from the run's state and records, yet both end with Assisted-by: None, which AGENTS.md defines as the declaration that no tool touched the work and calls a false disclosure when a tool did. No model wrote that text either, so a vendor trailer would be false too: the convention has no truthful form for a commit abcd composes.
- iss-2610020727129199The site's authorship tally counts the abcd label as an AI model: internal/core/site/contributors.go LoadAuthorship treats every Assisted-by value other than None as assistance, so a commit carrying Assisted-by: abcd:<version> (the label the implement loop's pick and sync commits carry under ruling PC1) is added to AssistedCommits, charted as a model bar named abcd:<version>, and adds abcd to the vendor set, and the comment at contributors.go:183 still calls None the only accepted non-vendor value. The label says abcd composed the text and no model wrote it, so publishing it under a heading that lists assisting models misstates the disclosure. Latent until the first loop commit lands on the default branch.
- iss-2610020727177336The implement loop's pull-request body carries no Assisted-by trailer, so the required attribution check refuses every pull request the loop opens: internal/core/implement/loop/land.go prBody ends with only the Delivers: and Resolves: trailers, and .github/workflows/attribution.yml runs scripts/check-attribution.sh body on every pull_request event not authored by a bot, which fails a body with no Assisted-by line. The body is text abcd computes from the run's records (its first sentence says so), but the change it describes carries the implementer's model work, and a squash merge can take the body as the commit message. Latent until the loop's first live landing in a repository running the gate.
- iss-2610020728118137Both enforcement points of the doc-fidelity gate (itd-60, ac-1 and ac-4) skip the whole gate when the population is empty: enforceDocFidelity returns nil on len(population)==0 (internal/surface/cli/docfidelity.go:55) and the release emit runs docfidelity.Gate only inside 'if len(shipped) > 0' (internal/core/release/emit.go:272). So a spec close that ships no intent and, more consequentially, a release cut carrying only issue resolutions (a patch release) run neither layer, layer 1 included: a sub-verb or agent added by an issue fix in such a cut meets no coverage floor at the cut, while the spec says the deterministic floor 'is cheap enough to run at every enforcement point and in CI'. The bare 'abcd docs fidelity' with no --intent does run layer 1, so only the enforcement points have the gap.
- iss-2610020728118183The doc-fidelity gate's layer 1 (itd-60, ac-1) counts 04-surfaces/README.md, the surfaces index, as a chapter: ReadInputs lists every regular *.md under 04-surfaces/ (internal/core/docfidelity/store.go:70) and names() accepts a code span in any of them, so at main 7fb52a6b5 the verb 'abcd spec', its sub-verb 'abcd spec close', the verb 'abcd rules' and the agent 'sota-researcher' pass the coverage floor on the README alone (abcd docs fidelity --json: coverage rows with chapter README.md), while no numbered chapter names them and no generated appendix (invariant 18) states their flags. A one-row index entry satisfies the floor for any new surface, which is the placeholder the spec's 'named by a chapter under 04-surfaces/' exists to refuse.
- iss-2610020728128805Ruling DR3, on which the doc-fidelity gate's shape rests (itd-60, ac-2: the semantic layer is a saved receipt for HEAD that spec close and launch ship find automatically, rather than a review invoked at the close), is cited by three source files (internal/core/docfidelity/store.go:4, internal/core/docfidelity/docfidelity.go:14, internal/core/lint/gatereceipt.go:10) but recorded nowhere in the committed record: the 2026-09-30 entry [dcn-2609300000000009](../../decisions/dcn-2609300000000009-the-person-answered-eighteen-rulings-of.md) restates DR1, DR2, DR4, DR5 and DR6 and skips DR3, whose text lives only in a local-tier rulings file this checkout cannot cite. The fidelity audit of itd-60 therefore grades ac-2 as a signed-off divergence on the strength of an uncommitted ruling; a reader of the record alone cannot see why the gate reads a receipt instead of running the reviewer.
- iss-2610020728592612The sentence every derived changelog section carries (sectionNotice, internal/core/release/ingest.go) says changes to earlier behaviour are not claimed until the composer can see the previous release, yet writableSections files a breaking record, by ruling, as an Added line that states the break, so every breaking cut prints the notice directly above Breaking lines that claim exactly such changes (v0.12.0's section, dc-4 of its docs-currency review, folded into iss-2609302306281487).
- iss-2610020730426636The build loop opens a lane for every ready spec step whatever the ceiling, making its worktree and brief at once (schedule.go move, the eager opening the parallel-lanes landing shipped), so a spec whose steps declare needs: none puts every step's worktree on disk before a helper is free to take it; ruling DR6d-1 (the product thinker, 2026-10-02) says a step's worktree is made just before an agent takes it, at most the agent ceiling's worth on disk.
- iss-2610020730472210A lane whose landing finds no preflight receipt naming its head refuses the whole build step (land.go landPush, a plain refusal), so every other lane stops while one lane waits for its full check, and nothing shows when that wait began; ruling DR6d-2 (the product thinker, 2026-10-02) says the other lanes carry on, the lane waits for its receipt like the merge wait (contend, not refuse), and the status shows 'waiting for its full check (since HH:MM)'.
- iss-2610020731591808The docs-lint ban on the retired role word (itd-2609212137129937, ac-2) reaches the docs roots, the command pages, .abcd/rules.json and the bundled rules source only: .abcd/docs-lint.json's 'roles/retired-role-word' entry lists extra_roots commands, .abcd/rules.json and internal/core/rules/defaults, and the top-level roots are docs and README.md. The brief (.abcd/development/brief, 22 occurrences before the sweep, the largest share), the principles (.abcd/development/principles, 5) and the personas registry (.abcd/development/personas.json) were swept by ac-1 but are in no root the token reads, and the ac-5 test walks only the rendered help, commands/*.md and agents/*.md, so the word can return to the brief or a principle with nothing refusing it, against the press release's 'the word cannot come back' and the mechanism claim that agents say what they read (the OPINIONS domain points agents at the principles).
- iss-2610020836255174The intent record has no way to declare a mutual builds_on pair that record-lint's edge_cycle rule honours. The technical facilitator ruled on 2026-10-02 that three two-intent cycles stay as declared mutual pairs, each direction naming the piece it needs (CY1: itd-2609201916056194 and itd-2609201916151817; CY2: itd-14 and itd-15, itd-2609081951381895 and itd-2609170822093401), but the frontmatter offers only builds_on and blocked_by, and edge_cycle reports every strongly connected set whatever the records say, so the three pairs are declared only in each intent's Audit Notes and still read as cycles to the linter, and to anything that orders work by these edges. Until a declared pair is something the linter can read, edge_cycle cannot be promoted from warn to blocker without refusing the ruled pairs.
- iss-2610020840196926abcd lint's privacy-hygiene rule reports a LAN hostname on internal/core/capture/eligible.go:137, where the match is a Go selector, the field `local` of the value `anchor` joined by a dot, which closes a call's argument list and no hostname at all. The net_lan_hostname pattern's selectorExpression skip (internal/adapter/scanner/network.go) treats a match as a selector only when '(' or '[' follows it, or '=' or '{' after spaces, so a selector passed as a call's last or middle argument, followed by ')' or ',', is reported. abcd lint exits 1 on the warning in a clean tree at 7fb52a6b5.
- iss-2610020922452875The net_lan_hostname exemptions still report a lower-case Go selector whose LAN-suffix field sits in any code position other than a call target or index (selectorExpression), an assignment target or block head, or a call argument closed by ')' or ',' (callArgumentSelector): a case label closed by ':', an index closed by ']', the right-hand side of ':=' or '=' at end of line, a 'return' operand, an operand of '&&' or '||', a composite-literal value or element, and a unary '!' operand are each reported as a LAN hostname (probed at 6d7ae00d2 on fix/scanner-selector-closing-call), so abcd lint warns and Stage-1 redaction rewrites such a line in a stored transcript. No tracked file carries one today; the class is latent.
- iss-2610020958574817TestSecondDispositionForOneItemRequiresSupersedes (internal/core/capture/ingest_reading_test.go) mints two dispositions into one ledger through the production minter (real clock, crypto/rand suffix), so when both land in the same UTC second and draw the same four-digit suffix the second write is refused by refuseExistingRecord as a duplicate id and the test fails. It failed this way in the race lane of make preflight on fix/scanner-selector-closing-call at 6aeaea01b (dsp-2610020953467982 minted twice); the refusal is the ledger's designed behaviour, so the defect is the test's unpinned mint.
- iss-2610021446271464The site's landing page composes its hero quote from the press release of the newest shipped intent whose fidelity audit is MET (internal/core/site/compose.go:1251 newestMetIntent, 1153), and the first ingested audit of itd-60 (shipped 2026-09-30, two days after the role-vocabulary sweep b4df4f25d, which rewrote no intent body) makes that intent the hero: its press release says 'flags it for the maintainer to read', so 'abcd lint site' refuses the render with roles/retired-role-word on index.html and the site-render gate of make preflight exits 2 on a branch that only recorded the audit (chore/audit-v012-gaps at 373d8b5f9, over main 7fb52a6b5). The sweep intent itd-2609212137129937 scoped intent bodies out, yet a press release is abcd's own text the moment the composer renders it publicly; the retired word stands nine times in itd-60 and ten in the sweep intent's own record, so any later MET audit of an intent carrying it reproduces the refusal, and the landing page's text is decided by which audit was ingested last rather than by a guarded source.
- iss-2610021502084298No check meets the retired role word in an intent's press release at the record: the docs-lint rule roles/retired-role-word roots at the docs, the command pages and the rules, so a shipped or planned intent's press release carrying it is refused only when the site composer renders it as the landing page's hero quote, which is how itd-60's first MET audit broke the site-render gate (iss-2610021446271464). After the R5 reword of itd-60, thirteen shipped press releases still carry the word (itd-65, itd-66, itd-67, itd-69, itd-73, itd-74, itd-93, itd-102, itd-111, itd-114, itd-125, itd-2609111003026787, itd-2609212137129937), so the next MET audit ingested for any of them refuses the render again on a branch that only recorded an audit; the product thinker's ruling R5 (2026-10-02) accepted that a future slip breaks the build and did not ask for this check. Related to iss-2610020731591808, which names the brief, the principles and the personas registry as swept but unguarded.
- iss-2610021542183618The shell guard allows a recursive delete of a chain of parents: `rm -rf ../..`, `rm -rf ../../.`, `rm -rf ../../..` and `rm -rf ../../*` are an allow, while `rm -rf ..`, `rm -rf ../.` and `rm -rf ../*` warn on rm-rf-working-directory. The entry's arg_values name `.`, `..`, `../` and `../*` but no deeper chain, and foldParents reads `../../.` as `../..`, which no value names, so TestTrailingDotAfterAParentFolds pins only that the two spellings agree. A chain climbs above the working directory's parent and holds it, so it deletes at least what `..` deletes. Found by the post-tag security review of 7fb52a6b5..d94472abb (sec-postTagA, LOW); present at both ends of that range.
- iss-2610021542528976capture disposition refuses a malformed answer to an item the ledger holds only after mutationPreamble has run: Disposition (internal/core/capture/reading.go) redacts the request and calls prevalidateDisposition after the preamble, which opens the allocator lock file, so a disposition with empty grounds, a held state with no exit condition, or a state the item's position does not offer exits 2 but leaves .abcd/work/issues/.iss-alloc.lock in a ledger that had none. The file is gitignored and no directory is created, but the capture chapter promises a refusal writes nothing, and admit already checks its request (requireWidening) before the preamble. Found by the post-tag security review of 7fb52a6b5..d94472abb (sec-postTagA, LOW); unchanged from the range's base.
- iss-2610021547096336The shell guard allows a recursive delete of the trailing-slash glob of the parent or of $PWD: `rm -rf ../*/`, `rm -rf $PWD/*/` and `rm -rf ${PWD}/*/` (and so `rm -rf ../../*/`) are an allow, while `rm -rf */` and `rm -rf ./*/` warn on rm-rf-working-directory. `../*/` globs every directory of the parent, the working directory among them, and `$PWD/*/` every directory of the working directory, as `./*/` does; the entry's arg_values name the trailing-slash glob for `*` and `./*` only. Confirmed at d94472abb while fixing iss-2610021542183618 (the parent-chain reading reaches `../*/` and finds no value for it).
- iss-2610030807157970The bundled ROADMAP rule domain still teaches retired phases and milestones. internal/core/rules/defaults/rules.json:34 injects 'The roadmap is intent-driven; each phase ends in a milestone.' into every managed repository on a prompt that names a roadmap, milestone or phase, although adr-2609212115255771 retired the phase, the milestone and the word roadmap (decision 8 replaces this domain with the decision's statement) and adr-2609292012006845 carries that forward. abcd's own repository masks the defect with a repo override (.abcd/rules.json:127-131), so its own sessions never see it; a sibling session's user test of an adopted repository on v0.9.0 reported it on 2026-10-03. The brief-wide sweep iss-2609251618079479 does not name the defaults file.
- iss-2610030931521214The OpenAI-compatible provider adapter sends non-streaming chat requests with one end-to-end deadline, so a long delegated step routed to a reasoning model fails and wastes the provider's work. internal/adapter/openaiapi/client.go:291 renders "stream": false; DefaultTimeout (client.go:63) bounds the whole call at 120 seconds (connecting, sending and reading the entire answer), and only the connect verification passes its own timeout (internal/core/oracle/connect.go:116), so a dispatched step gets the 120-second default; max_tokens is sent only when a route or --route sets it (client.go:81). Evidence from a user test on 2026-10-03 against a keyless local OpenAI-compatible server on loopback: that server's gateway answers HTTP 504 to a non-streaming request whose generation exceeds about 600 seconds, because no headers are sent until the answer is complete, and the model keeps generating up to its token limit after the 504; reproduced twice with two reasoning models on a 44-line classification prompt, while a non-reasoning model finished in 181 seconds. abcd's own 120-second deadline abandons such a call earlier still, and an abandoned non-streaming request is not cancelled at the server. Any proxy or gateway with a header or idle timeout behaves the same way; intent consistency's bundled corpus (about 29k tokens) is the kind of step that reaches it.
- iss-2610030956156354A request sent through the OpenAI-compatible provider adapter is never judged against the chosen model's size before it is sent. In a user test on 2026-10-03, an intent consistency check sent to a keyless local service carried about 29,300 tokens against a model the service runs at about 29,200, and the service refused it with HTTP 400, about 0.5% over. Some servers publish each model's served size in their model list; the standard list has no such field, and a published figure may be the trained size rather than the served one. Routed out of the guided-connect draft itd-2610030821294016 by its record review; a follow-up of the adapter's streaming fix captured the same day.
- iss-2610031012543135This repository's AGENTS.md is 37,109 bytes, past Codex's 32 KiB (32,768-byte) default instruction limit, so a Codex session stops reading before the end of the file and works without the conventions that follow the cut. The one-conventions-file rule (itd-2610030814013772, adr-2610030814023326) changes a count of files, not bytes: a file past a native reader's cap is, for that reader, not one file.
- iss-2610031156150387Batching related judge items into one request beats one request per item on a local OpenAI-compatible model service. A sibling session's measurement on 2026-10-03 (44 labelled lines of banned-term hits and near-misses, one local 8-bit model, streaming, temperature 0, max_tokens from the served context): all 44 in one request scored 41/44 in 181 s and 8,872 completion tokens; one request per item scored 30/44 in 2,487 s (14x) and 116,044 completion tokens (13x). One-by-one lost cross-item context (five false blocks on abcd's own documentation lines, two misses), let reasoning run away (three single items ran 566-589 s and hit max_tokens with no verdict), and paid a fixed overhead per request. abcd's delegated many-item steps (consistency, cold readings) are batch-shaped, so fanning them out per item to a local provider without their context is the losing shape. More data from two further 27B models in both modes is to follow.
- iss-2610031207397996The bare status board ignores the terminal's width: in an 81-column window the receipts line and every long intent title hard-wrap back to column 0, breaking the board's hanging indent (product thinker's screenshot, 2026-10-03). The same render indents rows at 2, 4, 6 and 10 columns, prints Go's raw true/true/[development work work.local] for the first three rows, and lists the next-up intent under both Now and Next, so it reads as a duplicate.related itd-2610031214560142
- iss-2610031210435016A failed provider call's body cut off at its 16 KiB size bound can end inside an echoed key, and the error then quotes a prefix of the key: internal/adapter/openaiapi/client.go reads a non-200 body through io.LimitReader(maxErrorBodyBytes), and providerSaid trims whitespace before bounding the echo to 200 bytes, so a 401 body of whitespace padding followed by the key yields the key's first bytes in the refusal, which the scrub (whole key forms only) does not match. Reproduced at the streaming lane's tip by TestAnErrorBodyCutOffIsNotQuoted/cut_by_the_size; the same read on main has the same cut.
- iss-2610031215428557Investigate whether the question chip ("Product Q1", "Tech Q2") can carry abcd's fixed role colours, the ones the status-line badge already uses for whom a question is for (product thinker amber #f0c052, technical facilitator light grey #e8e8e8, each with dark text; internal/core/statusline/badge.go rolePairs, drawn from internal/livery). The product thinker asked on 2026-10-03, pointing at a screenshot of Claude Code's question tool, where the chip is drawn by the host in its own highlight and abcd supplies only the header text. Findings so far: on the host path abcd cannot colour the chip, because the question tool renders the header as plain text, an escape sequence in it would show literally or be stripped, and brief invariant 13 plus the question check refuse escapes in that text; the role colour already shows on the host path in the status-line badge while the mode names the addressee. On abcd's own plain-Terminal drawing (itd-2610030810370060, internal/surface/cli/ask), abcd draws the chip itself and can colour it.
- iss-2610031236155833abcd's own setup questions break the asking limits its question check enforces. docs_target offers four answers and oracle_backend five, so with the decide-later answer they exceed the four options per question that the check and the host's question tool allow; and under the provisional row estimate artefact_kind (33 rows), docs_target (28), oracle_backend (43), scan_deep (25), visibility (30) and the machine routing offer (42) exceed 24 rows at 80 columns. TestEverySetupQuestionPassesTheLimits holds them as a baseline that may only shrink.
- iss-2610031915386832abcd ahoy install and abcd ahoy remote apply disagree on how a refused run exits: remote apply returns exit 1 when its result is refused or aborted (internal/surface/cli/cli.go, the applyCmd RunE, 'A change that did not happen exits non-zero'), while ahoy install renders every core refusal (the committed .abcd symlink hazard, the stale-binary guard, the retired docs.target refusal) with status refused and exits 0, so a script cannot tell an install that wrote nothing from one that landed. iss-2610020705158672 names the stale-binary case alone; this is the asymmetry across every install refusal and against the sibling verb.
- iss-2610031915495759When ahoy install's settings write does not land, stepConfigValues' rollbackForced (internal/core/ahoy/apply.go) clears the whole change list (a.changes = nil), not only the override echoes stepConfigValues itself added, so a dependency receipt stepDependencies recorded earlier in the same run (a tool installed and verified) is dropped from the result: the person is not told of a tool that was installed.
- iss-2610032027321900abcd ahoy install drops an explicit --visibility or --docs-target flag without a word when the person declines the config-change category while a required setting is still missing: stepConfigValues returns before the settings write, the deferred rollback takes the echoed change back (so the receipt no longer claims it), but no note says the flag the person typed was not applied, so the run reads as if the flag were honoured or ignored by design.
- iss-2610032048280232embark probe mispredicts the marker action for a chosen AGENTS.md that is a directory, a FIFO or an unreadable regular file: ahoy.EnsureMarker's dry run trusts classifyMarker, which folds every guarded-read error except a symlink into markerMissing, so the probe reports install (changed) while embark from, through installMarkerFileLocked, refuses the same file ('it could not be read') and reports skip. The person approves a plan that says AGENTS.md will be installed and the run then skips it; nothing wrong is written and the records land, but the plan was wrong. The embark marker tests ran the not-a-regular-file case through EmbarkFrom only.
- iss-2610032115023656A SIGTSTP sent from outside (kill -TSTP, not the Ctrl-Z key, which raw mode delivers as a byte) stops an abcd process that holds a term.RawSession with the terminal still raw; SIGTTIN and SIGTTOU sent from outside do the same. On SIGCONT the session enters raw mode again and redraws, so only the stopped interval is affected. The fix the security review of the answer loop proposed (catch SIGTSTP with signal.Notify, then signal.Reset and kill(self, SIGTSTP) to stop) does not work in Go: a scratch probe (Notify, Reset, then kill(getpid, SIGTSTP)) showed the process is never stopped, because the runtime keeps its own handler installed for SIGTSTP once it has been notified (runtime sigdisable leaves it while sigInstallGoHandler is true) and that handler drops an unwanted SIGTSTP. Catching it would therefore make SIGTSTP ignored for the rest of the process, Ctrl-Z in cooked mode after the interview included, and would swallow the kill(0, SIGTSTP) RawSession.Suspend stops with.
- iss-2610032144506540internal/core/history/store_boundary_test.go TestStorePathBoundaryScannerIsArmed builds its hostile literals by ranging over storePathNeedles, the scanner's own needle list, so a needle dropped from storePathNeedles shrinks the armed test instead of failing it: the proof that invariant 15's store-path scanner catches each spelling moves with the thing it is meant to check.
- iss-2610032202256580Setup's marker detection reports a conventions file it can never write as a resolvable marker.missing gap: classifyMarker (internal/core/ahoy/marker.go) folds every read error into markerMissing, so an AGENTS.md (or the chosen target file) that is a directory, a FIFO or unreadable raises a required, resolvable gap, install's write then refuses it ('it could not be read'), and the repository stays partial on every run with a gap install promises to close and never can.
- iss-2610032202259011Marker refusal notes carry the conventions file's absolute path through the wrapped OS error: installMarkerFileLocked and removeMarkerFileLocked (internal/core/ahoy/marker.go) wrap the guarded read's error with 'it could not be read: %w', and embark's dry-run refusal (internal/core/ahoy/embark_marker.go) does the same, so the embark result's note, rendered and in --json, prints the target's full path, the account name included, wherever the file cannot be read.
- iss-2610032202263648The embark probe mispredicts the marker for an unwritable target root: with the root at mode 0555, a writable .abcd/ and no AGENTS.md, probe reports the marker as install while from skips it with permission denied, because the dry run (ahoy.EnsureMarker) classifies an absent file as missing without asking whether the folder can take a new file, so the comment on embarkMarker that probe 'cannot mispredict the file or the action' holds only for the state of the file itself.
- iss-2610032205304585abcd creates its home folder ~/.abcd with different permissions depending on which command creates it first: the credential store makes it private to the account (0o700), while ahoy's history store and owned copy make it readable by other accounts on the computer (0o755). On a Mac shared by several accounts, whichever runs first decides whether others can list abcd's home. Found by the dashboard design's security review.
- iss-2610032303183254Setup's marker detection reports an absent conventions file as a resolvable marker.missing gap even when the folder it would be created in cannot take a new file: with the repository root at mode 0555 and no AGENTS.md, detectMarkerDrift raises marker.missing (required, resolvable), install promises to plant the block and its write refuses on every run (permission denied creating the lock or the temporary file beside it), so the gap never closes and each run repeats the promise. The defect is on main: detectMarkerDrift there classifies an absent file as missing without asking whether its folder can take one.
- iss-2610040025088395abcd ahoy install --answers stops with exit 2 at a question the answers file does not answer, and writes no answers record, but it does not always write nothing, as spc-2610030911534855's B3 says it must.
- iss-2610040116409067Two pseudo-terminal tests assert that a panic's message reached the terminal by reading the drained output once, straight after the child exits (internal/surface/cli/ask/pty_test.go, the a-panic-inside-the-loop case; internal/term/raw_child_test.go, the panic-in-a-hook case). The drain goroutine may not yet have read the child's last bytes, so the assertion races it. It failed on the macOS merge-queue runner on 2026-10-03 with 'the panic did not reach the terminal' and ejected an unrelated pull request from the merge queue.
- iss-2610040147016103Renaming abcd's home from ~/.abcd to ~/.abcd.noindex, as the noindex stop tells the person to (mv ~/.abcd ~/.abcd.noindex), moves every git worktree kept in the store under it, and git records a worktree's location in absolute form: after the move each repository lists those worktrees as prunable ('gitdir file points to non-existent location'), and a git worktree prune, by hand or by a tool, deletes their links. Reproduced on a scratch repository 2026-10-04: after mv, git worktree list marks the moved worktree prunable; git -C <moved worktree> worktree repair restores it. spc-2610031309233367 neither names this nor tells the person, and on the product thinker's machine the store holds about thirty live session worktrees.
- iss-2610040202190813The secret scanner's bundled patterns know sk-ant-, sk-proj- and sk-svcacct- keys but no plain sk- key, the shape OpenAI's older keys and many OpenAI-compatible services issue (sk- followed by a long alphanumeric run). The guided connect refuses a typed value as a key only by those patterns (keyLines in internal/core/oracle/connect_guide.go), so a plain sk- key pasted where the guide asks for a model name still passes validModel and is printed in the command; every store-before-commit redactor has the same gap.
- iss-2610040350324314itd-2610030814013772 criterion A8 is evidenced only by a scripted claude -p receipt, not the person's fresh-session receipt its spec requires. The fidelity audit of 2026-10-04 judged A8 MET_WITH_CONCERNS: a dated receipt exists (2026-10-03, Claude Code 2.1.288, the canary word the canary word answered correctly), but it was taken with claude -p in print mode, which by the receipt's own stated limit cannot show whether the session called a tool to read AGENTS.md before answering, records no /memory line naming AGENTS.md, asks a different question from the spec's no-tool wording, and sits under receipts/ in a sibling worktree's local tier rather than at the .abcd/.work.local/logs/agents-md-canary-<date>.md path the spec's Approach names for this checkout. The canary's purpose is to show AGENTS.md was LOADED as instructions, which a print-mode answer cannot distinguish from a file read. The intent's Audit Notes already say the person's receipt was requested on 2026-10-04 and is outstanding; nothing in the ledger marked the gap until now.
- iss-2610040350491915itd-2610030814013772 criterion A1 says 'when setup runs, then it writes AGENTS.md' with the example 'after setup in a new folder the root holds AGENTS.md', confirmed by the product thinker on 2026-10-03, but a bare setup writes no AGENTS.md: docsTargetDefault is skip (internal/core/ahoy/detect.go), so only an install at --docs-target agents_md, or prepare-this-repo, creates the file. The fidelity audit of 2026-10-04 judged A1 MET_WITH_CONCERNS on that difference. The spec (spc-2610031156364295, open design question 1) chose reading (a), keeping the standing ruling that a default install names abcd in no committed conventions file (iss-2609110944498549), and the facilitator decided it without a question; the criterion's example, as the product thinker confirmed it, reads the other way. Either the example is confirmed as holding at agents_md only, or the default is reopened; today the record carries both.
- iss-2610040452174484The secret scanner's bundled patterns know OpenAI's sk-proj- and sk-svcacct- keys but not its sk-admin- admin keys, the third prefix gitleaks' openai-api-key rule names (cmd/generate/config/rules/openai.go: sk-(?:proj|svcacct|admin)-...). An admin key reaches no bundled pattern: the plain sk- rule cannot match it either, since 'admin' is followed by '-'. Every store-before-commit redactor, the launch scan and the guided connect's key check share the gap.
- iss-2610040639162928The plain-Terminal interview guard reads an entry of git's own directory that is a link (a dotfiles-managed .git/hooks, .git/info or .git/config, or a submodule's hooks under .git/modules) by its link text alone, so a role writing a hook or a configuration change where the link leads is not seen, though git follows the link and runs or reads it. Same class as the re-check's N1 for core.hooksPath, which resolves links before reading.
- iss-2610040729344770The record dashboard (/record/) scrolls sideways at 360 and 390 px: the site-screenshots job measures scrollWidth 476 to 482 there on every pull request since 2026-10-03 23:37Z. The cause is not the genealogy timeline, whose svg sits inside its own overflow-x:auto panel and cannot widen the page, and not the four sub-navigation links the job names first, which scroll inside their own bar; it is the Latest decisions panel. A .list row is a two-column grid (auto 1fr) whose title is a plain span, and a grid item's automatic minimum width is its min-content width, so a title holding one long unspaced token sets the width of the row, which spills past the panel and the page. The two ADRs from #795 (adr-2610031751065746 and adr-2610031751066232) carry such titles, a home-relative path with no break in it, and became the two newest decisions on 2026-10-03. Every .list on the site (dashboard decisions, health, status, development, supersessions) has the same shape, so any record whose title holds a long token reproduces it.
- iss-2610040732240935Record pages scroll sideways at 360 px whenever a record's title or source path holds a long unbroken token, and the overflow audit cannot see it. Every ADR minted with a timestamp id shows its source path, .abcd/development/decisions/adrs/<16 digits>-<slug>.md, as one mono span in the side panel's reclinks paragraph, and the run up to the first hyphen is about fifty characters with no break opportunity: /record/adr/adr-2609091248200336/ measures scrollWidth 374 at 360 px. adr-2610031751065746 and adr-2610031751066232 also carry a home-relative path in their titles, which overflows the record page's h1 (scrollWidth 455). The stylesheet sets no overflow-wrap on body, the title or reclinks, so a block whose text has nowhere to break widens the page. The site-screenshots audit samples only the lowest-numbered record of each type (adr-1, itd-1, iss-1), whose paths and titles are short, so these pages have overflowed since timestamp ADRs began without the job noticing.
- iss-2610040739124513The plain-Terminal interview guard reads no worktree entry of the repository's common git directory except the current one's HEAD and config.worktree, and no other worktree's local tier: a role allowed only Write can register a worktree under .git/worktrees/ whose gitdir names its own turn directory (left out of the reading) and plant a push receipt there, or plant one in a sibling worktree's local tier, and preflight-receipt.sh check accepts it so the next push of that commit passes the pre-push gate; it can also repoint a sibling worktree's commondir at a fake common directory whose configuration carries an alias, which runs on the person's next git command there. Neither stops the interview.
- iss-2610040741103264The overflow audit names the wrong culprits when a page scrolls sideways. measure() in site-src/audit/overflow-audit.js lists the first five elements whose box passes the viewport edge, including elements inside their own scrolling container (overflow-x auto, scroll or hidden), which cannot widen the page. On /record/ at 360 px it named the four sub-navigation links and the genealogy svg, both inside their own scroll containers, and never the Latest decisions title span that set scrollWidth 482, which sent the bisect after the timeline renderer. It also reports nothing when the overflow is a text run rather than an element box, as on a record page whose h1 holds a long unbroken path.
- iss-2610040744587676The site-screenshots workflow's path filter rests on a premise this repository has falsified: its comment says a record edit under .abcd/ moves page content without moving the layout the audit measures, so record-only pull requests do not run the audit. #795 added two ADRs whose titles quote a path with no break in it, which moved the /record/ layout past 360 px; the audit did not run on #795 and first failed on the next pull request that touched site sources, an unrelated one, which then carried a red check it did not cause. The wrapping nets of iss-2610040729344770 and iss-2610040732240935 close the one class seen so far by construction, but the comment still states the premise as fact.
- iss-2610040758095861ahoy install seeds .abcd/docs-lint.json with roots ["docs", "README.md"] whatever the repository holds, so in a repository with no docs/ folder the documentation check it has just armed cannot run: abcd lint docs exits 2 with 'roots entry "docs" does not exist', and neither the install receipt nor bare abcd ahoy says the seeded check is broken. Reproduced at 57d5ec9fa in a scratch repository holding only a README.md, after an install given --scan-deep false. A downstream lab reported the check as silently disarmed; at tip the lint fails loudly on a missing root (since iss-2608270500208736, which already named this seed as the trigger), so the defect is the seed its fix left in place, not a silent pass.
- iss-2610040758303107Bare abcd ahoy prints 'staleness: up to date' when the running binary matches its own install's pin, a comparison made from disk alone by design (itd-111; internal/core/ahoy/vintage.go, Staleness), and the line says neither what it compared against nor that abcd update --check is the verb that asks for the newest release. A downstream user on v0.9.0, several releases behind, read 'up to date' as current and kept working against bundled guidance that predated the retirement of phases and milestones.
- iss-2610040758304494embark unpacks a lifeboat whole: every decision, issue, intent, spec and retrospective it carries is written, and any conflict refuses the entire write (brief 04-surfaces/03-embark.md). A downstream user starting a new project from its predecessor's lifeboat wanted only selected records carried across and had no way to choose them, so embark could not serve that use. The whole write is the designed behaviour, so this is a capability gap rather than a defect, and intent-shaped: routing it to an intent is the product thinker's call.
- iss-2610040758387938The disembark probe grounds evidence/open-questions only from open issues and intents, and evidence/tradeoffs only from ADR alternatives and the decision log (internal/core/lifeboat/sources_native.go, nativeOpenQuestionsSource and nativeTradeoffsSource). Neither reads the repository's own brief file for its section (03-evidence/03-open-questions.md, 03-evidence/04-tradeoffs.md), which every other brief section's source reads, so a downstream project with both files authored saw them ignored. A partial verdict also carries no reason: Evidence fills Searched and Question only on a blank, so a section rated partial does not say what was found or what would ground it.
- iss-2610040758394205The bundled INTENTS rule tells every managed repository 'Personas are always Alice, Bob, Carol — never other names.' (internal/core/rules/defaults/rules.json), a fixed roster of three that a repository can change only by overriding the whole INTENTS rules field in .abcd/rules.json. abcd's own repository does exactly that to point at its own persona registry (iss-2608211849583208), so its sessions never meet the cap. A downstream owner wanted a fourth persona and the rule forbade it; the lab proposed an open naming sequence (Alice, Bob, Carol, Dave, and on) with each persona's role declared by the repository.
- iss-2610040758485431Four gaps in the documentation check's banned-names support, met by a downstream project: (1) a name family the repository may later remove has no include file, so its entries sit inline in .abcd/docs-lint.json and removing the family means deleting each by hand; (2) a case-sensitive entry works through the regex flag (?-i:...), but no command page, user doc or brief chapter mentions it; (3) a warning-severity entry never fails any gate, so a warning has no route to being acted on; (4) the docs-lint allow marker records no reason, so an allowed line carries no account of why. The lab also proposed a docs lint --adjudicate mode in which a judge model rules on each match in context: in its own measurement a frontier model judging in session agreed on 97.8% of 280 held-out lines and missed none, and locally run judges reached about 90%.
- iss-2610040758486433The lab discipline (itd-2609251624540864) defines a lab as a throwaway world pinned at one commit: a detached clone with no remote, discarded at the end, with knowledge entering the record only through ceremony. A downstream brief-authoring lab ran in the real project repository, whose output (the brief) is the product being kept, and the procedure has no form for that case: its snapshot, record and discard stages all assume the world is thrown away.related itd-2610040822131032
- iss-2610040758569116abcd decide writes an ADR as proposed, and its help says the status stays proposed until the author sets accepted, but no verb sets it: accepting a decision means hand-editing status:, and nothing records who accepted it or when. A downstream project accepting its first decisions did exactly that.
- iss-2610040758571292The LOAD rule domain governs one session's own load experiments (one owned process group, consent with a cap below the core count on a live machine) and says nothing about load another session on the same machine is about to start. A downstream session asked a peer session go, wait until, or not tonight before loading a 17 GB local model, and reported back once the machine was clean; the exchange worked, and the protocol is stated nowhere.
- iss-2610040758579292An intent's blocked_by edges are read by the build gate (internal/core/intent/startcheck.go, startBlockedRow, and the implement loop's check) but no verb writes them: abcd capture link adds and removes blocked_by on an issue, and abcd intent has no counterpart (its link sub-verb links a spec), so a downstream project hand-typed every edge between its intents.
- iss-2610040847166532An AI-written interview's role can slow the change guard by planting a link to a huge directory tree where the guard follows links (for example its turn directory's preflight-receipts made a symlink and registered as a worktree): followLink content-hashes up to maxWatched (500,000) files before refusing. The guard still fails closed (the interview stops and nothing is accepted), but a turn can take minutes first.
- iss-2610041345196368When abcd's PreToolUse guard refuses a call, Claude Code prints the error as 'PreToolUse:<tool> hook error: [<the hook's whole command>]: <stderr>', and abcd's hook commands are inline shell of about 2,500 to 2,800 characters each (hooks/hooks.json: UserPromptSubmit 2,505, PreToolUse 2,774, PreCompact 2,408, SessionEnd 2,169, SubagentStop 2,173, SessionStart 959). The person sees a wall of mangled shell, wrapped and cut at the terminal width, and the guard's actual message (here the asking guard's 'the mode reads managed … say whom … then ask again') sits unreadable at the end. Seen 2026-10-04 in a downstream project on v0.12.0, when its agent asked the owner a coordination question and the asking guard refused it.
- iss-2610041944562639After Ctrl-Z and a resume, the plain-Terminal answer loop can fail to come back: on the macOS merge-queue runner (run 37210244082, 2026-10-04) the subtest TestLongListRestoresTerminalOnInterrupt/ctrl-z restores, and SIGCONT re-enters and redraws saw the child stop and the terminal restored while stopped (both asserted), then after SIGCONT the child wrote nothing for 20 s, so the question was not redrawn and raw mode was not re-entered. A person would see Ctrl-Z, fg, and the question still frozen until Ctrl-C. Lead: RawSession.reenter's tcsetattr (internal/term/raw.go) runs from a process group that is not the terminal's foreground group, and the kernel answers with SIGTTOU, stopping the child again. Alternative: a race between Suspend's wait for its continue token and the watch goroutine's continued(). It ejected an unrelated pull request from the merge queue; the detector stays armed.
- iss-2610042333573913The home-name boundary scan (TestOnlyTheHomeResolverNamesTheHome, internal/abcdhome) walks non-test Go only, so a test can build abcd's home by hand, filepath.Join(home, ".abcd", ...) or a "~/.abcd/..." literal, and keep passing after the name changes. Observed 2026-10-04 merging main into the noindex rename (#815): guided-connect, interview and credential-guide tests merged after step 2 hand-built ~/.abcd paths; most failed once the home was renamed, and internal/core/credential/guide_test.go passed while seeding a connection into the old folder, which the code under test no longer reads, so it checked nothing.
- iss-2610050259118177launch ship reads the release's records at HEAD (ShippedSince lists them with git ls-tree HEAD), so a spec close left uncommitted in the working tree is neither refused nor included: during the v0.13.0 cut, `launch ship --json` with the home-rename spec's close uncommitted returned rc=0 and a plausible cut of 54 records that silently left out the shipped intent itd-2610030720038073. The dirty-tree refusal fires only on the ingest (--changelog-json), not on the derivation the person reads first.
- iss-2610050259233425docs fidelity --apply writes each drafted replacement into .abcd/work/brief-review-flags.json, but the sentence a person then tidies by hand before committing (grammar, a half-replaced wrapped line, a flag name the chapter prose may not carry) is not what the flags file records: in the v0.13.0 cut, five chapters (10-docs, 15-prepare-this-repo, 22-site, 23-reading, 27-implement) landed wording that differs from the flagged replacement, so the record of what the product thinker must read names text that is not in the brief.
- iss-2610050259237102internal/core/ideate/record.go's comment (around line 134) asserts that os.Root refuses every symlinked path component, but os.Root follows a relative symlink that stays inside the root; the release cross-check (x-044, v0.13.0) raised it and could not reproduce a write through it, so the claim and whatever guarantee leans on it are unverified.
- iss-2610050315146044An AI-written interview's role can slow the change guard by writing core.hooksPath into .git/config, naming a large directory outside the tree: the reading after the turn hashes every file there (toward the 500,000-path bound, with no byte bound) before it reports the configuration change. A probe with a 16 GiB sparse file held the reading about 7 seconds, growing with the size. The guard still fails closed (the change to .git/config and the planted directory are named), but a turn can take minutes first. The followed-link budget (iss-2610040847166532) does not cover it, because the hooks directory is resolved and read whole, not reached through a followed link.
- iss-2610050348402910An AI-written interview's role can redirect where the change guard reads git's own directory, and slow the reading after its turn: a commondir file written into a main checkout's .git (or a linked worktree's commondir or .git file rewritten) makes git resolve the common directory elsewhere, and the next reading then hashes that directory's hooks, info, configuration, refs, modules and worktrees whole, with no budget, before the change is reported. A probe on a scratch repository: .git/commondir naming a directory holding only objects/ and refs/ made git rev-parse --git-common-dir name it, and git status still ran. The guard fails closed (every key of the person's own git directory disappears from the reading, so the turn is stopped), but a refs file there of many GiB holds the turn for minutes first. The followed-link and hooks-directory budget (iss-2610050315146044) does not cover it: git's own directory is read as owned, and its legitimate size (loose refs) is not one the 1,024-entry budget can hold.
- iss-2610050348533437An AI-written interview's role can slow the change guard by writing one large file into the working tree: the reading after its turn hashes every path git status lists whole (hashOne, then contentState's io.Copy), with no byte bound, so an untracked sparse file of many GiB holds the turn for as long as hashing it takes (about 7 s for 16 GiB in the hooks-directory probe, growing with the size) before the new path is reported. The guard fails closed (the path is named), and the budget on what one reading reads outside the tree (iss-2610050315146044) does not cover it, because the path is inside the tree, where a large untracked file can be the person's own.
- iss-2610050429322910An AI-written interview's role can slow the change guard through git itself: every reading runs git status before the guard's own bounds apply, and git reads some files in its own directory whole on every command, so a role writing a sparse HEAD, packed-refs or info/exclude there holds the turn while git reads it, before the guard's byte bound refuses the file. A scratch probe of git status with each file grown to 4 GiB sparse: HEAD 0.8 s, packed-refs 2.3 s, info/exclude 0.4 s, growing with the size (so minutes at 128 GiB). The guard fails closed (the file is named once read), and neither the in-tree byte bound (iss-2610050348533437) nor the followed-link budget covers it, since git, not the guard, does the reading. Files git bounds itself are not affected: a tracked file whose size changed is not re-read, a .gitignore or .gitattributes past 100 MiB is skipped, an index of zeros is refused at its header, and a configuration of zeros at its first line.
- iss-2610050504094430An AI-written interview's role can slow the change guard, and change a submodule's refs unseen, through a tracked submodule's git directory: git status in the checkout runs status inside each populated submodule, which reads that submodule's git directory under the common directory's modules/ (its HEAD, config, packed-refs, info/exclude) whole, and the guard neither sizes those files before git runs nor hashes the submodule's HEAD and refs (readModules hashes its hooks and config only). A check's probe grew .git/modules/sub/packed-refs to 128 GiB sparse and held the reading past 20 s; a small write to the same file was unseen (changedSince empty).
- iss-2610050532499080Nothing removed the spent worktrees and branches after the v0.13.0 cut (tagged 2026-10-05), so the checkout still carries work that is already on main, and abcd peers reports 35 live peers and 51 differing records, which buries what is actually in flight.
- iss-2610050543365882Renaming abcd's home to ~/.abcd.noindex (itd-2610030720038073) keeps the home out of Spotlight, but the .abcd/ folder inside each repository is still indexed: a folder whose name starts with a dot is not skipped, only one whose name ends in .noindex. On 2026-10-05, macOS 27.0, mdfind in this checkout returned at least 45,000 indexed items under .abcd/.work.local and about 3,150 under the committed tiers, and .abcd/.work.local/scratch alone holds about 130,000 files (1.6 GB), so every scratch export, log and review an agent writes there sets off indexing work, the cost the home rename was meant to remove. The intent's scope names the home only, so nothing covers the in-repo tiers.
- iss-2610050556323779On 2026-10-05, after the person had renamed ~/.abcd to ~/.abcd.noindex, ~/.abcd reappeared three times within an hour, and each time the guard refused every shell command and every question in two sessions at once (this one and gropiusllm-a3), because one stray folder blocks every session on the account. The cause was a SubagentStop entry in the person's ~/.claude/settings.json that ran a locally built ~/ABCDevelopment/abcd/bin/abcd-darwin-arm64 (old enough to reject --version) with 'hook subagent-stop'. Whenever any subagent stopped, it staged that subagent's transcript under ~/.abcd/transcripts/<root-sha>/staging/, recreating the old home. Evidence: the stray folder held only transcripts/488a0aa9…/staging/20261005T054848.953201000Z-a765320031b9991b5.stage.json and .raw (a subagent of this session, staged at 05:49:05Z) and an empty sessions/ marker. The plugin already registers its own SubagentStop hook with the current binary, so the settings entry was a stale duplicate. Removing it and moving the staged files into ~/.abcd.noindex stopped the recurrence. The rename's guard (itd-2610030720038073, D2) only notices the old folder after something has written it. Nothing in abcd, ahoy included, notices an abcd command wired into the host's settings outside the plugin, so a binary built before a migration keeps writing the old layout in every session until a person hunts it down by hand.
- iss-2610050556383525Product thinker ruling, 2026-10-05: abcd does not touch a person's ~/.claude/ folder, and nothing in it calls abcd, with one exception the person consents to: the status line, which is essential for product thinkers and which a plugin cannot set (a plugin's settings may set only agent and subagentStatusLine; the hooks abcd needs can all live in the plugin's hooks/hooks.json). Today ahoy install offers and writes the statusLine entry, and the person's settings had also gained a SubagentStop entry that called a stale abcd build (the defect that recreated ~/.abcd the same day). Because the status line runs on every refresh in every session, the risks the ruling accepts are: a stale or missing binary at the wired path; a status-line verb that writes state; a line left behind after an uninstall; the person's previous status command recorded once and gone stale; a concurrent write corrupting settings.json so the harness ignores the whole file; a wired path a project or another user can replace; and settings synced to a machine without that path.
- iss-2610050728100598The rename remedy abcd prints and documents, mv ~/.abcd ~/.abcd.noindex && for w in ~/.abcd.noindex/worktrees/*/*; do git -C "$w" worktree repair; done, assumes every worktree sits exactly two levels down, at worktrees/<root-sha>/<name>. A worktree named after its branch, such as docs/capture-sibling-repo-owner-redaction, sits three levels down, so the loop runs git in the docs/ folder above it, fails with 'not a git repository', and never repairs it. One left over at one level, with no root-sha key, gets git run on each of its files ('cannot change to …/AGENTS.md: Not a directory'). Seen on 2026-10-05 in a second account on this machine: eleven 'not a git repository' lines and five 'Not a directory' lines, and afterwards worktrees/488a0aa9…/docs/capture-sibling-repo-owner-redaction still had its main checkout pointing back at the old ~/.abcd path, so git treats it as missing and a git worktree prune would drop its entry. The 'repair: gitdir incorrect' lines in the same output are successful repairs that read like errors. The store there also held empty branch-prefix folders left by removed worktrees (check/, chore/, fix/ …) and a 117 KB test log at its top level.
- iss-2610050844241683The status-line trust check resolves a recorded entry with EvalSymlinks and judges the link's own directory and the final target's directory, but not the directory of a link in the middle of a longer chain. Example: the install record names ~/.local/bin/abcd, a link to /opt/homebrew/bin/abcd (a group-writable root:admin directory), itself a link to the real binary. Both judged directories pass, another admin account can repoint the middle link, and the status line then runs their binary on every refresh. Neither install shape abcd writes is a chain (a copy, or one link to the pinned plugin binary), so it is reachable only through a hand-edited install record that vouches for a hand-made chain.
- iss-2610050859363813On the Linux CI race lane, TestStartNeverSignalsAServerThatAlreadyExited failed in 0.03s: dashboard start killed the process group of a server that had already exited. A server that exits at once closes its configuration pipe before start writes to it; on Linux the write fails with EPIPE, and start treated that error as a stuck server and killed its group at once, while a concurrent cmd.Wait could already have reaped it, so the group number could by then name another program's processes. macOS passed only because the write lands in the pipe first.
- iss-2610050927169919GuardFindings reads the open/ issue folder at HEAD, so a major or critical finding captured but not yet committed is invisible to the findings gate; with --allow-dirty past the ingest's dirty-tree gate, the cut proceeds past it. Same class as iss-2610050259118177 (records read at HEAD), on the open side.
- iss-2610051434156079On the v0.13.1 release PR's merge-queue run, the macOS race lane failed TestHookSubagentStopConcurrentCompletionsAllStage: 12 simultaneous subagent-stop hooks all exited 0 but only 10 transcripts were staged (internal/surface/cli/hook_subagent_stop_test.go:336). The same suite passed on the PR's own run and on every queue run earlier that day, so the loss appears only under a slow, race-instrumented host, but it is a silent loss: the hook reports success and the transcript never reaches the store. It is the defect iss-2609090828371674 resolved (the shared lock's backoff ceiling capping staging throughput), shown not to hold under load.
- iss-2610051540383966commands/ahoy.md names the stray-hook gap id as harness.stray_hook.<Event>, but internal/core/ahoy/harness_strays.go appends .<n> for a second abcd hook on the same event. The page already tells the host to relay detail and fix_hint as they stand, so no action goes wrong; the id shape is simply incomplete. Deferred from the v0.13.1 cut to keep its content commit stable.
- iss-2610070547057816In abcd's own source checkout the person wants every abcd invocation, the plugin's hooks and command pages included, to run a build of the checkout's HEAD (dogfooding), and in every other repository to run the most recently installed stable release, so the two can always be compared. Today the hooks and the command pages resolve the plugin-root binary first, which is the last published release (v0.13.1 at 2026-10-07), so inside this checkout the guard, the loader and every slash command run stale code unless an agent knows to substitute go run ./cmd/abcd; the DOGFOODING rule in .abcd/rules.json teaches the agent but cannot reach the hooks. Automatic detection of abcd's source was rejected: a repository posing as abcd would get its own code run by the hooks, the hazard the hook shim's PATH rung already refuses (a binary inside the working tree).
- iss-2610070637562567After the hook commands became one-line wrappers, a guard refusal still reaches the person as 'PreToolUse:<tool> hook error: [sh "${CLAUDE_PLUGIN_ROOT}/hooks/pre-tool-use.sh"]: <message>', framed as an error, because the guard blocks by exiting 2 with its message on stderr. Claude Code's hooks reference documents a structured alternative for PreToolUse: exit 0 with hookSpecificOutput.permissionDecision "deny" and permissionDecisionReason on stdout, which blocks the call (a question included) and hands the model only the reason; the command echo in front of an exit-2 message is not documented at all. Unverified here: the guide that reported it worked from summarised documentation.
- iss-2610070927488590zsh, the user shell abcd's own sessions run in, reads $name:r, $name:h, $name:t, $name:e and $name:s as history modifiers on an unbraced parameter, so a refspec or a path written "$sha:refs/heads/x" expands to the sha with its last suffix stripped followed by 'efs/heads/x'. On 2026-10-07 this broke a git fetch into a lab snapshot inside a chain whose next step, after a ';', dropped the stash being archived; the objects were restored from the repository within two minutes. The shell-hazard registry teaches rm-after-cd and similar shapes but not this one, and bash does not have it, so a command tested in bash passes and fails in zsh.
- iss-2610071248006619The cli test suite read the machine's own ~/.abcd.noindex/oracle-routing.json: once a routing table was accepted on the machine (written 2026-10-07 13:13, by another session), every delegated disembark verb printed a routing line to stderr and six TestDisembark* tests that parse the --json output failed, on this machine only. The suite's TestMain already kept the machine's rules.json out of reach (rules.SwapUserHomeForTest); the layered loader that resolves the routing table called os.UserHomeDir directly.
- iss-2610071528375981During abcd ahoy install, each category approval (Setup Q1 to Q5 in a managed repository, e.g. 'Apply conventions-file changes?') is asked with nothing but that one line: apply.go composes the question as "Apply " + category + " changes?" and the setup question carries no material, while its Yes option says it 'Writes what the text above describes.' There is no text above, so the person approves file writes without seeing which files change or how; the category name itself (conventions-file, git-hooks, ...) is an internal word. Seen 2026-10-07 by the product thinker in a downstream repository on v0.13.2 (screenshot: five approvals answered 'Yes, make the change' with no list shown).
- iss-2610071529246095The ahoy install question that sets what a repository releases (artefact kind, .abcd/config/artefact.json) gives too little context and too few answers. Its whole explanation is 'What this repository releases; abcd's release commands refuse to guess it.', it offers only plugin, binary and application, and the default is explained as 'as binary today', which tells a person nothing about their own project. A website, a native desktop app, a mobile app or a library has no answer that fits, and nothing says what each choice changes in the release flow. Seen by the product thinker during abcd ahoy install in a downstream repository on v0.13.2, 2026-10-07 (Setup Q11).
- iss-2610071530110820The summary abcd ahoy install prints at the end is hard to read. Problems:
- iss-2610071533256167A running drain's pace cannot be changed: abcd drain refuses --pace, --sub-agents and --fix-rounds while a drain is in progress ('a pace is set when a run starts'), and there is no verb to end a drain early, so the only way to move a drain started on the bundled 120/300 pace (two hours of work, five of pause) to continuous work is to wait for it to end or to discard its local state by hand. Met 2026-10-07 when the product thinker asked a drain started minutes earlier to work throughout.
- iss-2610071538011774abcd lab preflight's dual-binary gate cannot pass in a managed repo that is not abcd, so every such lab halts
- iss-2610071538028804ahoy reports no gaps while abcd lint errors on the missing shared work tier
- iss-2610071538032843ahoy install with --docs-target wrote config and re-rendered AGENTS.md although every asked approval was answered later
- iss-2610071538055431Question guard's 24-row limit counts the option lines, but the asking rule reads as a limit on the question text
- iss-2610071538064699Report field check refuses a slash-command name as a filesystem path
- iss-2610071538075997Name check: judge warn-tier hits in session, keep a local-model shadow log, and review it
- iss-2610071538088019Route work about abcd itself to abcd report, never into a managed repository's intents or issues
- iss-2610071636011953abcd's questions offer no 'Unclear, explain more' answer, though the product thinker needs one often: in one session on 2026-10-07 they typed it by hand into the host's free-text 'Other' field three times ('I don't understand', 'unclear, explain', 'unclear, explain'), and once answered 'what does that have to do with abcd?'. Each time the question was re-asked with more context. The asking rules list exactly the defensible answers plus 'Decide later' or 'None of these', so a person who cannot answer for lack of explanation has only free text to say so, and nothing records how often a question failed to explain itself. Screenshot of the third case: a 'Product Q1' setup question with a typed '4. unclear, explain' entry.
- iss-2610072113549994A user-visible change reached main with no record, so the derived changelog would not announce it: the guard hook refuses through the host's JSON deny, so a refused command no longer echoes the hook's command line before the guard's message; a question whose only fault is its length is shown with a note to the agent rather than refused; and a new abcd:question-drafter agent drafts abcd's questions so they fit. Merged as 12a5dca2f; iss-2610070637562567 stays open because the host still draws every hook refusal as an error.
- iss-2610072347230409ahoy remote apply's refusal message says nothing was changed, but two paths in internal/core/ahoy/remote.go reach the refused status after a toggle has already landed on GitHub, so the person is told nothing changed when one setting did.
- iss-2610072347238476commands/launch.md and the brief's launch chapter describe the unfixed-finding refusal as major/critical-only, but the findings gate now also emits it for any open issue record that differs from HEAD; and when unfixed or deleted findings are present too, the uncommitted paths appear only in --json, so the operator loops once more before seeing them.
- iss-2610072347247487The disembark probe's invariants, naming and personas sources ignore their own brief files, unlike open-questions and tradeoffs since the probe lane, and the pack's per-section file does not print a partial section's reason, which coverage.json and the text render now carry.
- iss-2610080243358597A fix round that rebases the lane branch leaves the lane receipt's resolves[].commit at the pre-rebase sha, which is no longer reachable from the lane head, so the landing would stamp an unreachable resolved_by.commit that RS003 refuses at preflight. Met overnight on run-2610072316033117 (fab3f1704 rebased to 90f48d5f9); corrected by hand in the run state.
- iss-2610080243367006TestStatuslineSlowPreviousCommandIsStopped asserts the status line returns within 300ms; on the CI macOS runner it returned in 326ms for a change that did not touch it (PR #857, run 37707291322), so a fixed wall-clock budget under a race-instrumented shared runner makes it flaky.
- iss-2610080243367274TestEveryStreamFailureIsRefusedWithoutTheKey/a_stream_that_never_ends failed on the CI ubuntu runner with 'the call had not returned after 30s' for a config-only change (PR #859, run 37710101909); it passed on rerun, so its fixed wall-clock wait is flaky under load.
- iss-2610080546203039The implement loop titles a lane's pull request from its issue's title; when that title names another record id, RS004 refuses the PR because no Refs line declares it (PR #865 named iss-2609261536147903 from its issue's title; fixed by hand by editing the body).
- iss-2610080546205127A lane run the drain opens takes the bundled 120/300 pace and 2 sub-agents rather than the drain's --pace and --sub-agents, so a continuous drain (--pace 10080/0 --sub-agents 6) pauses its lane after two hours: run-2610080105040584 paused until 08:07Z overnight and was set to the drain's pace by hand in its state.
- iss-2610080546210831commands/prepare-this-repo.md tells every prepared repository to run git config core.hooksPath .githooks with no condition, which shadows a global hooks dispatcher: the exact advice ahoy's status now refuses to give when hooks_path is foreign.
- iss-2610080618506115Route work to model tiers by role, per task as well as per agent: thinking (Opus today), default (Sonnet) and quick (Haiku), so that, for example, a summary written for the product thinker goes to the quick tier rather than the thinking tier. The tier names are what abcd stores; each model family maps them to its own models, so a move to another vendor changes the mapping and nothing else. This refines the planned per-agent tier table (itd-2609170822093401), which has economy and frontier but no middle tier and no per-task routing. Before a cheaper tier takes over any task it should earn it: keep the thinking tier doing the live work and run the quick tier on the same task in the shadow, recording both outputs, so a later evaluation can show where the quick tier is good enough.
- iss-2610080620372731When an agent or sub-agent loses its network connection mid-task, the work stalls or fails instead of waiting the outage out, and this keeps happening on the product thinker's machine. An agent that notices a lost connection should pause and retry on a widening schedule: wait one minute and try again, then five minutes, then ten, then an hour. Sibling agents should also learn of the outage without depending on each other over the network, since they may have lost the connection too: a channel on the machine itself, such as the run state and run log abcd already shares between sessions, would let one agent record the outage and the others hold off instead of each failing on its own.
- iss-2610080621450495Consider running abcd's autonomous runs as a collection of agents, a shape seen in an outside open-source agent tool: the person talks to one lead agent; the lead hands each task to a worker running as its own terminal session in its own git worktree; and a plain shell watcher, which costs no model tokens, sleeps on the workers and wakes the lead only when one finishes, fails or needs a decision. Today abcd's lanes run as sub-agents inside the host session, and the lead keeps checking on them itself (re-arming watchers on pull requests, polling queue state), which spends its context on waiting. Independent worker sessions would also contain a lost connection or a crash to one worker instead of the whole run, and state kept on disk lets every worker resume after a restart. The same tool can run workers on another machine over SSH, which is worth weighing later.
- iss-2610080623391354Consider a browser review loop for the product thinker, seen in an outside open-source agent tool: the agent writes an HTML artifact (a mockup, a report, a criteria walk, an intent's press release); the person opens it in the browser, annotates exact elements or text, attaches images, and queues feedback; the agent collects the whole batch with one long-polling call and writes the next revision, with the changed parts marked as revisions. The same tool audits each render for layout faults (clipped text, unreachable controls) and lists them as issues the person can send back. Today abcd's only channel from the person back to the agent is the terminal question tool, held to twenty-four rows at eighty columns, so long material is split across many questions or pushed into an HTML report read separately, with the answers still typed in the terminal. abcd's dashboard already runs a server reachable only from the person's own devices over Tailscale, but serves nothing of the project yet, so it is the natural host for such a loop. Feedback arriving from the browser is a new path into the agent's context and must be treated as data, never instruction.
- iss-2610081312364884Post-cut docs currency for v0.13.3: launch.md and the --allow-dirty help omit the open-records refusal, prepare-this-repo shadows a foreign hooks path and names a bare record-lint.json, and implement step --discard help misorders its steps
- iss-2610090642371836When a release cut is refused for an unfixed or deleted finding and also for an issue record under open/ that differs from HEAD, the open-records refusal gets no refusal entry of its own: emit.go raises the unfixed and deleted refusals and adds the guard's verdict as a backstop only when both lists are empty, so the uncommitted-records reason survives only in the findings verdict. A front door that acts on the refusal list fixes the findings, retries, and only then meets the second refusal.
- iss-2610090642376032A pull request the implement loop lands can leave the merge queue silently. Twice it sat CLEAN with auto-merge armed and never entered the queue (#837, #844; the enqueue mutation then failed with a forge error and only toggling auto-merge queued it), and four times across this run and the v0.13.2 cut a failed merge-group check (the macOS job cap, or a flaky test) dropped it from the queue (#839, #854, #867, #869) with nothing re-queuing it. The loop arms auto-merge and walks away, so a run that trusts it stalls unseen; one drop cost about 45 minutes in this run.
- iss-2610090642381632A hand-run review or checker agent has no deadline of its own. In the v0.13.2 cut a crosscheck checker ran over an hour, and in this run a ruthless reviewer ran about 95 minutes; neither answered a wrap-up message, and both were stopped and relaunched with a time budget and a one-pass method by hand. The agent definitions and the release crosscheck brief carry no budget or stopping rule, so the orchestrator has to invent one each time.
- iss-2610090642385898A drain has no way to hold back one issue or one package for now. A peer's verbal hold is invisible to it (only implement claim or a branch carrying the record keeps a lane off an issue), and while a fix is in flight in one package the only way to keep the drain out of that package is to stop the whole drain, so this run drove a colliding lane anyway and let whichever landed second rebase.
- iss-2610090642392144AGENTS.md tells a verifier to work on a copy made with git archive into a scratch directory, and the local scratch tier lives inside the worktree. A copy extracted there is not a git checkout, so every abcd verb run from it that reads git or the record store resolves upward to the live worktree that contains it. In the v0.13.3 cut the binary verbs run from the export read the release worktree, which was only equivalent because that worktree was clean at the content commit.
- iss-2610090642394550TestModeMadeQuestionAbcdsSaysSo failed once on the macOS leg of PR #858 with 'stdout is not one hook output object: EOF' after 0.11s, in a change that never touched the guard; a re-run passed. The test arrived with #849. An empty stdout from the question hook reads as a race between the hook's output and the test's read.
- iss-2610090642407850TestStatuslineSlowBranchStillRendersThePartialRow failed once at 0.34s in a local landing preflight under a load average above 50; a retry passed. It is the sibling of TestStatuslineSlowPreviousCommandIsStopped, whose wall-clock budget was fixed in iss-2610080243367006, but that fix did not reach this test, so the same family can still fail under a loaded host.
- iss-2610090643230618The orchestrating session filed two intent drafts, itd-2610071545369520 and itd-2610071545380041, without the hand-run four-piece decomposition table the DECOMPOSITION rules require before an intent is filed; it flagged the omission to the product thinker afterwards.
- iss-2610090643232149The orchestrating session overwrote the local-tier handover file .abcd/.work.local/NEXT.md with its handover note without reading what it held first; the file is gitignored, so the prior handover could not be recovered from git. The runbook's rule is never to overwrite NEXT.md unread.
- iss-2610090643232207In this run's interview the first two phrasings of a question about the banned-names check were not understood by the product thinker ('I don't understand', then 'what does that have to do with abcd?'): the question named the check by its mechanism without saying it was abcd's own and what it does for the person. Only the third phrasing, naming it as abcd's check, landed.
- iss-2610090701491123The product thinker ruled on 2026-10-09 that once abcd has sent a brief to the person's own model server for the size count, a later failure before any answer still moves the step to the agent harness: 'no answer received' is the trigger, not 'nothing was sent'. Today the adapter stops with an error instead, because the fix for iss-2610030956156354 stopped reporting such a failure as unreachable, and only an unreachable error falls back (internal/core/oracle/dispatch.go FellBack).
- iss-2610090703513626After a release, nothing checks that every problem an autonomous run met was captured. The run logs under .abcd/.work.local/logs/ (for example the 2026-10-07 cleanup-and-bugfix-cut log) record each stop, slip, observation and autonomy gap, but turning them into issues was a manual pass the product thinker had to ask for after v0.13.3, and it found ten defects and five records owed new evidence.
- iss-2610090703514921A drain reads only the issue ledger, so security advisories that others submit through the forge's private vulnerability reporting never reach it. Unpublished advisories are not named by any record, so nothing in abcd shows whether they were triaged. They cannot simply be copied into the ledger as issues, because the ledger is public and an advisory stays private until it is fixed; and even a ledger issue in the security category is handed back by the drain under its default rule.
- iss-2610090740139804abcd ideate record writes every verdict straight into the repository: a research note under .abcd/development/research/notes/ and a pointer line in .abcd/work/DECISIONS.md, both committed and public once pushed. The product thinker treats every idea put through ideate as secret: an idea and the sources it came from are kept private first and enter the repository only when the person decides it should.related itd-2610141646456128
- iss-2610090742488191When an idea is adopted, nothing carries the public primary sources it rests on into ACKNOWLEDGEMENTS.md. AGENTS.md asks for an entry in the same change that lands an adopted pattern, but ideas now arrive through ideate verdicts kept private in the home store (iss-2610090740139804), so the sources and the licence findings the research leg checked stay in a file the adopting change never reads, and a private source must never be named at all.related itd-2610141646456128
- iss-2610090744063842ADR 0007 and the superseded itd-27 link the PRD template's source at mattpocock/skills skills/engineering/to-prd/SKILL.md, but that skill was merged into to-spec and to-tickets upstream on 2026-07-08, so the link now answers 404 and no longer shows the source it credits.
- iss-2610090744073409The CONCURRENCY rule in .abcd/rules.json (and its AGENTS.md short form, if it repeats it) says the worktree store's own verbs are itd-2609091014076309, in drafts/, but that intent is in planned/; its link already points at planned/, so the prose contradicts the link beside it.
- iss-2610090744325698The product thinker's 2026-10-07 lesson, that a user-visible host fix is proven by a capture of a live session before and after the change and never by script output alone (v0.13.2's hook fix passed its tests while every live session still showed the error), is held only in one agent's local memory. No committed rule, principle or definition of done carries it; its only committed trace is the measurement inside iss-2610070637562567, so another session or contributor never receives it.
- iss-2610090747102654abcd has a place for a short note of where the work stands now, the local-tier handover file .abcd/.work.local/NEXT.md, but nothing keeps it: no command writes it, nothing says when it is stale, the PreCompact and Stop hooks write nothing durable to it, a session can overwrite it unread, and it is lost when the worktree holding it is removed. A short note of where the work stands, rewritten every session, is the one thing an outside agent-memory pattern adds over abcd's brief; abcd keeps it out of the repository on purpose, but leaves it unmaintained.
- iss-2610090748299348A public source behind an idea is named in the repository only once the idea is accepted. An idea that is rejected, killed or abandoned names none of its sources anywhere public (no record, research note, decision line, commit or pull request), only in its private verdict; nothing enforces this today, and ideate record currently writes every verdict's sources into the committed research notes.related itd-2610141646456128
- iss-2610090816296964When abcd asks the person to choose, the question keeps running past the host's question box: a question over 24 rows at 80 columns was refused in a live session on the 0.13.2 plugin, and the agent cut its options down to a few words each to get it through. The product thinker, reading the refused draft, saw that its long text added nothing: a paragraph before the options described each option again, while the options' own labels and descriptions were already perfectly clear. The problem was repetition, not too little room, so the fix is a rule against it rather than a second channel for the overflow; a separate text file for the full options was considered and dropped on the product thinker's ruling of 2026-10-09.
- iss-2610090821313095`abcd guard` only warns on a bash `function f { ...; }; f` whose body is a blocker, and the PreToolUse hook lets a warning run, so the function executes.
- iss-2610090821476887`abcd guard` allows a blocker written as the command string of `trap`, and bash runs it, an EXIT trap needing no further command.
- iss-2610090821484829`abcd guard` allows `BASH_ENV=<file> bash -c true`, and non-interactive bash sources that file before `-c`, so a blocker written to the file in the same command runs.
- iss-2610090821489740`abcd guard` steps over the value of `bash --init-file` and `--rcfile`, and interactive bash runs that file before `-c`, so a blocker in it runs while the checked command reads `bash -i -c true`.
- iss-2610090821491948The secret scanner misses a token or home path written as a JSON escape stacked on a percent encoding (or the reverse), because it never runs one decoder on the other's output, so `ScanText` reports nothing, `Redact` leaves it, and the launch gate ships it.
- iss-2610090821499579The secret scanner reports a PNG as content-decoded while bytes inside a compressed chunk after the zlib checksum are never inflated or scanned, so a gzip member there ships through the launch gate.
- iss-2610090821502084The secret scanner counts a file as fully scanned when only its first 8192 bytes are valid UTF-8 text, so a gzip member after a page of prose in an included markdown file ships with no finding.
- iss-2610090821506490A committed `.abcd/config/pii.json` with `skip_path_fragments: ["."]` sends every dotted path to the byte-only branch, so a non-reserved IPv4, IPv6 or MAC address in an included file ships through the launch scan.
- iss-2610090821510097The implement loop's lane sync merge (`git merge --no-ff` through `pickGit`) runs a repository-configured merge driver, which executes as the operator and writes the merge result git keeps, although the loop presents this merge as running no hook code.
- iss-2610090821512707The secret scanner reports a tar archive as content-decoded while the bytes after the first NUL of a GNU long-name (`././@LongLink`, type L) body are consumed by the tar reader and never scanned, so a gzip member there ships.
- iss-2610090821520843The picked implement run's hooks-off record commit runs the repository's signing program (`gpg.program`, `gpg.ssh.program` or `gpg.ssh.defaultKeyCommand`) as the operator when the checkout sets `commit.gpgsign=true`.
- iss-2610090821527948abcd's git environment does not set `GIT_NO_LAZY_FETCH`, so an object read (`show`, `cat-file`, `ls-tree`, or `tag --list` with an object-reading `tag.sort`) of a missing object in a promisor checkout lazy-fetches and runs the repository's transport program (`remote.origin.uploadpack` on a local or file:// URL, `core.sshCommand` on ssh://).
- iss-2610090821531394abcd's read-only `git log` and `git show` calls do not pin `log.showSignature=false`, so a checkout with `log.showSignature=true`, a repo `gpg.program` and one `gpgsig` commit runs that program as the operator during probes such as `abcd disembark probe`.
- iss-2610090821531570record-lint's armed agent-diff check runs `git diff --unified=0` without `--no-ext-diff --no-textconv`, so a repository `diff.external`, `diff.<driver>.textconv` or `diff.<driver>.command` runs as the operator and its stdout can forge the `prompt_version` bump the check looks for.
- iss-2610090821543020A copied checkout whose `.git/config` sets `core.worktree=../..` makes abcd take an ancestor directory as the repository root, so `abcd decide`, intent, spec, capture and memory writes land under that ancestor instead of the checkout.
- iss-2610090821548169The launch dirty-tree check (`git diff ... HEAD` in `DirtyTreeFiles`) runs a repository `filter.<name>.clean` program as the operator on a copied checkout, and the gate can still report the tree clean.
- iss-2610090821550872main pins go 1.26.7 in go.mod, and govulncheck fails the merge queue (merge_group run 37897679940) on twelve stdlib advisories fixed in go1.26.9, among them GO-2026-6599 and GO-2026-6600 (html/template, reached through the dashboard page handler) and net/http traces.
- iss-2610090821552801The implement loop's land stage accepts any non-empty worktree path from the run state file, so a planted state makes `abcd implement step` create `<that path>/.abcd/.work.local` (mode 0700) in a directory the state names.
- iss-2610090824041378The status board's Now list shows a run's lanes with an empty title when the run was started for an issue rather than an intent: statusblock.go builds each started run's row by looking the id up in the intent corpus only, so an issue-keyed lane (every drain lane, every 'abcd build <iss-N>' run) renders as a bare 'building:' line. It also counts a lane as building after its pull request merged: on 2026-10-09 the product thinker's view showed 24 blank 'building:' rows, the overnight drain's lanes, most merged days earlier but still recorded at the land stage because nothing moves a run on once its pull request lands.
- iss-2610090831317531abcd's verbs have never been reviewed as a set: nothing lists every CLI verb and /abcd: command page with whether people or agents mainly use it, and whether it should be kept, merged, renamed or retired. Draft intent itd-2610090831227812 (a person's /abcd: list shows only the commands people use) needs that classification before its spec can say which pages move.
- iss-2610090841317423abcd dashboard start never starts on a Mac whose Tailscale cannot reach its own IPv6 address. Start listens on both of the computer's Tailscale addresses and requires a self-check fetch to answer on every one; on 2026-10-09, with Tailscale 1.102.4 on macOS, a TCP connection to the computer's own Tailscale IPv4 address succeeded while one to its own Tailscale IPv6 address timed out, so the IPv6 self-check failed and start stopped the dashboard with 'could not be reached from this computer ... check that nothing on this computer blocks the port' (exit 1). Nothing blocks the port; the dashboard is unusable from every device.
- iss-2610090841586205abcd's dashboard reaches other devices only through Tailscale: it listens on the computer's Tailscale addresses and admits a device only when Tailscale's own lookup names it. The product thinker wants WireGuard as a built-in alternative the person may choose instead, so the dashboard does not depend on one vendor's account and coordination service. A plain WireGuard tunnel has no lookup that names a person's device, so the alternative needs its own device identity, such as each peer's public key mapped to a named device.
- iss-2610090849280432The issue-resolution gate (RS004) does not count a Refs: line that names an issue alongside an intent, such as 'Refs: itd-2610090831227812, iss-2610090831317531, itd-146': DECLARE_RE in scripts/check-issue-resolution.sh accepts a line listing iss- ids and nothing else, so the issue on a mixed line reads as an undeclared mention. The refusal then asks for exactly one declaration line, which the commit already appears to carry, and never says the line was passed over because it also names an intent, so the author cannot tell what is wrong. Found on 2026-10-09 when make preflight refused a records commit.
- iss-2610090925390900abcd guard allows a bash -c whose environment prefix sets SHELLOPTS=xtrace and a PS4 holding a command substitution: bash expands PS4 before tracing the first command, so a blocker in PS4 runs although the -c payload is harmless. Reproduced at main 016c1510a: `SHELLOPTS=xtrace PS4='$(pkill node)' bash -c true` (and the `env` form) judges allow while `pkill node` blocks. Sibling of the BASH_ENV finding iss-2610090821484829, found in the security-drain-2026-10-09 sweep; kept uncommitted until its fix lands.
- iss-2610090925399967abcd guard allows a bash -c whose environment carries an exported function (a BASH_FUNC_<name>%% variable, through env): bash imports it at startup, so a function named like the -c command runs a blocker in its body although the -c payload is harmless. Reproduced at main 016c1510a: `env 'BASH_FUNC_true%%=() { pkill node; }' bash -c true` judges allow while `pkill node` blocks. Sibling of the BASH_ENV finding iss-2610090821484829, found in the security-drain-2026-10-09 sweep; kept uncommitted until its fix lands.
- iss-2610090932257904abcd guard allows a shell that reads its script from a file through a stdin redirect (`bash < f`, `bash -s < f`), while the pipe form `cat f | bash` blocks under interpreter-reads-stream: stdinStream (internal/core/guard/tokenize.go:49-54) is set for a pipe, a here-document, a here-string and a pipe into a group, never for a < redirect, so shellReadsStream (payload.go:1871-1874) never sees the file as the script. Reproduced at main 016c1510a. Sibling of iss-2610090821484829, found in the security-drain-2026-10-09 sweep; kept uncommitted until its fix lands.
- iss-2610090936460789A lane's worktree and branch are cleaned up only by a final 'abcd implement step' run after its pull request merges, and nothing runs it: the land stage waits (exit 3) until the merge, the drain records the lane as 'pull-request' and moves on, and no hook, drain move or schedule comes back. On 2026-10-09 all 18 overnight drain lanes sat merged but still at the land stage, their worktrees in the store and their runs counted as building on the status board (iss-2610090824041378). The step was also refused when it was finally run, because the run's pacing window had elapsed ('nothing before 14:36Z'), so even finishing a merged lane waits hours.
- iss-2610091010558682The research the routing of itd-2610091010348892 owes before planning has not been done: how abcdev.app can build pages from other public GitHub repositories within the GitHub API's limits (60 unauthenticated requests an hour, adr-47) and its terms, whether to fetch on a schedule, on an owner's request or from the owner's own release, and how comparable hosted documentation services handle opt-in, rebuilds and takedown.
- iss-2610091851095194abcd gives a person no way to commission a cold reading of a document they choose: abcd reading assemble takes only a position and a commit, and what each position reads is fixed by the committed preset file .abcd/config/reading-presets.json (today a set of shipped intents, their specs and delivered code), so a reading of one new draft, a principle or a single brief chapter means editing and committing that file first. Asked on 2026-10-09 whether a cold reading is only triggered automatically and only for the brief, the product thinker learned it is neither, and placed reading on the person's list.
- iss-2610091903077581abcd report lets an agent in an abcd-managed repository file a defect report or proposal about abcd into the abcd inbox without asking anyone: commands/report.md says nothing about permission. The product thinker ruled on 2026-10-09 that report stays an agent's command but must ask the person's permission first when it runs in an abcd-managed repository, since the report carries that project's words to another project's inbox.
- iss-2610091920437492abcd ignores a ~/.abcd.noindex/filter-roots file that fails its ownership, mode or symlink checks without saying so: the core has no output channel, so a checkout its owner listed to keep its content filters running silently gets them switched off, and the reads that depend on them (an LFS checkout's status) degrade with no notice. Found in lane X round 3 of the security-drain-2026-10-09 run.
- iss-2610091935324732On git older than 2.44 the partial-clone refusal exempts check-ignore and ls-files as commands that read no objects, but git reads a skip-worktree .gitignore missing from disk out of the object store, so a copied partial clone still lazy-fetches through a promisor remote's transport on those paths (CheckIgnored, IgnoredUnder, lifeboat probe, launch gates, intent consistency, capture reframe). Sibling of iss-2610090821527948, found by the security-drain-2026-10-09 lane W sweep; kept uncommitted until its fix lands.
- iss-2610091935325886record-lint's patch diffs (decisions-append, agent-diff) start an inner git diff inside a submodule when the superproject sets diff.submodule=diff, and git passes that child none of the parent's --no-ext-diff/--no-textconv, so the submodule's diff.external or textconv runs and its output lands in the text the check parses. Sibling of iss-2610090821531570, found by the security-drain-2026-10-09 lane W sweep; kept uncommitted until its fix lands.
- iss-2610091935327982abcd's filter-free working-tree reads (gitutil.Status, the launch dirty check DirtyTreeFiles, intent consistency dirtyCorpusPaths, the release-receipts status) still run a checked-out submodule's own clean filter: without --ignore-submodules git starts a child status inside each submodule, and FilterOverrides blanks only the filters the superproject defines, so a copied checkout's .git/modules/<sub>/config filter runs on a stale index. Sibling of iss-2610090821548169, found by the security-drain-2026-10-09 lane W sweep; kept uncommitted until its fix lands.
- iss-2610091935334207The implement loop's pickGit (pick commit, sync merge) runs with ScrubbedEnv, so it lacks gc.auto=0, maintenance.auto=false and GIT_NO_LAZY_FETCH: a pick commit can trigger gc --auto (and gc.recentObjectsHook on git 2.42+), and a merge in a partial clone can lazy-fetch through a promisor transport. Found by the security-drain-2026-10-09 lane W sweep; kept uncommitted until its fix lands.
- iss-2610091937218987The lost-connection fix of iss-2610080620372731 is proven by unit tests with an injected clock and prober, not yet by a live run: the record asks for a lab that cuts the network during a real autonomous run and shows each kind of loss (the host's own turn, a sub-agent, a tool's network call, and the model service) waited out on the one shared probe, the other lanes held only at network steps, a dead or yielded lane restarted from its last commit with its edits kept for review, and the 8-hour give-up ending in one notification. The product thinker ruled on 2026-10-09 that this lab runs after the next patch release is cut, since it switches off the machine's network for a few minutes.
- iss-2610091942156774An agent's `rm -f "$VAR"/*` triggers the host's own dangerous-rm permission prompt ("possibly-empty variable path ... rewrite it as "${VAR:?}"/* or use a literal path"), even with permissions skipped. The person cannot tell whether the variable is empty and cannot make the agent take the suggested form, so they must approve blind. abcd's guard allows the shape today, and sub-agents never receive the injected SHELL rules, so nothing steers an agent away from it. Reported by the product thinker on 2026-10-09 from two prompts raised by a review sub-agent.
- iss-2610092011131598TestSurpriseRefusesAnUnresolvedOccasion failed in the merge queue on 2026-10-09 (PR #880, macOS race lane, run 37980092117) with 'duplicate issue id: srp-2610092000060599 already exists in this ledger; the mint collided with a record already committed': the test mints three surprise records in quick succession, two drew the same timestamp-plus-four-digit id within one second, and the allocator refuses a collision instead of drawing again, so a records-only pull request was dropped from the queue.
- iss-2610100546338578A paced run pauses 300 minutes after every 120-minute window by default: the bundled pace is 120/300, so an implement run that outlives its first window stops every stage, landing moves included, for five hours unless a flag or a configuration layer sets the pause. The product thinker ruled on 2026-10-10 that no pause is needed and that the default must be zero.
- iss-2610100602595553A rate limit gets no wait once the pause is zero: pacing's rate-limit checkpoint (itd-2609201925079472) ends the run's window early and sets next_eligible_at to now plus the run's pause, and with the bundled pause now 0 (iss-2610100546338578) the next step hands the same work out again at once, so a rate-limited run can hit the same limit again and again. The product thinker ruled on 2026-10-10 that a rate limit waits on its own, independent of the pause, as work after pacing and the drain (itd-82).related itd-2611040344170206
- iss-2610100626211810An abcd question is refused with 'the mode reads managed' whenever the agent has not run abcd mode just before it, although the question's own chip ('Tech Q3', 'Product Q2') already names whom it is for. The mode is reset two ways: the asking rules tell the agent to set it back to managed after every answer, and the prompt hook resets it on the next prompt the session receives while a question is marked open, which in a turn of several questions can be a peer session's message or a message the person sends mid-turn (inferred from a refusal on 2026-10-10 after a peer message arrived; not yet reproduced). So an interview of several questions is refused intermittently, and the person sees the hook's error line each time (iss-2610070637562567 measured that every refusal reaches them framed as an error). The product thinker chose on 2026-10-10 to fix this in code first, before the general rewriter.
- iss-2610100626320367A record's file name has no cap tied to the length of its full path, so a record checked out on Windows can pass the 260-character path limit, which the product thinker reports records already do. The longest tracked path is 149 characters inside the repository; the checkout's own location comes on top, and a worktree in the machine store adds its prefix, the 40-character root commit and the worktree's name. Git for Windows will not check such a file out unless core.longpaths is set (itd-2610070544145422 is the Windows install draft).
- iss-2610100626327722When an abcd question is refused for another fault, the refusal lists the question's rows overrun among the parts to fix ('fix each and ask again'), although the rows limit alone never refuses (the question gate's rowsOnly, iss-2610070637562567). The person and the agent read it as a cause of the refusal, and the agent cuts a question the gate would have shown; seen twice in one interview on 2026-10-10.
- iss-2610100649466578Brief template: a standard Product principles section beneath the press release, filled by the vision step
- iss-2610100649471088abcd lint docs --json prints two JSON documents on a blocker, and names its finding fields differently from abcd lint
- iss-2610100649479892The public name check was silently disarmed: its roots still named a retired CLAUDE.md, and bare abcd lint reported no findings
- iss-2610100649481907A review verb for proposed brief edits: deduced changes recorded, asked or settled, then appliedrelated itd-61
- iss-2610100649485756Let the product thinker edit the brief and their parts of intents in a local web editor before anything is committedrelated itd-2610040740122709
- iss-2610100649495706A verb to run state-of-the-art research and keep it as a research note in the recordrelated itd-2610142116477426
- iss-2610100846469473TestRebuildingInPlaceIsByteIdentical (internal/core/site) failed in make preflight on 2026-10-10 with 'sits inside a checkout but git cannot name its root (exec: WaitDelay expired before I/O complete (stderr: ""))' while the machine's five-minute load average was about 48 on 16 cores, from concurrent sessions' preflights; the same test passed three times in a row once the load fell. The site build's root lookup turns a git subprocess that misses its WaitDelay into a refusal, so a loaded machine fails a records-only branch's preflight on code it did not touch.
- iss-2610100913086397A validator that meets a rate limit and whose partial return cannot be saved aside leaves its lane stuck: the record tells the user to run abcd implement step --restart <lane> after the pause, but Restart refuses any lane without an implementer out, so every later step waits on validators that are gone.
- iss-2610100913088696The rate-limit checkpoint matches an await by its receipt path alone, though its comment says a restarted await is skipped: Restart keeps the receipt path, so an await re-told while the dispatch was out is saved aside and reset again.
- iss-2610100913095172Only the claude runner recognises a rate limit: an opencode limit is an ordinary failure that falls back to the next runner, and a limit met by a host-run sub-agent is never seen by the loop, since no verb lets the host report one.related itd-2611040344170206
- iss-2610100913096346The run-start budget check never compares anything today: no shipped runner implements QuotaReporter, so every real run skips the check, and the estimate leaves out fix rounds, so it is a lower bound.related itd-2611011230226453 · related itd-2611031342011261
- iss-2610100913096412The run-start quota query has no deadline and its error is not home-redacted: Config.Quota runs on context.Background, so the first runner that reports a quota over I/O can hang build and drain at start, and its error reaches the run record and the checks row with the home path in it.
- iss-2610100938485695The rm-unguarded-variable-path guard entry misjudges three edge shapes found in its review. (1) Inside a double-quoted shell string the successor's own rewrite is refused: sh -c "rm -rf ${X:?}/y" blocks, because the re-read string spells ${X:?} as ${X} (payload.go spellParameterAt), so the refusal tells the agent to do what it did; single quotes avoid it. (2) A nested guard is not read: "${VAR:-${OTHER:?}}"/y and "${VAR:-${OTHER:-/tmp}}"/y block although both are guarded (varpath.go stripEmptyableRefs strips the inner reference). (3) A site followed by a substitution is not followed: rm -rf $VAR$(true)/x is allowed (varpath.go).
- iss-2610101610446956abcd intent ready reported itd-82 READY while abcd build itd-82 refused it at check (open_questions) for two open questions in its record: the readiness verb does not run the check the build makes, so READY does not mean the build will start.
- iss-2610101617040184Peer sessions' holds on open issues reached this drain only as chat: on 2026-10-10 three sessions (abcd-0b, abcd-a5, abcd-49) named eleven issues to keep out of an abcd drain, none of them through implement claim, because their lanes were build runs or plans that take no claim until a lane opens. The drain cannot see any of them, so the only guard was the driving session hand-skipping each one when a lane opened on it. Evidence for iss-2610090642385898, which a peer is building as the drain's skip-for-now; filed apart because that record is being edited on the peer's lane.
- iss-2610101617043118A drain left in progress by a session that has ended stays in force with no owner. On 2026-10-10 a new session's bare abcd drain silently resumed a drain begun on 2026-10-07 (last move 2026-10-08 05:20, since when no session drove it), inheriting its --pace 10080/0 and --sub-agents 6. Nothing in the payload named who began it, when it last moved, or that its ceiling was set for another session's share of the machine's agents. Three live peer sessions were asked and none owned it. A second drain cannot start while it stands, and --pace or --sub-agents naming anything else is refused, so the only ways forward were to inherit it or move drain.json aside by hand, as an earlier session already had (drain-2026-10-07-paced.json).
- iss-2610101659347329abcd implement receipt <path> is refused at the state stage when more than one run is in progress, asking for --run, although the receipt path it was given (.abcd/.work.local/run/<run-id>/lane-N/...) already names the run. On 2026-10-10 a drain lane's receipt was refused this way because 24 stale runs from an earlier drain were still in progress; the next the drain itself printed (run `abcd implement receipt <path>`) omitted --run too, so following it verbatim fails.
- iss-2610101707453618When the implement loop's brief stage refuses a base without AGENTS.md, its remedy tells the person to run `abcd prepare-this-repo`, a binary verb that does not exist (it exits 2 as an unknown command); prepare-this-repo is the plugin command /abcd:prepare-this-repo. Both the intent brief (brief.go) and the issue brief (issuebrief.go) carry the same wrong text.
- iss-2610101803326081The brief's launch chapter's refusal-kinds table describes unfixed-finding as the consequential (major/critical) finding case only, while the guardrail list forty lines below now says it also fires for an open issue record that differs from HEAD (added by the drain lane for iss-2610072347238476, which left the table row alone because a peer's verb split edits nearby). The table and the list now disagree within one chapter.
- iss-2610101819067941The cold-reading exclusion floor disagrees with itself about heading case. TestTheFixtureLeakIsAbsentUnderEveryCommittedPreset (smoke lane) failed when a record carried a '## Open questions' heading (lower-case q): the redactor, redactExcluded in internal/core/reading/project.go, looks the heading up exactly, case-sensitive, while the verifier compares with strings.EqualFold. So a record whose excluded heading differs only in case is not redacted but is refused, and reading assemble fails for the whole repository. It fails closed, so nothing leaks, but any record author can break the assembler with a lower-case heading.
- iss-2610101900387053A drain opens a full lane on an issue whose fix has already landed under another issue's id. On 2026-10-10 the drain took iss-2610080546210831 (prepare-this-repo's unconditional core.hooksPath step); commit afa6e7b16 had already made that step conditional while citing iss-2610081312364884, so the record stayed open. The lane spent about 35 minutes and 92k tokens to find nothing to fix, then added a guard test so the landing could resolve it. Neither the dry run nor abcd capture mentions sees this, because the fixing commit names a different issue.
- iss-2610101903385281Two siblings of the core.hooksPath advice that prepare-this-repo now makes conditional still give it unconditionally. .github/CONTRIBUTING.md (around line 64) tells every clone to run git config core.hooksPath .githooks, and the commit-msg hook's 'no abcd source' refusal (.githooks/commit-msg around line 162) prints the same command. On a machine whose global hooks dispatcher is in force (ahoy's banlist.hooks_path reports foreign), either one overrides that dispatcher instead of having it call .githooks/. The 2026-10-10 drain lane's reviewer found them; that lane's remedy did not cover them.
- iss-2610101930219027An ATX heading line inside an HTML block ends the cold-reading redactor's span early, so the rest of an excluded section travels. The redactor spans sections by the site section walk (sectionSpan in internal/core/reading/project.go over site.Sections), which reads a column-0 '## Next' as a heading even inside a `<div>` block, while a renderer reads that line as raw HTML. For `## audit notes / SECRET / <div> / ## Next / SECRET-IN-DIV / </div> / ## After / KEPT`, SECRET-IN-DIV travels. The verifier refuses a fence opener inside an HTML block (fenceInHTMLBlock) but has no heading-in-HTML-block refusal, and the redacted text it reads has already lost the `<div>` line. Pre-existing on main; the case-insensitive redaction made it reachable for case-variant headings too.
- iss-2610101930329211The cold-reading exclusion floor's sameRendering (internal/core/reading/project.go) compares heading titles by site.Slug, which is coarser than 'renders the same': the slug collapses every run of non-alphanumerics to a hyphen, so '## Open/Questions' slugs like '## Open Questions' and is treated as the excluded heading. Since the redactor now shares namesExcludedHeading with the verifier, such a heading is silently redacted rather than refused, so a section that merely slugs alike disappears from the bundle without a word.
- iss-2610101930333607A heading spelled with a Cyrillic confusable, '## Аudit Notes' with a Cyrillic A (U+0410), is neither redacted nor refused by the cold-reading exclusion floor, on main as on the redaction-case branch: namesExcludedHeading folds case and compares slugs, and both compare code points, so the excluded section travels into the bundle. The floor discloses homoglyphs as residue in a comment beside namesExcludedHeading, but nothing refuses them.
- iss-2610102020442624Several sessions' make preflight runs overlap on one machine with nothing to space them out, and the overlap fails gates on tests no lane touched. On 2026-10-10 evening, two other sessions' full test suites were running at once (two go-build trees, a dozen .test binaries at 40-80% CPU each) and the one-minute load reached 124 on 16 cores. Four drain lanes in a row then lost a preflight run to load-only timeouts: TestAnIssueLaneLandsOnePullRequestThatResolvesItsIssue and TestAClosedPullRequestIsRefusedAndNothingIsCleanedUp (internal/core/implement/loop), and two internal/core/interview tests ('WaitDelay expired'). Each passed alone. The preflight load check (implement load --site preflight) warns above four times the core count but never waits, so every lane pays a re-run of about 20 minutes, and a lane whose re-run also lands in a peak has its receipt refused.
- iss-2610102020447522Two internal/core/interview tests fail under machine load with 'WaitDelay expired' (a different test on each run), on 2026-10-10 in two consecutive make preflight runs of a drain lane at load averages of 31 to 57 on 16 cores; the package passes when run alone and under the race lane. The tests' subprocess wait is a fixed wall-clock budget that a loaded runner overruns, the same shape as the openaiapi stream test fixed for iss-2610080243367274.
- iss-2610102021042657Once the drain lane for iss-2610090642392144 lands, this repository's AGENTS.md and .abcd/rules.json say a verifier's copy goes outside every working tree, never under .abcd/.work.local/scratch/. The bundled default CONCURRENCY rule every managed repository receives and the principle the-users-directory-is-theirs.md still allow it in the checkout's .abcd/.work.local/ tier, and itd-193 and adr-2609091014087993 quote the archive command without saying where the copy goes. Changing the bundled rule changes what every managed repository is taught, so that lane left it alone.
- iss-2610102021189565The shell guard's hook refused an abcd capture command as script-unread because one of its option values, the --found-at value, named a JSON file under internal/core/rules/defaults. The guard treated that file as a script the command runs and reported that it 'runs .abcd/docs-lint.json inside a chain of scripts deeper than the guard reads'. Nothing was executed: the path was a plain string argument to abcd capture, preceded by a cd and joined with &&. The same capture went through with the path reworded as prose (2026-10-10, abcd-60 drain run).
- iss-2610102142432879A peer's announced record freeze cannot hold pull requests that were armed for auto-merge before it began. On 2026-10-10 a session opened a freeze so it could rename every record with a long slug (#904), and the drain session parked its new lanes. But a drain lane PR (#901), armed by the implement loop's landing an hour earlier, merged through the queue during the freeze. Its record move under the old long name broke #904's queued tree, which dropped #904 from the queue and cost about an hour of re-merging and re-queueing. Nothing listed the PRs each session had armed, and nothing let the freeze disarm them.
- iss-2610102343100369Once the drain lane for iss-2610072347247487 lands, the lifeboat probe grounds the personas section from an authored brief file, as it does every other human-owned section. The design record still predicts the old ceiling: the personas row of the lifeboat mapping Table (internal/core/lifeboat mapping.go, around line 151) and the generated mapping table in the brief's 00-meta.md say 'only partial there'. The probe now exceeds that on abcd's own tree, which has about 859 bytes of personas prose. Both of that lane's reviewers noted it as outside its remedy.
- iss-2610110012045504A validated lane cannot take the default branch in before it lands. On 2026-10-11 three drain lanes held through a peer's record-rename freeze were validated against a base that the rename then moved. Merging origin/main into one lane branch before its landing made implement step refuse at land ('is at <merge>, not at the head <sha> its validators judged'). So the only order that works is to land on the stale base (the resolve commit moves the record under its old long name), push, open the PR, and only then merge main and run the rename tool on top. Each lane then pays a third full preflight, and its PR is conflicting until that second push.
- iss-2610110025455728The rm-unguarded-variable-path guard entry allows an alternative inside a double-quoted shell string: sh -c "rm -rf ${X:+x}/y" is allowed, although the enclosing shell expands ${X:+x} to nothing when X is unset and the string's shell then deletes /y. The direct form, rm -rf ${X:+x}/y, refuses. The cause is the payload re-read: the alternative's texts are the empty text and x, neither names a variable, so the string is written out as rm -rf /y and rm -rf x/y and neither reading leads with a variable (payload.go namedPayloads, varpath.go leadSpelling). It has been allowed since the entry landed in #889. The same re-read misses a default the enclosing shell writes as an escaped reference: sh -c "rm -rf ${X:-\${Y}}/y" and ${X:-\${Y:-}} are allowed, although every shell hands the string rm -rf ${Y}/y. The default's body ends at the first }, so its text is ${Y, and the written text ${Y}/y does not pair with the marked word, whose } follows the mark (payload.go fitsWritten); main allows it too. Separately, the edge fix refuses sh -c "rm -rf ${X:-\\ }/y", whose escaped blank the string's shell keeps as text; this is a deliberate over-refusal (varpath.go emptiedInside) and main refused it too.
- iss-2610110233253365On the library surface 'ingest' now names two different acts: abcd library ingest distils a source into the memory store's cited pages, while the /abcd:ingest page (to fold into the library page in step 6 of spc-2610100613109045) means registering a document in the sources corpus, which is abcd library add. Every sub-verb kept its name under decision 7, so a person who learned ingest as register will run the distiller, and one who reads the page title will look for a corpus verb named ingest.
- iss-2610110253059544gitutil's one-time git version probe (internal/gitutil lazyfetch.go) runs with no deadline and under a process-wide lock. So the first git call of a process whose git hangs blocks in that probe, and every other git call waits on the lock behind it. For the status line this means a hung git ends the verb at its 500ms overall limit with the wrong message, and the hanging git version child is never killed, so one is left behind on every refresh. Found by the 2026-10-11 drain lane for iss-2610090642407850: a test's hanging fake git, answering the probe, blocked every git in its test process for 30s.
- iss-2610110348151970lint.UnwrapPrincipleLinks ends a link destination at its first ')' and a label at its first ']', so a principle statement linking [label](https://x/Audit_(finance)) projects a fragment of the address into the reading bundle
- iss-2610110359273529After the drain lane for iss-2610092011131598 lands, the surprise, admission, disposition and reframe records redraw a minted id only when it clashes with a record this same process wrote, and still refuse a clash with any other existing record. The issue and reading-item allocators redraw on any clash (spc-33 ruling 2). Both of that lane's reviewers noted the split. The retained refusal guards against overwriting, which a redraw never does, so it protects nothing a redraw would endanger, and it can still fail a same-second mint against a peer's committed record.
- iss-2610110401224302A lane's pull request can leave the merge queue without anyone being told, and its auto-merge falls off with it. On 2026-10-11 the queue removed two drain PRs. #906's queue CI was cancelled when a peer's PR was re-queued ahead of it. #903 was removed about 45 minutes after entry while its macOS check was still running. Both then sat open and unarmed. Meanwhile implement step went on reporting only 'pull request #N is not merged yet', because it reads merge state, never queue membership or the armed flag. They were found by hand an hour or more later.
- iss-2610110432159652The guard's question check lets a question without abcd's label through without a word when git cannot name the repository root for a directory that looks like a repository. The hook writes nothing at all: an empty stdout, exit 0 and an empty stderr. The guard's own rule is to fail open, but loudly. On a loaded machine this silence was what TestModeMadeQuestionAbcdsSaysSo met on PR #858, before f1703a29f removed the 50ms root-lookup deadline. The silent branch is still there for any other reason the lookup fails.
- iss-2610110456358519The surface register's sweep checks commands/ and hooks/ pages against the register in both directions, but the prompt files under agents/, which a harness registers as invocable agents, are checked in neither: nothing asserts an agent page has a register row, and nothing notices one added or removed.
- iss-2610110613372021When the merge queue rebuilds its groups (an entry dropped, re-queued or re-armed), the CI runs of the superseded groups keep running and holding runners, though their gh-readonly-queue refs are deleted and nothing reads their results. On 2026-10-11 nothing merged from 03:36 to past 07:00 BST. Seven stale merge-group ci runs (PRs 903, 906, 908, 911 and 915 at older shas) held the runners while every live group's run sat queued, until a session cancelled them by hand.
- iss-2610110908443341The implement loop arms a pull request that GitHub reports as conflicting and then waits on it in silence. #902, lane-1 of run-2610101724174688, had appended to .abcd/work/DECISIONS.md while later merges to main appended too. Local git merges that cleanly through the union driver; the forge ignores the driver, so #902 was armed but never entered the queue. For 13 hours every implement step said only 'pull request #902 is not merged yet', and the loop's rule that nothing is pushed after arming left it no way out.
- iss-2610110915210571A drain that an outage stops while it waits on a host judgement keeps its judging entry: that move prints 'awaiting the host judgement' beside 'ended: the run gave up', and a --judgement given afterwards is refused. Nothing wrong is written, but the drain both claims to wait and refuses the answer.related itd-2611041549461012
- iss-2610110915232822PromoteRequest.Grounds is documented as REQUIRED and a later comment names requireGrounds, but Promote reads it through optionalGrounds, and the drain's hand-back calls Promote with none. The code is right and the comments are stale, so a reader is told a call the drain makes would be refused.
- iss-2610110918418459The implement loop's landing never writes a spec step's '- landed:' line, so a spec the loop landed part of still reads those steps as unlanded: a later 'spec close --remainder' carries steps that already merged into the remainder, and a fresh 'abcd build' of the same spec opens a lane for them again. Found by the fidelity audit of itd-2609212103565953 (receipt rcp-2257cc3a38d9, criterion ac-3 MET_WITH_CONCERNS); spc-2609202134338445's Progress already says the landing does not mark a non-closing lane's step.
- iss-2610110938282654check (macos-latest) runs on every pull request as well as on every merge-queue entry, and macOS is the account's scarcest runner, 5 jobs at once at a median 40 minutes each (8 queue runs, 2026-10-11). Between 03:36 and 08:40 on 2026-10-11 nothing merged: entries waiting for a macOS slot passed the queue's timeout and were removed. Every push already passed make preflight on a Mac, so the pull-request macOS run repeats a local run, and only the queue run tests the merged tree.
- iss-2610110938293273The macOS leg tests twice: go test ./... (median 13.6 min) and then go test -race ./internal/... (median 23.1 min), of a 39.9-min median job over 8 queue runs on 2026-10-11. The race pass already runs every internal test, so the plain pass adds only the packages outside internal/ at a third of the job's time.
- iss-2610110938294826ci.yml runs the full gate again on every push to main, though with the merge queue every commit on main is the merge result the queue already tested: 68 push runs in the 6 days to 2026-10-11 against 71 merged pull requests, each taking a macOS slot.
- iss-2610110939547495The account runs at most 5 macOS jobs at once, which is the binding limit on the merge queue: on 2026-10-11 queue entries waited for macOS slots past the check timeout and were removed. GitHub documents that support can raise concurrency limits; nobody has asked.
- iss-2610110939559446Every push already carries a local make preflight receipt that ran the same gates CI runs, but CI cannot see it, so the pull-request run repeats the work. The receipt is the pusher's word, not an attestation, and with many agents pushing that is too weak to replace the queue run; it could only spare duplicate work before the queue.related itd-2610261025516272
- iss-2610110941283143A push to an open pull request started only some of its workflows: after b36b551ac was pushed to #904 (2026-10-10, about 22:50Z) only external-review ran, ci and attribution never triggered, and the pull request sat BLOCKED with eight of its nine required checks missing until it was closed and reopened. Nothing noticed: the checks were not failing, only absent.
- iss-2610110941289527The merge queue's check timeout was shorter than one macOS queue entry takes: over 33 merge-group ci runs (2026-10-10 18:00Z to 2026-10-11 09:40Z) a macOS job waited a median 40 minutes for a runner (p90 68, max 81) and then ran a median 40 (p90 44), so an entry needed about 80 minutes against a 45-minute timeout. Every entry that had to wait was removed: #903 and #906 twice each, #908, #910, #913 and #915 once (#913 at 04:46:54Z with every check green but macOS, run 38110208736). Nothing merged from 03:36Z to 09:38Z with 15 entries queued. The person has since set 2 entries and 90 minutes (ruleset 19969675, mirror PR #926); 90 is still tight against 80.
- iss-2610110941305040Stacked pull requests serialise behind the merge queue: verb-split steps 2 to 7 are #913, #918, #919, #920, #921 and #922, each carrying the previous step's commits, so none can merge before the one below it and every queue removal of a lower step delays the whole stack. On 2026-10-11 #913, the stack's base, was itself removed from the queue at the macOS timeout.
- iss-2610110946486757The kill-by-search guard entry allows a search inside a double-quoted shell string's default: sh -c "kill ${X:-\$(pgrep make)}" is allowed, although with X unset the string's shell runs kill $(pgrep make). The same search written straight into the string, sh -c "kill \$(pgrep make)", refuses, and so does the direct kill ${X:-$(pgrep make)}. The string's re-read takes only spellings and varLead from the written string, never the feeds of the substitutions it holds (payload.go namedPayloads, payloadInput), so the search's output never reaches kill. main allows it too; it was found by the review of the fix for iss-2610110025455728.
- iss-2610111007107579The pace window clock and the locked JSON state file beside the runs exist twice in the implement loop: loop/drain.go keeps drain.json under drain.lock with window_started_at and next_eligible_at, and build next's series (loop/nextseries.go, landing with itd-2609211116005482) keeps next.json under next.lock with the same fields and the same window logic, copied because drain.go is mid-change under itd-82. Two copies is the point the one-canonical-primitive principle files it.
- iss-2610111007113635A single 'abcd build next' can pick an intent that a completed run already delivered: the pick excludes only intents with a run still in progress, and once the landing has merged and removed the lane's branch, a checkout whose main has not been pulled still holds the intent in planned/, so the pick starts a second run for delivered work. A series excludes what it already picked, so only the single pick is exposed. Reported by the build-next implementer (run-2610110908001704).
- iss-2610111014215034A move that starts a run and then records it is two durable writes, so a process killed between them leaves a run its series never records: in build next's series (loop/nextseries.go, startPick then finish) a --max 2 series can start three runs and never report the orphan's outcome, and the drain's drainMove (Start then finish) has the same gap. Found by the build-next lane's ruthless review (run-2610110908001704).
- iss-2610111014218303Two verbs in the implement loop read one lane state differently: build next's series counts a pick delivered only when its run is Complete(), which a lane whose pull request is left open for a person to merge never reaches, so 'build next --until-empty' in such a repository makes one pick and then only says 'drive run X' until a person merges; the drain reads the same state as DrainLanePullRequest and moves on, because the merge is a person's gate. itd-2609211116005482 decision 4 calls the two flags shared with the drain, and criterion 5's 'its lane stops' does not say which reading is meant. Found by the build-next lane's ruthless review (run-2610110908001704).
- iss-2610111549593667The sync merge fails on git older than 2.44 (Apple Git 2.39.5) when an attribute selects a merge driver: BuiltinMergeDriver, the merge-file command that replaces every repository merge driver (iss-2610090821510097), passes --diff-algorithm=histogram, which merge-file only accepts from git 2.44, so git merge exits 1 with "unknown option 'diff-algorithm=histogram'" even on a clean merge. The repository's driver still does not start and the merge.default case passes. Reported as GitHub issue #894, pinned at 3b8700ef7.
- iss-2610111552464704A README.md just under ahoy's 1 MiB read cap (maxAhoyFileBytes) can be written past it by the README-parts writer: syncReadmePartsLocked reads the file under the cap, composes the parts into it and writes the result without measuring it, so a 1,048,566-byte README became 1,048,701 bytes. Every later sync or removal then refuses with 'file exceeds size cap' at the guarded read, so abcd can no longer take its own part back out of a file it grew. Found by the security review of README parts step 1 (spc-2610031704338417, itd-2610031348087517); the writer is staged and not yet called from setup.
- iss-2610111559070779The guard allows `zsh -c` lines that bypass it through process substitution spelled `=(...)`: zsh writes the substitution to a temporary file and sources it, while the tokenizer reads `=` as a plain word, so a bundled blocker inside an `echo` or `cat` runs as the operator with exit 0.
- iss-2610111600022820The guard allows a zsh line that loads a function file through `FPATH` or `fpath` and `autoload`: zsh reads the file and runs its body when the function is called, and the guard never opens it, so a bundled blocker in that file runs as the operator with exit 0.
- iss-2610111600031244The guard's script reader resolves a different file than bash runs in three ways: after `cd` it keeps the logical path (so `cd -P link && bash ../s.sh` judges the file beside the link while bash runs the one beside its target), it ignores `CDPATH`, and `source` of a bare name ignores a `PATH` prefix on the same command. Each lets a planted script carrying a bundled blocker run with exit 0.
- iss-2610111600039059The guard judges `BASH_ENV` as literal text, but bash expands the value (command substitution, parameters, tilde) before using it as a filename, so `BASH_ENV='$(<blocker>)' bash -c true` runs the blocker during that expansion, and `BASH_ENV='$HOME/f' bash -c true` runs a file the guard never reads.
- iss-2610111600044238The implement loop's outage probe runs `git ls-remote --exit-code origin HEAD` with the isolated git pins only, and those pins do not set `protocol.ext.allow`, `credential.helper`, `core.sshCommand` or `remote.<name>.uploadpack`, so a program the checkout's git config names for any of them runs as the operator on the next due network probe.blocked by iss-2610111600058575
- iss-2610111600048326A planted gitfile defeats the toplevel check that GHSA-6wfm-pfhv-w267 added: with `core.worktree=../..` in a checkout `co` and a one-line `<parent>/.git` reading `gitdir: co/.git`, `holdsGitDir` accepts the parent, so `Toplevel` and `CheckoutRoot` return the parent and every store, the implement run and its `git add -A` address a directory outside the checkout.blocked by iss-2610111600058575
- iss-2610111600051340A one-letter `exclude_path_fragments` entry (for example `e`) passes `mergeConfig`, matches by substring nearly every path, and drops a file holding a secret from the release scan while one other scanned file keeps the zero-coverage sentinel quiet, so the secret is copied into the release payload and the ship gate does not refuse.
- iss-2610111600058575`abcd implement step --restart` snapshots the lane worktree with `read-tree` and `add -A`, then runs `reset --hard` and `clean -fd`, all without `FilterOverrides`, so a clean or smudge filter the lane's `.gitattributes` and git config name runs as the operator. The rate-limit checkpoint calls the same `saveAside` with reset for an implementer.blocks iss-2610111600044238 · blocks iss-2610111600048326
- iss-2610111600065621record-lint's armed agent-diff check counts any added diff line starting `+prompt_version:` as a version bump, so an instruction edit under `agents/` passes at an unchanged `prompt_version` when the diff also adds a body line `prompt_version: <same>` or adds one trailing space to the frontmatter line.
- iss-2610111701536641The status line should show which session it belongs to, the short name peer sessions use to message each other (for example abcd-60 or abcd-a5), so a person running several sessions in one repository can tell them apart and address one. Checked against the host's status-line documentation (code.claude.com/docs/en/statusline, 2026-10-11): the payload abcd's statusline verb reads on stdin carries session_id (a UUID) and session_name, which is present only when the person named the session (--name or /rename) or the host generated a title, but never that default short name, and no environment variable or file exposes it. The short name cannot be derived from session_id: this session is abcd-0b while its id begins d3616efc. internal/core/statusline/payload.go reads neither field today. Related: iss-2609291032194222, whose session-bound remedy also reads the payload's session id.related itd-2610111707085098
- iss-2610111724587800record-lint's agent-contract bump check never sees an edit made through a symlink: when agents/<name>.md is a symlink to a file elsewhere in the repository, editing the target changes nothing under agents/ in the diff, so an instruction change ships with no prompt_version bump and no finding. Found by lane X while fixing the unbumped-prompt check (iss-2610111600065621) on 2026-10-11; predates that change. Under abcd-fixes-what-it-adds this is abcd's own check not doing what it claims, so it is abcd's to fix.
- iss-2610111726481495The status line's counts should show what can run autonomously now, not the backlog. Today 'itd 139 · iss 332' counts every intent not yet shipped (drafts plus planned) and every open issue (internal/core/statusline/compose.go:139-160), which the product thinker said is not the number they care about. They want planned intents ready to build, and issues that need no design decision. Both exist already: the board's Now/Next block runs the readiness gate over planned intents (Next: 15 READY at main 22492dbf4, plus the Now rows), and 'abcd drain --dry-run' classifies open issues (64 eligible, 264 handed back, 4 without a remedy). Measured on this machine, the board took 4.9s and the drain dry run 0.55s; the status line's own work stops at 500ms, so neither can be computed on every refresh.
- iss-2610111729375108abcd's lane worktrees and restarts in a repository that uses Git LFS hold LFS pointer text instead of the real files. Lane creation (`git worktree add`, internal/core/implement/loop/lane.go) and a restart's `reset --hard` (restart.go) run through gitutil's isolated environment, which sets GIT_CONFIG_GLOBAL=/dev/null (internal/gitutil/repo.go), so the filter that a normal, global `git lfs install` defines is never seen and nothing is smudged. Reproduced 2026-10-11 with git-lfs 3.7.1: in a repository whose image is tracked by LFS, the person's own `git worktree add` writes the image's bytes, while the same command with GIT_CONFIG_GLOBAL=/dev/null writes `version https://git-lfs.github…` pointer text. The implementer then builds and tests against placeholders. This is abcd changing how a repository works, which the security scope rule (principle abcd-fixes-what-it-adds) forbids.
- iss-2610111729399920Several hardenings shipped in v0.13.4 switch a repository's own git settings off for abcd's commands, and need re-assessing against the security scope rule adopted on 2026-10-11 (principle abcd-fixes-what-it-adds: abcd never changes how a repository works on its own, and prevents an existing risk only where it can do so without such a change). Known instances: a sync's merge makes every configured merge driver git's built-in merge (gitutil.MergeDriverOverrides), so a repository's own lockfile or union-style driver is ignored on abcd's sync; the pick commit runs with commit.gpgsign=false and hooks off (gitutil.ExecPins via pickGit), so it is unsigned where the repository requires signed commits; the toplevel check refuses a checkout whose core.worktree names an ancestor, which refuses a deliberately configured layout. Reads that blank content filters (gitutil.FilterOverrides) change no repository behaviour and are likely fine.
- iss-2610111729417484`abcd guard check` given the command line as a positional argument (`abcd guard check 'git status'`) refuses with cobra's "unknown command … for abcd guard check" and exit 2, which the verb documents as 'a guard that cannot be evaluated'. A caller reading the exit code is told the command is unparsable, and the message does not mention --command or stdin, the two forms the verb takes. Hit on 2026-10-11 while reproducing guard advisories: every case returned exit 2 until the --command flag was found in the help.
- iss-2610111729420007make preflight's unit pass runs `go test` with the default ten-minute package timeout, and internal/surface/cli exceeded it on 2026-10-11 (panic: test timed out after 10m0s, in TestStatuslineHungGitDoesNotFreezeTheLine) while the machine's five-minute load average was 133 with several sessions running preflights and sub-agents at once. Every other package passed and the branch changed no Go code, so the failure was load, not the change; a second run was started at load 48. Concurrent sessions are the normal way this repository is worked on, so a load-sensitive package timeout fails preflight for nothing and costs a full re-run.
- iss-2610111729434988When an abcd interview asks the product thinker to approve text that will be posted outside the repository (an advisory, a pull-request body, an issue), the register rule rewrites that text into product terms, so the person approves a paraphrase and the agent then posts a different, technical wording. On 2026-10-11 a product-register question approved a plain-words sentence for a draft security advisory, and the sentence actually posted was a technical rewording the person never saw. The GRILL asking rules (bundled rules domain) say to quote the thing being decided, but the register rule overrides it for this case.
- iss-2610111730513071The guard does not track zsh's `path` array, which zsh ties to PATH: a zsh line that assigns `path=(<dir>)` and then runs or sources a bare script name searches <dir>, while the guard's script reader judges the file its own PATH search finds. Left open by lane G on 2026-10-11 while fixing the script-lookup gap (iss-2610111600031244), because in bash `path` is an ordinary variable name and tracking it there would misjudge bash lines.
- iss-2610111730551327zsh's `source` (and `.`) of a bare name looks in the current directory before PATH, while bash and the guard's script reader search PATH first, so on a zsh line the guard can judge a different file than zsh runs when both a working-directory file and a PATH file share the name. Left open by lane G on 2026-10-11 while fixing the script-lookup gap (iss-2610111600031244).
- iss-2610111730574385An FPATH already exported in the hook's environment and then changed on the line by a plain assignment (no export) is not handed to a child zsh, so the guard's autoload reader, which now tracks FPATH set on the line, can judge the function file from the line's value while the child shell searches the inherited one. Left open by lane G on 2026-10-11 while fixing the FPATH and autoload gap (iss-2610111600022820).
- iss-2610111730597708After `unset CDPATH` on the line, the guard falls back to the hook environment's CDPATH, so a `cd name` that bash would resolve without CDPATH is still blocked: a false block for a person who exports CDPATH, the one group the new CDPATH block reaches. Left open by lane G on 2026-10-11 (iss-2610111600031244).
- iss-2610111737295671The agent-contract bump check counts any different prompt_version as a bump, so an instruction edit that moves an agent's prompt_version back to an older value whose changelog entry already exists passes both halves of the check with no new entry. Found by the Fable review of lane X on 2026-10-11 (probe: main...HEAD and main..HEAD both report zero findings); predates the fix for iss-2610111600065621 and is outside its remedy.
- iss-2610111749083184With CDPATH exported in the hook's environment, the new CDPATH block (iss-2610111600031244) blocks every bare `cd name`, on the line and inside every script the guard reads (`bash build.sh` whose build.sh runs `cd sub` blocks as script-unread), including where only one directory can match; and the message never says the CDPATH came from the environment, so a person whose line never mentions CDPATH is told to edit a third-party script's cd. Found by the Fable review of lane G, 2026-10-11 (cdSearchesCDPATH: if !set { return rc.files.cdpath != "" }).
- iss-2610111749093946`cdOperand` takes an option it does not know (zsh's `cd -q sub`, `pushd -n sub`) as the operand, so with CDPATH set the option word is 'searched' and the line blocks with a misleading reason (observed: cd -q sub && bash s.sh blocks). Found by the Fable review of lane G, 2026-10-11.
- iss-2610111749099986zsh's common idioms `fpath=(~/.zfunc $fpath); autoload -Uz compinit; compinit` and `fpath+=(dir); autoload -Uz compinit` now block as script-unread, because the autoload search reaches the unfixed $fpath element before finding compinit, although a function found only in the account's own directories is what the guard already treats as unseen when FPATH is untouched. Found by the Fable review of lane G, 2026-10-11 (autoloadTargets).
- iss-2610111759340919abcd intent interview ends with a READY verdict computed by plain intent.Ready, so it can report 'the record is READY' for a planned record whose ## Open Questions still lists an unanswered item, which abcd intent ready now reports NOT READY (open_questions) and abcd build refuses at check (open_questions). Found by the ruthless review of run-2610111657111142 lane-1 (iss-2610101610446956).
- iss-2610111759346608The abcd itd-N dispatcher computes a planned intent's next move from plain intent.Ready, so for a planned intent whose ## Open Questions still lists an unanswered item it says 'ready — implement against the spec body', while abcd intent ready reports NOT READY (open_questions) and abcd build refuses at check (open_questions). Found by the ruthless review of run-2610111657111142 lane-1 (iss-2610101610446956).
- iss-2610111809142536zsh reads `cd X Y` with two operands, and an option word it does not take (`cd -e X`, `cd -@ X`, `pushd -n X`), as the substitution form: it replaces the first word in the current directory's path with the second and enters the result, so the guard's script reader judges a script in one directory while zsh runs the one in another. Found by the Fable review of guard round 2 on 2026-10-11 (reproduced with zsh 5.9: `cd <p>/with-n/dir && pushd -n sub && pwd` prints <p>/withsub/dir); the cd forms predate that round, and round 2 made pushd -n read as staying put.
- iss-2610111815024967The guard's script reader treats `pushd` with no operand as going to HOME, but bash swaps the top two directories of the stack instead (zsh does the same unless an option sends it home), so the scripts that follow can be read in the wrong directory. Noticed by guard round 3 on 2026-10-11 while fixing the zsh cd substitution form (iss-2610111809142536); predates it.
- iss-2610111820465940The pre-commit hook ahoy install scaffolds into adopted repositories (internal/core/ahoy/defaults/pre-commit, header lines 8-10) still tells every clone to run 'git config core.hooksPath .githooks' unconditionally, which shadows a foreign global hooks dispatcher instead of having it call .githooks/. A third sibling of the advice iss-2610101903385281 made conditional in CONTRIBUTING.md and the commit-msg hook; found by that lane's review (run-2610111657473488, PR #939).
- iss-2610111826193257Concurrent sessions gate their preflights and race runs with hand-written shell waiters, because abcd has no wait-for-capacity primitive: 'abcd implement load' (make preflight's load-check) only warns, never waits. On 2026-10-11 a waiter written as 'pgrep -f "go test -race"' matched its own bash command line, which contains that string, so it always saw a race run going and never opened; when such waiters were stopped or edited they released together, and the machine (16 cores) reached a one-minute load of about 500 with four race runs at once, one peak near 920, while unrelated preflights timed out (internal/surface/cli hit its 10-minute test limit at TestSiteVerbsSayWhichLabelsTheyAdded). Reported by peer session abcd-a5; the anchored forms that work are pgrep -f '(^|/)go test -race' and ps -Ao command | grep -c '^go test -race'. Two separate failures: the self-match, and many waiters with the same release condition opening at once (a thundering herd).
- iss-2610111850237083The README contents part builds each anchor slug from the heading's markdown source rather than its rendered text, so an emoji shortcode or an HTML entity in a heading gives an anchor the forge does not have: `## :rocket: Launch` is linked as `#rocket-launch` where the forge renders `#-launch`, and `## A & B` as `#a-amp-b` where the forge renders `#a--b`.
- iss-2610111850405447The README contents part carries a heading's inline HTML raw into the list text and its tag characters into the anchor: `## <a name="install"></a> Install` is listed with the tag in its link text and an anchor built from the tag's characters, where the forge renders the heading as `Install` with the anchor `#-install`.
- iss-2610111851225403After round 4 of the guard fixes (iss-2610111809142536), a cd whose option word has letters neither shell takes (`cd -x sub`) still leaves the directory unknown, so a following `bash s.sh` is allowed unread, while zsh reads the line as its substitution form (replacing `-x` in the current path with `sub`) when that string occurs in the path. Noted by guard round 4 on 2026-10-11; the same allow-unread held before round 3.
- iss-2610111851312171The README contents part lists an ATX heading that sits inside an HTML block no blank line has closed, though the forge renders that line as text: `<div align="center">` then `## Title` then `</div>` gives a contents entry linking an anchor the page does not have.
- iss-2610111855583968The guard's cd reader gives bash's reading no directory for three or more operands, but macOS /bin/bash 3.2.57 enters the first operand of `cd a b c` and exits 0 (verified 2026-10-11 with cd and pwd only), so a following `bash s.sh` runs the script in `a` while the guard leaves it unread. Same class as iss-2610111809142536; round 5 added the first operand for two operands only.
- iss-2610111855592575A bare `cd -x` (an option word neither shell takes, with no operand) leaves the directory unknown in the guard, but zsh 5.9 enters a directory literally named `-x` when one exists (verified 2026-10-11 with cd and pwd only), so a following `bash s.sh` runs the script there unread. An existing test expects the allow; zsh's -N directory-stack words need care.
- iss-2610111926302443TestWorktreeStoreRuleNamesTheIntentsActualState (internal/core/lint/conventionsfile_test.go) checks for stale draft wording per blank-line paragraph, and the references list in .abcd/development/brief/04-surfaces/34-build.md is one paragraph naming six intents, so a later '(a draft)' beside a different intent in that list would fail the test naming itd-2609091014076309 falsely.
- iss-2610111926302792Present-state planning prose still calls itd-2609091014076309 'the store draft' although the intent is in planned/: itd-148 (lines 64 and 188), spc-42 (lines 27 and 112) and iss-213 (line 11). The drift fix for iss-2610090744073409 corrected the CONCURRENCY rule, the build brief page and lane.go, and left these planning records as out of its remedy's scope; its ruthless review recorded them.
- iss-2610112021163993The README contents part doubles every backslash in a heading's text, so a markdown escape renders wrong in the list: `## A \* b` is listed as `[A \\* b](#a--b)`, which the forge shows as 'A \* b' while the heading reads 'A * b'; an escaped backtick (a backslash before a backtick) becomes a literal backslash before a backtick that can then open a code span. escapeLinkText (internal/core/ahoy/readme_derive.go) escapes \ to keep a trailing backslash from escaping the link's closing bracket, but it also re-escapes the backslash of every escape the owner wrote. Found while making the contents part read code spans literally (lane-3 fix round 1, run-2610110908176735).
- iss-2610112021361821readme.created can still vouch for an owner's README.md when no abcd run sees the created file gone: abcd creates README.md, the owner answers --readme-parts none (the file is left blank, the record stands), deletes the file and writes a placeholder holding only blank lines before any install or uninstall runs; uninstall then deletes the placeholder as the file abcd created. An install or uninstall that finds README.md gone now clears the record (lane-3 fix round 1, run-2610110908176735), which closes every sequence with an abcd run in between, but a boolean cannot tell the file abcd wrote from one written in its place. The loss is whitespace only.
- iss-2610112036089151The FindingGuardFailed doc comment in internal/core/changelog/findings.go says the guard fails when 'a consequential finding this cycle produced is still open and unwaived', but GuardFindings also fails on an open issue record that differs from HEAD (at any severity) and on deleted records, so the comment states one case of three. A sibling of iss-2610101803326081, whose lane fixed the launch brief's table row and RefusalUnfixedFinding's comment in release/emit.go and left this second package for capture.
- iss-2610112042253783abcd's lab snapshot (internal/core/lab/mint.go) and launch parity check (internal/core/launch/parity.go) run `git checkout` through gitutil's isolated environment, which drops the person's global git config, so in a repository whose Git LFS filter is set up by a normal global `git lfs install` their snapshot trees hold LFS pointer text instead of the real files. Same cause as iss-2610111729375108 (fixed for lane worktrees by gitutil.WorkingTreeCommand); noticed by that fix's sweep on 2026-10-11, not reproduced for these two callers.
- iss-2610112148115897The prepare-commit-msg hook ahoy install scaffolds into adopted repositories (internal/core/ahoy/defaults/prepare-commit-msg, header lines 20-22) still tells every clone to run 'git config core.hooksPath .githooks' unconditionally, shadowing a foreign global hooks dispatcher. The fourth sibling of the advice iss-2610101903385281 made conditional, found by the lane for iss-2610111820465940 (the scaffolded pre-commit). A sweep of every core.hooksPath mention on main at 2026-10-11 found no other unconditional instruction.
- iss-2610112155207746ahoy install writes its scaffolded guard hooks into an adopted repository only when they are missing (internal/core/ahoy/banlist_scaffold.go, the banlist.hook_missing branch through createContained), and never rewrites an installed v1 hook. So a repository that ran ahoy before a fix to a scaffolded hook keeps the old text: after iss-2610111820465940 and iss-2610112148115897 make the core.hooksPath advice conditional, every earlier adopter's committed .githooks/pre-commit and prepare-commit-msg keep the unconditional header, and ahoy reports no gap for it. Found by the ruthless review of the lane for iss-2610111820465940.
- iss-2610112201576037TestStopLeavesNothingListening is flaky on Linux and twice dropped a merge-queue entry (the run that landed #935). The dashboard's Linux readProcess reads /proc/<pid>/stat and /proc/<pid>/exe and treats only ENOENT, a zombie or a dead state as a gone process. A read that races the server's exit fails with ESRCH ("no such process") while the /proc entry still exists, so sameProcess returns that error and Stop fails, where it should have seen the process gone.
- iss-2610112202081803TestAPullRequestWhoseReceiptsNameNoModelIsNotOpened is flaky and twice dropped a merge-queue entry (the run that landed #935): t.TempDir cleanup fails with "origin.git: directory not empty". newLandFixture in internal/core/implement/loop/land_test.go creates its bare origin with a plain git init --bare, so the origin lacks the gc.auto=0, gc.autodetach=false, maintenance.auto=false and core.fsmonitor=false config that gittest.NewRepo writes for exactly this race (iss-252). A detached auto-gc child spawned by a push into the origin outlives the test and writes objects while cleanup removes the directory. About 17 other git init --bare calls in 15 test files share the gap.
- iss-2610112206165535The doc comment on fsutil.IsRealDir (internal/fsutil/fsutil.go, ~621) says os.Root refuses symlink traversal at every level, the same false claim iss-2610050259237102 corrected in internal/core/ideate/record.go: os.Root refuses only a path that escapes the root and follows a symlink that stays inside it.
- iss-2610112206188882The command surface's sentence for `abcd history staged` still says it refuses outside a git checkout, which stopped being true when --root-sha was added by the fix for iss-2609091717146700.
- iss-2610112214150230The abcd spc-N page (describeSpec in internal/core/record/record.go) and a bundle's shared-spec page (describeBundleSpec) judge the spec's intent, or each live bundle member, with plain intent.Ready, so for an intent whose ## Open Questions still lists an unanswered item they say 'implement against this spec's body; when done, abcd spec close ...' while abcd itd-N, abcd intent ready and abcd build all say it is not ready. Confirmed for describeSpec by a scratch-repository run in the lane for iss-2610111759346608; describeBundleSpec by reading the code.
- iss-2610112214257996Two spellings of a kill by name that iss-2609262259360005 named stay unread after ruling AS (product thinker, 2026-10-11) settled its third, the kill by the holder of a port or file: (1) a pid list carried through a file across commands (pgrep make > p; xargs kill < p), a data flow between commands the per-line reading does not follow; and (2) a pid list taken from a ps | grep | awk chain, where reading ps or grep as a search source would also block ps -o pid= -p N | xargs kill, the everyday kill of a recorded pid. The ruling as relayed to lane G2a named only the holder class, so whether these two block is still owed. A pid list carried through a variable is iss-2609281134544802.
- iss-2610112232319827The guard has no entry for `npx kill-port <port>` (and its kin such as `kill-port` installed globally), a common way to stop whatever holds a port, which the product thinker ruled on 2026-10-11 should be blocked like stopping by name; `npx` is also not a wrapper the guard looks through. Found by guard lane G2a on 2026-10-11.
- iss-2610112237411831The README contents part masks a heading's code spans twice, which is not idempotent. In readme_derive.go, headingText unmasks its result, then anchor (and escapeLinkText) re-run mdrecord.MaskCodeSpans on that output. When the first pass strips an inline tag or a link tail sitting directly between two code spans, the second pass pairs the spans across the join.
- iss-2610112237488013Three planning records still treat the worktree-store intent itd-2609091014076309's planning interview as owed, though it was held on 2026-09-30 (its record lists the rulings, and its Open Questions read 'None open'): spc-42's '## Blocked on' lists that interview as the blocker; iss-213's deferral_reason says 'Owed: the store draft's planning interview'; itd-148's Acceptance Criteria note and Open Questions defer to after it; and spc-42's Scope item 2 calls the check verb's name one of the store intent's open questions, though that intent's Decision 5 settled it as a sub-verb of ahoy. Found by the lane for iss-2610111926302792.
- iss-2610112255507078On macOS the dashboard reads a /bin/ps that its own 5-second timeout killed as a gone process: any exec.ExitError, including 'signal: killed' from the context deadline, maps to errProcessGone. On a stalled machine Stop then takes the live server for stale, removes its run file and signals nothing, leaving the server running with no record of it.
- iss-2610120129098206A README part's example can fail the question limits that R8 holds every tab to, because the lines are the project's own text quoted exactly. A heading such as '## Install — fast' lists as '- [Install — fast](#install--fast)', which question.CheckLimits refuses as an em dash in a list item, and a heading naming '__init__' is refused as bold markup. The cut fits only the rows rule, and the limits test's fixtures hold neither. Confirmed at the lane head after round 1's fixes with a README holding both headings: the contents tab raises em-dash-in-list-item and no-bold. Quoting the line differently would no longer be the exact line the part writes.
- iss-2610120137339391Two lane-discard paths in the implement loop delete a lane's branch with `git update-ref -d` without first checking whether another worktree has that branch checked out: `abcd implement step --discard <lane>` (internal/core/implement/loop/hold.go, the update-ref after removeLaneWorktree) and a handed-back receipt's discard (internal/core/implement/loop/receipt.go, discardReceiptLane's update-ref). git refuses `git branch -d` for a checked-out branch but not `update-ref -d`, so if the person (or a peer session) has checked the lane's branch out in a worktree other than the lane's own, that worktree is left on an unborn branch with its HEAD dangling. The same gap in landMerged was found by the security review of itd-82 step 3 (run-2610101724174688 lane-3) and closed there by a branchCheckedOutElsewhere check in land.go; these two siblings were outside that step's scope.
- iss-2610120138028442The implement loop's merged check (internal/core/implement/loop/land.go, landMerged) asks the forge twice per poll while a pull request is not merged: `gh pr view --json state`, then prMergeability's `gh pr view --json mergeable,mergeStateStatus`. Both fields come from one view, so each poll spends two forge calls where one would answer, against the same rate limit the loop's other waits share.
- iss-2610120138148399The implement loop's conflict probe (internal/core/implement/loop/conflict.go, conflictRefusal) predicts the forge's merge from the head the loop pushed, ld.Pushed, not the branch's current tip. The refusal's remedy is a person's hand merge, pushed to the lane's branch; that push does not change ld.Pushed. So if the pull request is still reported CONFLICTING afterwards (a second conflict, or the forge not yet recomputed), the probe re-merges the old head and can name a path the person has already resolved, sending them to fix what is fixed.
- iss-2610120138153613The implement loop's unarmed conflict remedy (internal/core/implement/loop/conflict.go, conflictRefusal's default case) says the next step 'arms it once the forge reports it mergeable', but the arm proceeds on any verdict other than CONFLICTING, UNKNOWN included (land.go's arm path). The wording promises a wait the code does not make.
- iss-2610120157489609abcd implement load --wait -- <command> exits 1 when the gated command is killed by a signal: runGated in internal/surface/cli/implement_load.go maps any non-positive exit code to 1. The help and commands/implement.md promise the waiter exits with the command's code, so a SIGTERM to the waiter leaves make preflight dead by SIGTERM and the waiter exits 1, which reads exactly like a preflight that failed a gate.
- iss-2610120505551170When setup ends with no .abcd/config.json (the starter files declined, at a terminal or off one), it reports the README question under optional_skipped, and both routes its hint names fail: the summary's action says to run abcd ahoy install at a terminal without --yes and answer it, which is the run just made and does not ask it, or to pass --readme-parts, which storeReadmeParts refuses because .abcd/config.json does not exist yet; the text render's extra line says the same. The true route, creating the starter files first, is named only by the separate declined-starter-files entry.
- iss-2610120527586962A restart and a rate-limit checkpoint read, copy aside and then remove the file an await's receipt path names, and that path comes from the run's state file, which an archive of the checkout can carry hand-written, without being held to the lane's directory. A state naming `.env`, `go.mod` or `.git/config` (or a `..` path that cleans to one) had `abcd implement step --restart <lane>` move that file of the checkout into the lane's aside; one naming `changes.patch` or a file of the lane's asides could overwrite a saved patch before the worktree was reset, losing the uncommitted work. The worktree path already had this check (derivedLaneWorktree, iss-2610090821552801); the receipt path was the sibling that sweep missed. The route is abcd's: the removal is the loop's own.
- iss-2610120601203457The abcd guard hook refused a Bash call holding a Python heredoc with 'unterminated single quote', although bash runs the heredoc body as data: a quote inside a here-document body is document text, which the guard's own help says is not an unterminated quote. Hit by lane B2 on 2026-10-12; the exact line was not kept.
- iss-2610120601214392The bootstrap's environment-read allowlist test treats a variable reassigned from itself (x=${x#* }) as an environment read, so new shell code in hooks/bootstrap.sh has to use fresh variable names to pass it. Found by lane B2 on 2026-10-12.
- iss-2610120601505029The install one-liner the site serves (/install.sh, built from site-src/install.sh.tmpl) installs a release without recording the newest-release mark that the bootstrap and abcd update now keep (the fix for iss-2609151847117977 on branch fix/sec-pub-b2-261011), so a machine installed only that way has no mark until the bootstrap or update next runs, and a stale cached release is not refused in that window. Found by lane B2 on 2026-10-12.
- iss-2610120617515834abcd ahoy install promotes an owned copy of the abcd binary (internal/core/ahoy/owned_copy.go) after checking it only against checksums.txt from the same release page, the weakness iss-2609231050273096 fixed for abcd update: whoever can change the release page can swap the binary and its checksum together. Found by the E5 fix lane on 2026-10-12.
- iss-2610120617521209The plugin's first-run bootstrap (hooks/bootstrap.sh) and the install one-liner the site serves (site-src/install.sh.tmpl) download an abcd binary and check it only against checksums.txt from the same release page, the weakness iss-2609231050273096 fixed for abcd update in Go. A shell script cannot run the in-process provenance check, so the fix needs a design choice (for example: verify with gh attestation verify when gh is present and refuse or warn without it; or verify with a previously installed, already-verified abcd). Found by the E5 fix lane on 2026-10-12.
- iss-2610120640452939Under the security scope rule (abcd never changes how a repository works on its own), abcd's lane creation (git worktree add, which runs a post-checkout hook) and a restart's reset and clean still run with core.hooksPath=/dev/null, gc.auto=0 and maintenance.auto=false through pickGit/WorkingTreeCommand, while the pick commit and sync merge were handed back to the repository's own settings by iss-2610111729399920. Found by lane C on 2026-10-12.
- iss-2610120640454742The implement loop's worktree store check (ensureStore in internal/core/implement/loop/lane.go) refuses every group-writable level, which is stricter than the product thinker's 2026-10-11 ruling for abcd's own home (admit a group-writable directory when the owner is the group's sole member, fixed for the home by iss-2609290703091174). Found by lane C on 2026-10-12.
- iss-2610120656366937The rules loader fences every rule of any domain a user or repo override names (internal/core/rules/rules.go ~965, fix for iss-2609020219265817), including a domain whose override only changes recall or state, so bundled rule bodies lose their markdown in that case. Over-fencing only; no attack path.
- iss-2610120656379101The bootstrap ignores a newest-release mark that fails its ownership or mode check (find ... ! -perm -0020) silently, so a machine whose mark is unreadable looks the same as one with no mark (fix for iss-2609151847117977). The attestation behaves the same way.
- iss-2610120704269048The install script the site serves (site-src/install.sh.tmpl) ends with report(), which runs "$bin_dir/abcd" version, a command abcd does not have (it exits 2; the version is printed by --version), so an install that succeeded ends in an error. Found by the installer lane on 2026-10-12.
- iss-2610120724251698Cloud agent sessions started on 2026-10-12 to work drain-eligible issues all failed abcd's preflight and had git identity problems, so none pushed a branch (the person reported this; the exact errors are with the launching session abcd-0b). abcd's gates assume the local development machine: every commit must name a human author (the attribution gate refuses a machine identity or none), and preflight resolves the go.mod-pinned toolchain and other local prerequisites. A cloud session gets neither by default, so abcd cannot yet be worked from a cloud session.related itd-2610120738075547
- iss-2610120729071657abcd has no way to launch or manage cloud agent sessions. On 2026-10-12 a session asked to move three drain-eligible issues to cloud sessions: its sub-agents could not reach the cloud and quietly started on the local machine instead, and the real cloud sessions had to be started by the person at claude.ai/code. Nothing in abcd starts a cloud session with the right brief, lists the running ones, or collects their results, so cloud work is launched and tracked by hand.related itd-2610120738075547
- iss-2610120729076366A request to run lanes as cloud sessions fell back to local sub-agents without saying so: on 2026-10-12 three lanes meant for the cloud started on this machine, inside the requesting checkout (under its .claude/worktrees/), and other sessions only learned of it when the requesting session noticed and corrected its own announcement. A run that cannot reach the place it was asked to run in must say so before it starts (principle loud-staging).related itd-2610120738075547
- iss-2610120729083126A cloud session's stop report (what it did, what failed, what it needs) is visible only in its transcript at claude.ai/code: on 2026-10-12 the cloud sessions could not message the local sessions and pushed nothing, so the person had to copy one session's report into a local session by hand, and the other two sessions' reports are still unread.related itd-2610120738075547
- iss-2610120729087253A cloud session whose preflight cannot pass has no way to hand its commits back: the pre-push hook refuses a push without a preflight receipt, and skipping that hook is forbidden, so on 2026-10-12 a finished fix (two commits and a resolved record) stayed trapped in the cloud container and had to be redone locally.related itd-2610120738075547
- iss-2610120729094755Nothing prepares a cloud container to work on abcd the way the development machine is prepared: on 2026-10-12 the container ran everything as root, had no gitleaks, and needed the brief to set the git identity, so preflight failed (iss-2610120724251698). abcd documents its local prerequisites but has no setup step or check for a cloud environment.related itd-2610120738075547
- iss-2610120751478299abcd peers, on main, lists the uncommitted records it finds in every sibling worktree of the checkout, titles included. A private record held in a hand-run private worktree, or in the embargo store, is therefore shown to every local session that runs abcd peers, and a title alone can disclose a security report still under embargo. Under the security scope rule abcd adds that route itself, so the leak is abcd's to close. Found 2026-10-12 by the embargo steps 10-11 lane.
- iss-2610120820482513The lifeboat mapping Table's personas row (internal/core/lifeboat/mapping.go, rendered into .abcd/development/brief/00-meta.md) says its Reads are 'personas registry, press-release quote attributions', but the only personas adapter, nativePersonasSource, reads the brief's own personas page (brief/01-product/05-personas.md) through nativeWithBriefFile and nothing else. A reader of the generated table concludes the probe looks for a registry or attributions it never opens. Raised by the ruthless and security reviews of the lane for iss-2610102343100369, which left it outside that remedy.
- iss-2610120916220240On branch fix/sec-g2-261011, fileCarries (internal/core/guard/carried.go) treats every unfixed word of a later command as a read of every file the line wrote, so after a search's output is merely logged to a file, the guard's own sanctioned successor piped through xargs (a recorded pid echoed into xargs kill) blocks as kill-by-search. Rare false block; the ruling says a variable the line did not set reads as before.
- iss-2610120916248850A script downloaded to a file and run on the same line (curl to a file, then bash, sh < or source of that file) is not caught: the same-line file carry built for pid lists on branch fix/sec-g2-261011 is not consulted by interpreter-reads-stream. Pre-existing (the base allows it too); found by the Fable review of guard rounds G2.
- iss-2610120921425348Running a source checkout's abcd through go run and typing a flag the verb does not have (go run ./cmd/abcd build next --dry-run) says 'this binary predates --dry-run the plugin surface it was provisioned from documents; this PATH copy is stale; run abcd update'. The binary is a fresh go-run build of the checkout, not a PATH copy, and abcd update would change nothing: staleUsageNote (internal/surface/cli/staleusage.go) takes its default branch for any executable outside the plugin root.
- iss-2610120921497084The stale-usage note matches a flag anywhere on the verb's command page, not under the sub-verb typed: build next --dry-run was called documented because commands/build.md mentions '/abcd:drain --dry-run' in prose, so the note blamed the binary's age for a flag build next never had.
- iss-2610120925509505abcd build next --max 1 on a live series is silently taken as a series move instead of the documented refusal. NextOptions.many() is UntilEmpty || Max > 1, so the count check at nextseries.go (if n.many() && (n.UntilEmpty != st.UntilEmpty || n.Max != st.Max)) never runs for --max 1; a --max 3 series in progress plus 'abcd build next --max 1' continues the series with exit 0, while commands/build.md says a count other than the one the series began with is refused at the pick stage, exit 2. Found by the ruthless reviewer, round 2 of run-2610110908001704 lane-1.
- iss-2610120925598775readSeries (internal/core/implement/loop/nextseries.go) checks a series file's intent, run_id and outcome but not its stored pace flags (flags.pace, flags.sub_agents, flags.fix_rounds), so a hand-written or repository-shipped .abcd/.work.local/run/next.json can carry control or bidi runes (for example U+202E, U+009B) in them; on a series move that picks nothing (window or cap), those strings reach 'abcd build next --json' unvalidated and encoding/json leaves them raw. Low severity: display spoofing of the JSON text on a terminal, no read, write or exec. Found by the security reviewer, round 2 of run-2610110908001704 lane-1.
- iss-2610120926008447commands/build.md lists only one of the four refusals the pick commit's worktree stage raises (internal/core/implement/loop/pickcommit.go): it names the missing git identity, but not the intent being no longer planned in the lane's worktree, a lane branch whose first commit is not the pick's, or a worktree dirty with other changes. A person whose 'abcd build next' run stops at the worktree stage on one of those three finds no description of it on the page. Noted by the intent auditor, run-2610110908001704 lane-1.
- iss-2610120929469571The release scan accepts an exclude_path_fragments entry that matches no payload file without a word, so a typo'd exclusion (generatd/ for generated/) reads as working while the files it was meant to leave out are scanned, and a fragment left behind after a rename silently stands ready to exclude whatever later takes that name. Found by the follow-up to lane X's whole-segment exclusion fix (iss-2610111600051340) on 2026-10-12; whole-segment matching makes a near-miss fragment match nothing where a substring match often still hit, so the silent case is now the common one.
- iss-2610120949163534Folders in abcd's home that an earlier abcd, a hand-run `mkdir`, or `git worktree add` created at the process umask are readable by every other account on the computer whenever the home itself is too: a home made 0755 keeps that mode, because every abcd writer leaves an existing folder's mode as it stands ([dcn-2610040000000007](../../decisions/dcn-2610040000000007-decided-without-a-question-by-abcd-50.md)). On a Mac where `~` is 0750 group staff and every local account is in staff, the other accounts can list and read `~/.abcd.noindex/{worktrees,runs,history,lifeboats,review-copies,scratch,sources,lab}` (each 0755), which hold private checkouts and session material. A lane worktree git adds into the store is 0755 whatever the store's mode.
- iss-2610120953445472The guard does not read a sourced file found through a PATH the line extends rather than replaces: after PATH=dir:$PATH, export PATH="dir:$PATH" or PATH+=:dir, a source of a bare name that dir holds is allowed unread, because the search gives up on a PATH value holding a variable instead of searching its fixed entries, and the += form is not read as an assignment at all. Found while fixing the zsh path array (iss-2610111730513071) in security lane G3, 2026-10-12; probe: PATH={d}/x:$PATH; source foo.sh = allow with x/foo.sh holding a blocker, while PATH={d}/x; source foo.sh blocks.
- iss-2610120953449511A source or . of a file the same line writes is allowed unread when the file does not exist at check time: printf '<blocker>' > n.sh; source n.sh allows, because the source search finds no file and the written-then-run check is only made for a file it found, while bash n.sh on the same line blocks as script-written-then-run. Found in security lane G3, 2026-10-12, while fixing iss-2610120916248850 (the downloaded-file form of the same gap is now refused as a stream).
- iss-2610120955431790abcd ahoy install adopts an existing owned PATH copy on a cold cache without verifying its build provenance: when the plugin cache is missing or unbound and the PATH entry is already an owned copy, install returns and keeps it as it stands (internal/core/ahoy/apply.go, the binTargetOwnedCopy return in the cold-cache branch). It writes nothing, so it is not an unverified write, but it is a gap in the claim that every promotion is verified: the copy it adopts was never checked by this run against the provenance release.yml signed, nor against the release commit.
- iss-2610121016162262Nothing calls embargo.Check but the abcd embargo check command: the commit-msg hook, abcd lint outbound, abcd launch ship and the implement loop's pull-request bodies all publish text without running it, so an unpublished advisory's id, reserved CVE id or title reaches public history unless the person remembers to run the check by hand. Separately, advisory ids travel in gh's argv (the REST path names the advisory id), and the triage --reason, --exists-without and --cannot-help text travels in abcd's own argv, where any local account can read them from the process list while the call runs; the update bodies already go to gh on stdin.
- iss-2610121056562293When git will not name the repository root inside a checkout, a question that carries abcd's label is still checked against the field limits, but if it passes, the guard's question check cannot set the status-line badge or mark the question open, and it says nothing about that: the person and the transcript cannot tell the bookkeeping was skipped. The unlabelled case now says so (iss-2610110432159652); the labelled case is still silent.
- iss-2610121204263271The run-start quota query passes its deadline to the runner's QuotaReporter and then waits on the reporter: runner.quotaOf (internal/core/runner/runner.go) calls qr.Quota(ctx) and returns whatever it returns, so a reporter that ignores its context holds the start of abcd build and abcd drain for as long as it chooses, the deadline notwithstanding. No shipped runner implements QuotaReporter today, so nothing reaches it yet; the next runner that reports quota over I/O inherits it. The route is abcd's: the wait is the loop's own.
- iss-2610121206163414readSeries (internal/core/implement/loop/nextseries.go) still accepts the stored pace provenance strings in .abcd/.work.local/run/next.json unchecked: each pace setting's layer and origin (pace.*.layer, pace.*.origin) is free text that reaches 'abcd build next --json' raw, so a hand-written or repository-shipped series file can carry control or bidi runes there, the same display-spoofing class iss-2610120925598775 closed for the stored flags. The same Pace shape is read from a run's state.json and echoed by 'implement record --json'. Found by the implementer fixing iss-2610120925598775.
- iss-2610121206277151The stale-usage note's classifier (internal/surface/cli/staleusage.go) reads a positional argument under a verb that has sub-verbs as an unknown sub-verb: 'abcd build itd-1 --frob-top' takes itd-1 for a sub-verb of build, so a flag the build page genuinely documents for 'abcd build <itd-N>' gets no stale-binary note. It fails safe (the plain unknown-flag refusal, never wrong advice), but a stale binary is then not told why. Found by the fix for iss-2610120921425348 and iss-2610120921497084 (branch fix/stale-usage-notes), which left it outside those remedies. <!-- record-lint: forward-looking -->
- iss-2610121209284195The check that refuses to delete a lane branch another checkout stands on (branchCheckedOutElsewhere, internal/core/implement/loop/land.go, used by the landing and both discards) compares branch names byte for byte. On a filesystem that folds case, macOS by default, git resolves a loose ref whatever case it is named in, so a run state naming build/Lane-1 reads and deletes the branch build/lane-1 with update-ref -d, while a worktree on build/lane-1 is not seen as standing on build/Lane-1 and its HEAD is left naming nothing. The same route exists without abcd: plain git branch -D build/Lane-1 deletes build/lane-1 from under a worktree, so under abcd-fixes-what-it-adds this is help only, offered because it changes nothing about how a repository works.
- iss-2610121209489908The shell guard's bundled registry (internal/core/guard/defaults/guard.json) refuses none of the ordinary commands that move a remote-tracking ref by hand: git fetch . +refs/heads/<x>:refs/remotes/origin/<y>, git remote set-head, git remote set-url, an edit of remote.origin.fetch, or git update-ref and git symbolic-ref under refs/remotes/. The dogfood build's security review showed four of these moving refs/remotes/origin/main to an agent's commit with the guard answering exit 0; the dogfood fix makes the build source a remote the person declares, so that route closes without them, but any other reader that trusts refs/remotes/origin as the reviewed tip is still exposed to them.
- iss-2610121210280182abcd build next --max 0 is read as no count at all: NextOptions.Max is 0 when the flag is not given, so an explicit --max 0 continues a live series (exit 0, a series move) and gives a single pick otherwise, while the refusal of a negative --max says a run count is '1 or more'. A person who types --max 0 is neither refused nor told it meant nothing. Found by the ruthless reviewer of fix/build-next-followups.
- iss-2610121214249290A command prefixed by an append assignment is not judged: FOO+=x rm -rf / is allowed while FOO=x rm -rf / blocks, because isAssignment accepts only NAME=VALUE, so the walk to command position takes FOO+=x for the command and the hazard for its operands; bash and zsh read NAME+=VALUE as an assignment prefix. Found in security lane G3 follow-up, 2026-10-12, while reading PATH+= for iss-2610120953445472, whose fix reads += only in the script reader's shell state.
- iss-2610121215586434The release cut compares terminal-folder record PATHS between the anchor tag and HEAD (internal/core/changelog/shipped.go:286-303), so the 40-character slug rename (255463f0d, PR #904) makes 1724 records read as removed and re-added: the v0.13.4..origin/main dry-run reports 1770 added and 1724 removed against 73 records that actually entered resolved/ or shipped/. The changelog check then requires about 1797 ids to be cited, and the doc-fidelity population lists about 78 intents instead of 4.
- iss-2610121224332411When ahoy install refuses a prompted answer to the visibility, docs_target or oracle_backend question (a piped 'y' where a choice is expected, say), it says nothing about the refused answer: the person sees only the gap that remains. The fix for iss-2610020700263496 adds a note naming the refused answer for scan_deep alone, as that remedy asks, and a retired docs target already has its own note; the other value questions stay silent. Found by the lane for iss-2610020700263496 (abcd-0d, 2026-10-12).blocked by iss-2610020700263496
- iss-2610121240517742In a checkout listed in ~/.abcd.noindex/dogfood-roots, every hook shim but the PreToolUse one hands its event to the dogfood build with no fall-back to the installed release if that build dies. hooks/user-prompt-submit.sh, subagent-stop.sh, pre-compact.sh, post-tool-use.sh and session-end.sh replace the installed binary with the build that hook dogfood-binary names and exec it, and session-start.sh runs it in the release's place; a build that crashes, is killed or exits with an error leaves the rules loader, the router reset, the transcript capture or the session-start checks undone for that event, with nothing run in its stead. The brief's dogfood store section says a hook never runs weaker than the release, and only hooks/pre-tool-use.sh implements that, by handing the command to the installed release when the dogfood guard answers exit 1 or dies. Found in the round-2 security review of the dogfood remote fix (iss-2610070547057816).
- iss-2610121431244546Once the fix for iss-2610120921497084 scopes the stale-usage flag match to fenced synopsis lines (internal/surface/cli/staleusage.go, synopsisCarriesFlag), a flag a command page documents only in its argument-hint front matter or in inline-backtick prose no longer counts as documented. About 60 flags across commands/*.md appear only there (capture resolve's [--commit <sha>], build's --release and --discard, ahoy install --yes), so a release PATH copy that predates one of them now prints the plain unknown-flag error and withholds the true stale-copy note. Fails safe (silence, never a false claim). Found by the ruthless review of fix/stale-usage-notes, 2026-10-12. <!-- record-lint: forward-looking -->
- iss-2610121442314872In the README question pair asked through the host's question tool, every part's tab lists on, off, Decide later in one fixed order, so the cursor rests on on and a quick Enter turns on the two parts that are off unless chosen: the managed-with-abcd badge and the table of contents. The product thinker ruled on 2026-10-12 that those two tabs list off first, so Enter takes each part's usual answer; the order may differ between tabs. The drawn and stdin terminal doors already start on the default.
- iss-2610121442326914R8's dated receipt for the README question pair (.abcd/.work.local/logs/readme-questions-2026-10-12.md) holds tmux capture-pane text copies of the 80-column harness view, not the screenshot the criterion names. The product thinker ruled on 2026-10-12 that the receipt adds pictures as well: images of Q1 and of each tab call, taken in a fresh live session.
- iss-2610121448005835The dogfood build's residual statement (AGENTS.md, internal/core/dogfood/dogfood.go's package doc, the brief's dogfood store section) names the account's environment by example: the go toolchain, the module cache, GOENV, PATH and ~/.ssh/config. Git's own inherited environment is the same residual and is not named: GIT_EXEC_PATH, GIT_SSL_CAINFO and SSL_CERT_FILE, https_proxy, and ~/.ssh/known_hosts. A reader can take the list as complete.
- iss-2610121448010531The dogfood remote check accepts an ssh or https remote on this machine: localhost, 127.0.0.0/8, ::1 and [::1]. An agent running as the account can move such a remote, and the docs state it as the person's residual because abcd cannot tell an ssh alias from a forge. Refusing the literal loopback names would cost nothing for a real forge and would match the refusal of filesystem paths, as defence in depth that an alias still escapes.
- iss-2610121448011094The dogfood remote check (remoteRefusal, internal/core/dogfood/dogfood.go) refuses an scp-like IPv6 remote such as [::1]:path or [2001:db8::1]:path with the remote-helper reason, because the text contains '::'. The refusal is right but the reason is wrong: git does not read a '['-led remote as a helper.
- iss-2610121505153157readDrain (internal/core/implement/loop/drain.go) accepts the free text a drain state stores in .abcd/.work.local/run/drain.json unchecked: each hand-back's reason, home, question, rule, draft and wrote fields and the judgements are copied into 'abcd drain --json' as stored (res.HandBacks = st.HandBacks), so a hand-written or repository-shipped drain.json can carry control or bidi runes (U+202E, U+009B) onto the JSON stream; the same display-spoofing class as iss-2610121206163414, which hardened the drain's stored pace. Found by the implementer of that fix.
- iss-2610121516552317abcd drain --json echoes each issue's disposition reason straight from the ledger reader: that text includes the reader's error messages with record paths unquoted and a record's raw deferred_after value, so a repository whose ledger file name or deferred_after carries a control or bidi rune (U+202E, U+009B) puts it raw on the --json stream, and the drain copies the same text into a judgement's note in drain.json, where readDrain (since iss-2610121505153157) then refuses the whole file. Found by the implementer of iss-2610121505153157.
- iss-2610121516559163ReadState (internal/core/implement/loop/state.go) does not check a lane's stored hand-back text in a run's state.json, and on the call that routes a hand-back the drain echoes that text onto abcd drain --json before drain.json is ever re-read, so a hand-written or repository-shipped state.json whose hand-back reason, home or question carries a control or bidi rune (U+202E, U+009B) puts it raw on the stream. The receipt path sanitizes these fields when the loop takes them, so only a forged file carries them. Found by the implementer of iss-2610121505153157.
- iss-2610121521482863fsutil.FoldPath, the canonical fold for names a case-folding filesystem resolves, lower-cases with Go's simple mapping and then applies NFC, but APFS folds with full Unicode case folding over normalised text. It treats straße and strasse, final and medial sigma, the micro sign and mu, and the fi ligature and fi as one name, where FoldPath keeps them apart, and FoldPath equates a dotted capital I with a plain i, where APFS keeps them apart. Every FoldPath caller (the payload destination check, the pack overlap check, embark's claimed key) can therefore read two spellings of one directory as distinct. The loop's branch check now folds fully through its own refFold; the shared helper does not.
- iss-2610121528179959abcd has no shared handover place for concurrent sessions. On 2026-10-12 seven sessions had to close at once (usage limit) and resume days later as fresh sessions; the only convention, .abcd/.work.local/NEXT.md, holds one session's note and was stale from 2026-10-07, each session's scratchpad (lane briefs, cloud prompts, peer notes, security plans) is deleted when the session closes, and the coordinator improvised a per-session folder and template (.abcd/.work.local/handover-2026-10-14/) by message. Nothing lists which branches, worktrees, PRs, records on unmerged branches, private local-only branches and memory files each session leaves behind, so work can be orphaned across a closure.related itd-2611041549461012
- iss-2610121532247004A lane receipt's model and each resolution's note and grounds are stored on the lane unchecked and echoed raw on 'abcd implement record --json' and 'abcd implement status --json': verifyReceipt (internal/core/implement/loop/receipt.go) checks a receipt's run, lane, branch, commits, resolution issue, commit and impact, but takes rc.Model and each resolution's note and grounds as written, and readStateIn reads them back from state.json unchecked. A receipt an agent writes, or a hand-edited or repository-shipped state.json, can carry control or bidi runes (U+202E, U+009B) onto both streams. Found sweeping the loop package's on-disk readers after iss-2610121516559163.
- iss-2610121533474806abcd report only reaches an inbox in the same user account (~/.abcd.noindex/inbox), so a managed repository worked from another account, another machine or a cloud session cannot report a defect or proposal to abcd at all; on 2026-10-12 an agent building a game engine with abcd had two issues to report and no route to deliver them. Reports need a delivery path that works across accounts, for example a GitHub issue on abcd's repository.
- iss-2610121535283764abcd should audit and apply GitHub security settings for every repository it manages
- iss-2610121541515477abcd's setup questions in a terminal are unclear to a product thinker and to a technical facilitator. Seen on 2026-10-12 with abcd ahoy remote apply on a managed repository: (1) a meaningless 'Setup Q1' heading; (2) the question names raw API keys ('secret_scanning: disabled -> enabled; secret_scanning_push_protection: disabled -> enabled') where plain words are needed; (3) the option meanings are circular ('Makes the change the question names') or wrong for the verb ('so the next install asks again' on a remote apply), and 'No, leave it' and 'Decide later' read the same; (4) 'Now: not applicable' and 'Change later: not applicable' lines are printed as noise; (5) the cursor highlight is not recognisable as the selection, so the person could not tell which option they had picked, and the result line 'abcd ahoy remote apply — clean' after a change does not say plainly that it succeeded.
- iss-2610121542240257A run's state.json stores text that legitimately carries repository or tool content, unchecked at read time and echoed on abcd implement status --json and implement record --json: spec step titles (stored raw from the spec), the pick text and excluded reasons, record notes quoting step titles and git errors, kept (git error text), sync paths (repository file names), the landing's forge URL, the runner's reported model and transcripts; ids, shas, stages, branch and worktree names, paths, verdict words and audit fields are unchecked too, though abcd writes clean values there. Refusing at read time would refuse runs abcd itself wrote (a spec in a right-to-left language, a coloured hook failure), so the fix needs a design choice: mask such text where it is stored, or refuse at read time and accept false refusals.
- iss-2610121542258412The issue record validator (internal/core/issuerecord) prints stored values unquoted in its error messages, schema_version among them, and those errors reach --json payloads and refusal reasons on several verbs, so a record carrying a control or bidi rune in a stored value puts it raw on those streams.
- iss-2610121542258778A capture disposition's title (an issue record's first body line) reaches abcd drain --json raw, and capture surfaces other than the drain still show the ledger reader's unreadable-record error raw (only the drain's copy is masked, since iss-2610121516552317), so a repository whose issue record body or a stored value carries a control or bidi rune puts it on those streams.
- iss-2610121542263820The run log's outage spans reach abcd implement record --json raw: their text comes from the run log the session appends to, so a hand-edited or repository-shipped log carrying a control or bidi rune puts it on the stream.
- iss-2610121542268630spec.ParseSteps passes a spec's step titles through raw, and the build loop stores and echoes them (brief, state.json, implement status --json, pull-request titles), so a spec whose step title carries a control or bidi rune puts it on those surfaces.
- iss-2610121542385455The claude runner (internal/core/runner/claude.go) copies the external tool's reported model into the route record, which reaches abcd implement record --json raw, so a tool reporting a model name with a control or bidi rune puts it on the stream.
- iss-2610121602237516termsafe's mask (internal/termsafe/termsafe.go, isZeroWidth and the bidi set) leaves several invisible rune classes unmasked: the Unicode tag characters U+E0000 to U+E007F, the interlinear annotation marks U+FFF9 to U+FFFB, U+180E (Mongolian vowel separator) and U+034F (combining grapheme joiner). They render invisibly, so text carrying them passes Sanitize (and every Sanitize-equality check built on it) unchanged and can hide content on a terminal or in a transcript; tag characters can also carry hidden instructions to an agent reading the output. Pre-existing across every Sanitize caller. Found by the security reviewer of fix/sec-build-next-series.
- iss-2610121622596154The checked-out check before a lane branch is deleted (sameBranchRef and refFold, internal/core/implement/loop/land.go) still misses one family of names APFS treats as one: Cherokee. golang.org/x/text's cases.Fold is not idempotent for Cherokee (it maps U+13A0 to U+AB70 and U+AB70 back to U+13A0, and U+13F0 with U+13F8), so a run state naming build/lane-<Cherokee small letter> passes the check while a worktree stands on build/lane-<Cherokee capital>, and update-ref -d deletes that branch from under it; reproduced end to end on APFS. The route exists without abcd (git branch -D with the other spelling does the same), so under abcd-fixes-what-it-adds this is help only, and lane branches abcd mints are ASCII. The person ruled on 2026-10-12 to ship the branch with this gap filed rather than take a fourth fix round.
- iss-2610121623088421fsutil.CaseFoldingFS decides whether names fold by the operating system (darwin or windows), not by the volume a path is on. A case-sensitive APFS volume on macOS only over-matches, the safe side; a case-insensitive mount on Linux (SMB, exFAT) under-matches, so every check that folds through it (the loop's checked-out check, the FoldPath callers) reads two spellings of one name there as distinct.
- iss-2610121629141674The dogfood store keeps the three newest builds per repository (keepBuilds, internal/core/dogfood/dogfood.go), and since 4c0555851 each declaration keeps its own verified tip. Four or more declarations of one repository at four distinct tips therefore never settle: each build's prune evicts another clone's build, whose next Resolve finds no ready binary and asks for a rebuild, which evicts the next. Two or three declarations are fine.
- iss-2610121653432051abcd implement report --json echoes the run log's text raw beyond the outage spans: each mode tally's mode, each session context's session and role, and the other event strings Compare reads from the log the sessions append to, which ParseLog checks only for presence. A hand-edited or repository-shipped run log, or one named with --log, whose line carries a control, bidi or zero-width rune puts it on the stream. Found while masking the outage spans for iss-2610121542263820, which closed only the span fields.
- iss-2610121653499543abcd capture list --json, and the other capture surfaces that emit an issue whole, echo a record's stored text raw: its body and its frontmatter strings (remedy, found_during, resolution, wontfix_reason and the rest). capture writes a body with its hidden runes percent-encoded, but the validator holds no stored string to a rune set, so a hand-edited or repository-shipped record carrying a control, bidi or zero-width rune puts it on the stream. Found while masking the skipped-record list for iss-2610121542258778; a test planting U+202E and U+034F in a record body sees them raw in capture list --json.
- iss-2610130501296659Merged branches and spent worktrees pile up because nothing removes them: by the close of 2026-10-12 the checkout held 137 local branches (83 already merged into main), 94 worktrees and 4 merged remote branches, and a person had to ask for the cleanup by hand. The person asked (2026-10-13) that a future drain and similar runs do this automatically. Done by hand that day with a read-only inventory (merged into origin/main, contained in a kept branch, PR state, worktree clean, local-tier file count) and a dry run before acting: 92 local branches, 40 worktrees and 4 remote branches removed, every worktree's local tier archived first. Draft itd-118 (merged work leaves no residue) and planned itd-2609091014076309 (the worktree store and its reclaim) describe the want; neither runs at the end of a drain or a cut.related itd-118 · related itd-2609091014076309
- iss-2610130501353955The cross-session handover index was owed by one session, and when that session closed (on hitting the weekly limit) without writing its own handover or the index, nothing produced it: a person had to ask another session to reconstruct it on 2026-10-13, including three cloud runs only that session knew the state of (#974, #976, #982). The person asked that a future drain and similar runs do this automatically.related itd-2611041549483696
- iss-2610130502493655Typing only '/abcd:' in the coding host lists /abcd:lab first, not the status page /abcd:abcd, so pressing Return runs the lab listing instead of the general status board. Seen in a managed repository on 2026-10-13, where /abcd:lab had just been run, which suggests the host orders the menu by recent use (the next hit shown was /abcd:ahoy). The person expected the bare prefix to land on the status board.
- iss-2610140638074587The load waiter's one-waiter-at-a-time hold, ~/.abcd.noindex/load-wait.json, lives in the caller's own home, so it is per account, not per machine as the help and the LOAD rule call it. A second macOS account on the same machine (a colleague joining this machine) runs its own waiter against its own home and never sees the first account's hold, so two accounts' gated preflights are admitted together whenever the load and race-run conditions are open at once, which is exactly the moment between a preflight's start and its race step. Sharing the hold file across accounts is not a fix: a file another account can write would let one account hold every other account's gate shut, which the security rule forbids.related itd-2610170634394993
- iss-2610140643082027ReleaseOlder (internal/core/ahoy/release_mark.go:50-62) compares cores only and then asks whether a alone carries a pre-release, so two pre-releases of one version never compare older: ReleaseOlder("v0.14.0-rc.1", "v0.14.0-rc.2") is false, confirmed at tip. A machine whose newest-release mark is v0.14.0-rc.2 therefore takes a genuine v0.14.0-rc.1 build at every place the mark is the floor: the cold-cache PATH copy check (apply.go checkOwnedCopy), the warm cache promotion (owned_copy.go:467) and abcd update's withdrawal check (internal/surface/cli/update.go:102). A pre-release rollback inside one version slips the floor the mark exists to keep. Pre-existing; low reach while abcd publishes no pre-release tags.
- iss-2610140652230444Every review should run as a pair of models from two classes, with the top class only an occasional advisor. The classes are vendor-neutral: top, middle, the class below it, and smallest (the scale itd-2610100704270254 uses). For one vendor today, Anthropic, they are Fable, Opus, Sonnet and Haiku. The rule is stated in classes so it survives model churn and holds for any vendor whose models map onto them.related itd-2610161733316518
- iss-2610140706347640A garbled release mark makes the rollback floor disappear without a word. ReadReleaseMark in internal/core/ahoy reads an unparsable mark as no mark, so ahoy install and update adopt any genuine release, however old, and nothing tells the person their newest-release floor is gone. The fail-open is deliberate and safe: the mark is read only when this account owns it and no one else can write it, so whoever can garble it could already delete or lower it, and a copy admitted this way still passes the provenance check for the release it names (the warm path and hooks/bootstrap.sh fail open the same way). What is missing is the diagnostic. Route without abcd: none; the mark and its floor are abcd's own, so abcd fixes it.
- iss-2610140720357027termsafe.Sanitize leaves the variation selectors, about fifty other invisible format characters and the Hangul fillers unmasked. The variation selectors U+FE00-U+FE0F and U+E0100-U+E01EF, the Cf characters U+206A-U+206F, U+1D173-U+1D17A, U+13430-U+1343F and U+110BD, the Mongolian free variation selectors U+180B-U+180D, the Hangul fillers U+115F, U+1160, U+3164 and U+FFA0, the Braille blank U+2800, the line and paragraph separators U+2028 and U+2029 and the object replacement character U+FFFC each render as nothing or as blank space, so two byte strings can display identically and a run of selectors can carry a hidden payload past a reader (the Opus and Sonnet security reviews of fix/sec-build-next-series, round 2). They were not added blind: VS16 (U+FE0F) is legitimate in emoji, a heart followed by VS16 being the common case, and masking it would put a ? into ordinary text a repository writes.
- iss-2610140739284100The tree holds four hand-written longest-run counters for backtick or tilde runs: termsafe's private longestBacktickRun (internal/termsafe/prose.go), internal/core/history/reconstruct_render.go, internal/core/capture/promote.go's codeSpan, and the override fence writer in internal/core/rules (landing with the cut-2 installer branch). The one-canonical-primitive principle forbids a third copy; each is correct today, and each is allowlisted in the code-span canonical test rather than routed through one helper.
- iss-2610140813542607internal/core/history/store.go:22 and internal/core/lifeboat/voyage.go:25 each declare their own rootSHARe (^(?:[0-9a-f]{40}|[0-9a-f]{64})$) to check a store key is a repository root commit, while gitutil.IsFullSHA (internal/gitutil/repo.go) already carries the same pattern for the same purpose and is what the docfidelity, lab, implement and ideate stores call. The two copies can drift from it (one-canonical-primitive). Found while fixing iss-2610090740139804, whose first draft added a third copy before review pointed at IsFullSHA.
- iss-2610140819442690In a shallow clone, gitutil.RootCommit (rev-list -n 1 --max-parents=0 HEAD) returns the graft commit, not the repository's root, and every machine-scoped store keyed on it files under that wrong key with no warning: the history ingest (internal/core/history/ingest.go:86), labs (internal/core/lab/lab.go:172), implement runs and loop state (internal/core/implement/load.go:357, internal/core/implement/loop/loop.go:454 and siblings), the report inbox key (internal/core/report/inbox.go:106), the lifeboat probe (internal/core/lifeboat/probe.go:211) and ahoy's managed-repository index (internal/core/ahoy/store.go:68, managed.go:54). A later full clone of the same repository reads a different folder, so the records look lost. CI checks out full history (fetch-depth: 0), so the gates are not affected. Found by review of the ideate private/public fix (iss-2610090740139804), which now refuses a shallow checkout at its own front door.
- iss-2610140913332484fsutil.EnsureHomeScope and OpenHomeScope judge each level of ~/.abcd.noindex for symlinks and swaps but not for owner or mode: a level that already exists keeps whatever mode it has, and one another account created (under a HOME planted outside every working tree) is written into. File contents stay 0600, so only names leak (an ideate verdict's date and slug, for example); the planting route is the harness's environment, not abcd. Found by the security review of iss-2610090740139804.
- iss-2610141647294219ideate's command page has no step for an input that is a source rather than an idea: given a web address holding several ideas, the runner must improvise the extraction (which ideas, how worded), and that choice shapes every later leg yet appears in no record (lab finding F-1).related itd-2610141646452213
- iss-2610141647304982ideate record validates citations only in the record-grill leg: a verdict citing a non-existent intent id in leg 3 and another in leg 1, with 'a remark heard in passing' as a verified primary source, was recorded with exit 0; in the real run a surviving kill attempt rested on a draft presented as shipped (lab finding F-7).related itd-2610141646454347
- iss-2610141647307807A grill whose search silently failed writes the same ideate record as an honest empty grill: a search loop that zsh did not word-split returned zero hits for every term (90 files mention one of them), and the verdict schema carries hits only, with nothing saying what was searched or where (lab finding F-4).related itd-2610141646454347
- iss-2610141647308358ideate's leg 3 asks for one fresh evaluator, which conflicts with the standing Opus+Sonnet review-pair rule under the machine-wide sub-agent cap; fitting the pair into the cap meant batching several ideas into one evaluator context, and one evaluator made a single tool call and never opened the repository it judged (lab finding F-6).related itd-2610141646454347
- iss-2610141647309012ideate's leg-2 reading list omits the private verdict store (~/.abcd.noindex/ideas/<root-sha>/), and ideate record resolves repository ids only, so a directly relevant prior private verdict can be neither found by the list nor cited (lab finding F-5).related itd-2610141646456128
- iss-2610141647313018ideate's claim status cannot say whether a claim was verified as quoted or as true: a write-up's own experience can only be checked as quotation, and the three statuses carry no such distinction; any non-empty string is accepted as a primary source (lab finding F-9).related itd-2610141646454347
- iss-2610141647314635A stale published abcd binary in a source checkout can answer a verb with a plausible wrong result instead of refusing: iss-2608230943088357 resolved only the refusal half (an unknown verb or flag now names the staleness), and the same binary reports 'staleness: up to date' when run outside a checkout, so the flag cannot warn a runner who resolves it from elsewhere (lab finding F-3).
- iss-2610141647315880Nothing defines how two ideate evaluators are merged or where a reframing is recorded: the schema has one adversarial leg, one verdict and no reframing field, although the page says a graduation carries the reframing; runs encode it as a final 'survived' kill attempt by unwritten convention (lab finding F-8).related itd-2610141646454347
- iss-2610141647315978abcd lab harvest refuses probe citations given by path although its own help says each finding cites its probe records by path: findings citing state/probes/<name>/record.md are refused as 'incomplete: the record', because the parser looks the text up as a bare probe name; an earlier lab of the same day cites by path throughout (lab finding F-13).
- iss-2610141705100828The brief surface index table header reads Memory (/abcd:memory) and is not marked staged, but no /abcd:memory command exists: there is no commands/memory.md and no memory verb, and 07-library.md:11-16 says the old memory command was folded into library with its name not kept; memory notes are an open intent (itd-2610091918433290).
- iss-2610141705107330The brief surface index row for the hook verb says five host hook entrypoints and names prompt-router, prompt-router-reset, session-end, subagent-stop and session-start, but abcd hook --help lists six: question-answered (PostToolUse on the question tool, wired through hooks/post-tool-use.sh) is neither counted nor named; it is documented only in 05-internals/03-configuration.md:1118-1119. Raised by three checkers (CLI verb tree Opus, hook entrypoints Opus and Sonnet).
- iss-2610141705112796The glossary entry for memory note says an agent writes one with /abcd:memory add, as if shipped; no memory verb or command exists, and memory notes are an open intent (itd-2610091918433290).
- iss-2610141705124287The brief surface index row for docs-currency-reviewer says it serves docs, but neither commands/docs.md nor abcd docs (cite, fidelity) names or takes that agent output; it runs as a release-gate pass under launch (commands/launch.md:898-901), as 10-docs.md:220 says.
- iss-2610141705129324The brief agents chapter says the repo-workflow reviewers and researchers (docs-currency-reviewer, ruthless-reviewer, security-reviewer, sota-researcher) are dispatched by a human rather than by a verb, but commands/build.md:368 has the implement loop validate step dispatch a ruthless-reviewer and a security-reviewer and record their verdicts, and commands/launch.md:900 runs docs-currency-reviewer as a release-gate pass whose receipts launch checks.
- iss-2610141705135681The brief glossary names a shipped /abcd:intent grill sub-verb, but abcd intent --help lists no grill sub-verb, and the brief elsewhere calls that promotion a design target only.
- iss-2610141705138730The glossary entry for transport uses an impl-review skill in its example sentence as if it exists; abcd ships no skills, and no skill, command, sub-verb or agent has that name.
- iss-2610141705147398The glossary entry for oracle uses an impl-review skill in its example sentence as if it exists; abcd ships no skills, and no skill, command, sub-verb or agent has that name.
- iss-2610141706042163abcd guard check --help (mirrored in the generated docs/reference/cli/commands.md) says an allow still does not see a parameter expansion with no substitution ($VAR, ${VAR:-git}) wherever it stands, because the guard sees the variable, not its expansion; since the carried-value reading the guard does read a value the same line assigns and uses: P=pkill; $P make and X=rm-payload; sh -c "$X" both block. The help under-states the guard (it fails safe).
- iss-2610141706053335The 0.14.1 changelog line on masking names the reasons, titles and records that drain, capture list and capture status show, but abcd has no capture status sub-verb: bare abcd capture renders the ledger status, and abcd capture status gets the lone-word refusal. The wording comes from the resolution text of iss-2610121653499543, which the changelog derives from.
- iss-2610141706058429commands/update.md network inventory (adr-38) says GitHub attestations API and the Sigstore TUF repository are reached by update, to verify build provenance, reading as exhaustive; ahoy install now makes the same check (internal/core/ahoy/apply.go), and both verbs also reach the GitHub git API to resolve the tag commit (internal/core/update/provenance.go), which the inventory omits.
- iss-2610141706063703docs/how-to/install.md (also the 0.14.1 changelog and README) says a gh that is not signed in installs on the checksum alone with a warning; in every path a gh with --source-digest first resolves the release commit through the unauthenticated GitHub API and refuses when that lookup fails, before sign-in is tested, so a rate limit or outage gives a refusal, not the checksum-only install (fails closed).
- iss-2610141706064461commands/ahoy.md says install writes no entry when the check fails or cannot reach the GitHub attestations API or the Sigstore TUF repository, omitting that a failed GitHub git API lookup of the tag commit refuses too (internal/core/update/provenance.go); docs/how-to/install.md already names both APIs.
- iss-2610141706070227The --wait flag one-line help of abcd implement load says it waits until the load is below the wait limit and no other go test -race run is live; the gate also stays shut while any account make preflight or an earlier waiter is live, as the command Long help and commands/implement.md say.
- iss-2610141938299842Before 1.0 a release cut leaves every earlier release on offer: nothing removes the previous Releases and their downloads, and the recorded rule keeps the newest release of each version line rather than only the newest release. The product thinker ruled on 2026-10-14 that nothing older than the newest release is offered before 1.0, and the eight earlier Releases (v0.11.1 to v0.14.0) were deleted by hand that day, tags kept. iss-282 records the missing executor for the older newest-per-line rule.
- iss-2610141945581538Show repo activity as a small-multiple heatmap, like Kieran Healy's Baby Boom chart: commits, decisions, captures and other record events per weekday per week (or a better shape), one panel per kind of activity, so the rhythm of work on a repository can be read at a glance.
- iss-2610141947553722abcd lint's privacy-hygiene rule reads a dotted RFC section number such as [redacted-address] in prose as a non-reserved IPv4 address and fails the file
- iss-2610142025108700Release review receipts accepted any free-text disposition and let any number of deferred findings name one shared catch-all record: 1,090 of the 2,178 findings in committed receipts name iss-2609091956001547, and dispositions came in about twelve free-text shapes, including 'accepted: knowingly shipped unfixed', which defers without saying so. Nothing checked that a deferred finding had a record of its own.
- iss-2610142025250222abcd launch receipts passes the configured issues_dir to git status as a pathspec without checking it stays inside the repository; the release gate checks containment itself, so an out-of-repository value surfaces only as a raw git error rather than a refusal naming the setting.
- iss-2610142025259820No verb files a discipline-kind intent: the intent surface says a discipline is filed and never reclassified into, but abcd intent mints a draft, so a discipline is filed by minting a draft and moving it into disciplines/ by hand, as itd-2610141956319695 was.
- iss-2610142032594765ideate record's stray-store note now looks for a stray research/ideas store below the checkout root, so a stray research/notes store that the long-fixed subdirectory defect (iss-2609091729516940) left below a root is no longer reported when ideate runs. Raised by the Opus reviewer of PR #991.
- iss-2610142032595919A .gitignore the person already keeps in abcd's home is kept whatever it holds, and the marker is written beside it, so a file that does not ignore ideas/ (say one holding only transcripts/) leaves private ideate verdicts stageable by a dotfiles repository in the home, which the private store admits because abcd's home is taken to ignore itself there. Raised by the Sonnet reviewer of PR #991.
- iss-2610142036270003On the github-pages hosting provider the site loses the security headers abcd's own site serves: the build copies site-src/headers to _headers, which Cloudflare reads and GitHub Pages ignores, so a project site on GitHub Pages is served without the Content-Security-Policy and the other headers that file declares.
- iss-2610142126593198The reserve page and its brief chapter say a person sees reservations through abcd peers, but peers is an agent's verb (block: agents, user-invocable: false); a person sees them on the board (bare abcd) and on a record's page (abcd <record-id>), as step 11 of spc-2610031753359849 built.
- iss-2610142134339172After a busy-lock refusal leaves the reviewer route's placed return standing, a later implement step can re-tell the open review and DriveReview sends it to rp a second time, a review that can take up to 30 minutes, only to keep the second answer aside because the first return still stands.
- iss-2610142134342766placeRouteReturn (placeReturn) writes the run state when it records the route's answer on the await, but does not bump the state's UpdatedAt, so the run reads as unchanged since its last stamped mutation although its state moved.
- iss-2610142134346602Three tests (pace_stored_test.go, receipt_text_test.go, state_text_test.go) use schemaVersionUnkept, version 9, as the earlier version they migrate from, so since state schema version 11 they no longer test the version just before the current one.
- iss-2610142134350426A process killed between keepAside writing the answer's temporary file and linking it to its name leaves a hidden .rp-return-<hex>.tmp in the review's directory, which nothing removes later.
- iss-2610142134353345The role gates on the reviewer route's digest compare, in receipt (loop.go) and in verifyValidation (validate.go), are redundant and unreachable: no validator but a ruthless or security reviewer reaches the compare, so removing both leaves every test green.
- iss-2610142134368025The remedy for a run state of a newer schema version suggests abcd update, which assumes the newer abcd that wrote the file was released; a file a development build wrote needs that build, and updating to the latest release still refuses it.
- iss-2610142151400382removePlaced reports removed=true when root.Remove returns ErrNotExist, a peer having removed the file between the digest check and the Remove, so takeBack's refused-drop message says the return was taken back though this call removed nothing.
- iss-2610142151424332When no answer is recorded on the await, a concurrent invocation having already dropped it, and the run's lock is busy, takeBack still asks for the drop under the lock and its refusal says the recorded answer stays in the run's state, though there is none to drop.
- iss-2610142151428802createAside's refusal when every numbered aside name is taken names the review's directory, while keepAside's refusal for the same exhaustion names the review's return path, so one condition reads two ways.
- iss-2610142152501415release.yml's verify job runs go run ./cmd/record-lint from the gated tree, so a release pull request that edits internal/core/lint or cmd/record-lint disarms the receipt gate as surely as editing release.yml, with only pull-request review in the way. The same holds for every gate the verify job runs from the tree it gates; it predates the deferral discipline.
- iss-2610142200372105A reservation holder whose clock runs behind by more than half its lease plus the five-minute take-over margin can be taken over between its own renewals, so two drains on two accounts can work one issue; the bound is documented on the reserve page and in spc-2610031753359849 but not closed, and it is the one remaining route to that failure.related itd-2609151838312703
- iss-2610142200389875The reservations ruleset forbids deleting refs/heads/abcd-reserved/** with no bypass, so every spent reservation branch stays on the forge forever, counting against its per-repository branch limits and against the intent's 'needs occasional clean-up' (decision 10 of itd-2609091034175565); the rulesets README notes the itd-118 sweep needs the ruleset amended first.
- iss-2610142210511831A managed repository has no gate on the text handed to the forge CLI for a pull-request body, an issue or a comment, so a live agent-session URL or a tool attribution footer reaches the forge unchecked, and the forge keeps the pre-edit revision of whatever was posted. The commit-message half of iss-2609250834251447 shipped as the opt-in ahoy install --outbound-hook gate; this is the forge-text half that record named and that gate does not cover. scanner.ScrubOutbound already defines the scrub for outward text, and abcd lint outbound the check, but nothing a managed repository runs puts either in front of the forge CLI's pull-request, issue or comment commands. Split out of iss-2609250834251447 when its commit-message half was resolved.
- iss-2610142220581750The prompt router's --json envelope lists recalled notes as bare ids with no layer, while the injected text and the stderr line both name each note's layer (project or machine). A machine reader of the envelope cannot tell a note from the repository's committed .abcd/memory.json from the person's own. It was left as is because adding the layer changes the envelope's schema.
- iss-2610142221073140A recalled machine-layer note's head reads "(personal note, agent-written)" whatever its origin, so a note moved in from the host's own memory with memory add --moved-from-host carries the same label as one an agent wrote of its own accord. The label is true of how the file is written (an agent runs memory add) but not of where the lesson came from, which the note's origin field records.
- iss-2610142221086043A recalled note's title sits on the item's head line, outside the body's fence. It is one validated, masked line placed after the id and the layer label, so it cannot open a heading, a list item or a fence, but inline markdown in it (a link, emphasis, a code span, inline HTML) is still live to a markdown reader. A project note's title comes from the repository's committed .abcd/memory.json, so a cloned or compromised repository controls how it renders.
- iss-2610142227520380The prompt router's root-commit lookup (boundedRootCommit) is a full-history rev-list under a 2 s cap. On a very large repository without a commit-graph it could exceed that cap on every prompt, so the live drain and the tied-note recall would skip every prompt, each with a stderr line, and staged transcripts would never drain there. It measured 0.01 s on this repository (7,873 commits), so the failure is projected, not observed.
- iss-2610142233473049A run abandoned with its pull request closed unmerged, and the run left in place, keeps its issue or intent reserved for up to a day, since the fence now renews for a day under a ruleset mirror and nothing tombstones a reservation when a run is abandoned.
- iss-2610142234581003kill-port given no literal operand is allowed: a port read from standard input (echo 3000 | xargs npx kill-port, xargs -n1 npx kill-port < ports) or given as an attached flag (npx kill-port --port=3000, -p=3000) passes the guard, because the kill-port entry asks for at least one operand and xargs is not read as handing it one. Each line stops whatever holds the port, as npx kill-port 3000 does, which blocks.
- iss-2610142234596259The package runners beside npx, npm exec, pnpm dlx and yarn dlx are not read as wrappers, so a blocker behind them only warns as an unrecognised launcher: pnpm exec, yarn <pkg>, yarn exec, bunx, bun x and pnpx each run the program their first operand names, and pnpm exec kill-port 3000 or bunx kill-port 3000 warns where npx kill-port 3000 blocks.
- iss-2610142235000193npm's value-taking config flags and global options are not in the runner value-flag lists, so their value is read as the program: npm exec --registry <url> kill-port 3000, --cache <dir>, --userconfig <file>, and a global option before the subcommand (npm --prefix . exec kill-port 3000) read the value or the option as the program and only warn as an unrecognised launcher where npm exec kill-port 3000 blocks.
- iss-2610142235000811The package runners' shell-string flags are not read: npx -c '<cmd>', npm exec --call '<cmd>' and pnpm dlx -c '<cmd>' run their value as a shell command, and the guard passes it unread, so npx -c 'kill-port 3000' is allowed while npx kill-port 3000 blocks. commands/guard.md and the runner change name this as a limit.
- iss-2610142235017884kill-by-holder and kill-by-search block a kill that sends no signal: a signal-0 liveness probe (kill -0 $(lsof -t -i :3000), kill -s 0 $(...)) or a signal-name listing (kill -l $(...)) only asks whether the process exists, or names a signal, and stops nothing, yet blocks as a kill of whatever holds the port or matches the search would.
- iss-2610142247170228The implement loop's renewal takes its term from the reservation tip as last seen in the remote-tracking ref (claim.View), not the tip claim.Reserve fetches fresh; in a single-branch or depth-limited clone, or one with a narrowed fetch refspec, a push does not update that ref, so a stale two-hour tip can make a drain push a two-hour renewal over the fence's day-long tip and lapse the hold.
- iss-2610142247175819finishMerged swallows a claim.View error, so every parked run's renewal is skipped on that drain move with no run-record entry and no answer naming it.
- iss-2610142247183640The lost-reservation note says the reservation 'is held by X from another copy, until T' for another copy's tip that has already lapsed, which reads as live.
- iss-2610142247187628logOnce dedupes a reservation entry on its stage alone, not the kind of failure, so a different failure after an unreachable origin (a take-over by another person, say) is dropped from the run record, though the step's answer still names it.
- iss-2610142247197128Step 13 of spc-2610031753359849 (abcd build reserves at start) must release a build run's reservation when its issue lane is handed back: the drain releases a handed-back drain lane's, but a run abcd build iss-N starts is routed by no drain, so its reservation would hold others off until it lapses.
- iss-2610142306552961abcd guard refused a test-harness command as killall-by-name because a JavaScript file the command named contains the line 'num += (b & 0x7f) * mult;', a bitwise AND on a varint byte, which the script reader took for a shell kill
- iss-2610142319008919The invocation regexp in synopsisCarriesFlag (internal/surface/cli/staleusage.go) has no left word boundary before abcd and joins the known path with \s*, which allows zero whitespace: a fenced line `myabcd build next --x` or `abcdbuild next --x` counts as an invocation of `abcd build next` that documents --x, so the stale-binary note can be granted on a line that never invokes abcd. Found by the Opus+Sonnet review of fix/stale-usage-notes, 2026-10-15.
- iss-2610142319015643synopsisCarriesFlag (internal/surface/cli/staleusage.go) counts a flag anywhere after an invocation on the same logical line, across a shell control operator: a fenced `abcd lint | jq --frob` (or `abcd lint && jq --frob`) reads as documenting `abcd lint --frob`, so the stale-binary note can be granted for a flag that belongs to another command. Found by the Opus+Sonnet review of fix/stale-usage-notes, 2026-10-15.
- iss-2610142319016723An unstamped abcd binary on PATH, built by go install or make build from a source checkout, now gets no advice on how to catch up when typed a verb or flag the plugin surface documents: staleUsageNote's unstamped branch (internal/surface/cli/staleusage.go) says only that the thing is not in this build, with no abcd update and no rebuild hint. This is the intended trade-off of iss-2610120921425348 (an unstamped build's age is not what the page proves), recorded so it stays visible. Found by the Opus+Sonnet review of fix/stale-usage-notes, 2026-10-15.
- iss-2610142321227822The build page's worktree-stage refusal list gives only a missing git identity as the reason a pick commit fails, but the code also refuses when a repository hook rejects the commit, and separately when a signing prompt or hook stalls it (errCommitStalled), with different remedy wording.
- iss-2610142324526905The embargo check's fold misses cross-script look-alikes, default-ignorable characters outside category Cf, and encoded forms: a Cyrillic or Greek letter standing in for a Latin one, U+034F, a variation selector or U+3164 inside an id or title, or an id written as HTML entities or with markdown backslash escapes passes the outbound check unrefused.
- iss-2610142324530436abcd embargo check --range reads commit messages, added lines and added file names only, never ref names or annotated tag messages, so a branch name or a tag annotation naming an embargoed advisory goes out on a push unchecked.
- iss-2610142324534587The embargo check keeps a hyphen inserted at a line wrap: a title word split as over- and flow folds to over-flow, so a reflowed paragraph naming an embargoed title passes the outbound check unrefused.
- iss-2610142326511964The macOS check job's merge-queue runs grew from 31-35 minutes to 34-40 minutes on 2026-10-14 (#990 took 40.0 minutes), close enough to the 45-minute job limit that the limit was raised to 60. The extra time is unexplained, and if it keeps growing the new limit will be reached too.
- iss-2610142334360850addEmbargoed's dropClosedTitles is a bare positional bool, so a future third caller could pass the wrong value and either leak a closed advisory's title into a publication text or refuse every range on a merge title, with no compiler help; both current callers are correct and each direction is pinned by a test.
- iss-2610150102542349The brief session page cannot itself tell a GitHub App's client id from an OAuth app's, so a relay the repository names or the person confirmed could report app_type github-app while holding an OAuth app; with no scope requested a fresh grant reaches public data only, but a person who earlier granted that OAuth app wider scopes is signed in again silently with them
- iss-2610150256285152A run state written by unreleased builds of the reviewer-route branch, which stamped schema 11 and stored answered on an await, is refused after the move to schema 12 with the remedy to restore or remove the run directory, which would throw away an intact run; its stated reason (version 11 never wrote answered) is also untrue for that file. Only branch builds wrote it, in the window between the route placing its answer and the hand-back.
- iss-2610150500162972The ubuntu leg of ci.yml's check job (timeout-minutes 30) now runs at its limit for every pull request, and the cancel policy of 2026-09-28 has fired: a check cancelled at the cap twice for the same reason stops that pull request and opens a speed lane. PR #1003 (feat/memory-recall-notes) was cancelled at 30 minutes twice: run 38676280619 attempt 2 spent 03:58:37-04:06:22 in Test (about 8 minutes) and was still in Test (race, internal) from 04:06:22 when it was cancelled at 04:27:48. PR #1008 passed in 25m40 only on a rerun after its first attempt was cancelled at 30m05, and the merge-queue entry for PR #976 (run 38680018438) was cancelled at 30 minutes too, with internal/core/implement/loop still running. On passing runs the race step took 16-18 minutes and the plain step 6-7; the race step's package times sum to about 3,500-3,750 seconds on the four-core runner, so it is bound by total CPU rather than by one package, and its heaviest packages are internal/core/lifeboat (578-594s), internal/core/reading (547-557s), internal/core/launch (357-365s) and internal/surface/cli (333-367s). iss-2610142326511964 covers the macOS leg's slowdown; this is the ubuntu leg. <!-- record-lint: forward-looking -->
- iss-2610150512342464Reservation footprints are whole packages, so concurrent builds collide on hub packages even when they touch different files. A spec's footprint lists packages, and the reservation overlap check backs off any two holders whose packages intersect, including the same person's two worktrees (product-thinker ruling 2026-10-15: that serialisation stays). Ten of the thirteen open specs that declare a footprint list internal/surface/cli, the package every verb's command lives in, so in practice nearly every pair of concurrent builds runs one at a time even when one adds a new file there and the other edits a different one. Naming files instead of packages would keep the protection while letting non-overlapping builds run side by side; the cost is that every spec must name its files exactly, and a file it forgets is unprotected unless something checks the landed diff against the footprint.
- iss-2610150524235929A branch whose preflight passed is pushed only if someone remembers to: abcd pushes after the receipt for a build lane alone. abcd build's land step already refuses a push without a receipt naming the head and then plain-pushes the lane. Every branch landed outside the loop gets no such step: hand-built branches, cloud-session pull requests, release branches, record-only chores. On 2026-10-14 one such branch's preflight passed at 13:17 and the branch sat unpushed for about two hours, because the step after the gate was lost across a context compaction. The coordinator now runs a hand-written scratchpad script that pushes after a minted receipt; that is one session's workaround, not abcd. The product thinker asked (2026-10-15) for this to be abcd-wide, toggled in config, default on.
- iss-2610150524246898Ready pull requests reach the merge queue one at a time, so a queue that can build four entries at once tests one. On 2026-10-15 abcd's own queue was configured to build up to four entries (max_entries_to_build 4), but the coordinator queued each pull request only after the previous one merged, through hand-run watchers. With each queue run taking 25 to 40 minutes, three ready pull requests cost about two hours instead of about forty minutes. abcd's land step arms auto-merge for a build lane, which lets the queue batch, but landings outside the loop have no such step, and iss-2610090642376032 already records that even a lane's arming can leave a pull request unqueued. The product thinker asked (2026-10-15) for queueing ready work together to be the default for every abcd-managed repository, toggled in config. Bound by the security standard rule: abcd adds the queueing, never changes how the repository's queue is configured.
- iss-2610150526192138Derived values and append-at-end lists in the release-gate manifest and surface registers conflict on every surface-adding branch. Every branch that adds a command page, agent prompt or surface chapter rewrites the same lines of .abcd/development/release-gate/manifest.json (checkerCount, promptHash, and the one-line prompt context that carries the command and agent rosters) and the manifestHash literal in receipt.example.json, which is the sha256 of the manifest, so two such branches always conflict and the second must merge main and run a fresh preflight before it can queue again.
- iss-2610150529485165A project's site renders only what abcd already writes, so it has no pictures of its own: abcd should ask the person for images, or offer to generate some, depending on the context (the about page's hero, a chapter's figure, the project's kind), and commit what is chosen where the site can render it
- iss-2610150551207288When abcd offers the product thinker options, there is no option for 'this question is unclear'. On 2026-10-15, at the planning interview for itd-2609151838312703, the product thinker could not follow a question about an overlapping draft and had to type 'explain, unclear' into the host's free-text field. The asking rules let an option set end only in 'Decide later' or 'None of these', so a person who does not understand the question has no option to say so. The product thinker's words: when offering options to the PT, always offer 'Unclear, explain with an example' to ensure the user can select that.
- iss-2610150553031954Before any record quotes the product thinker or the technical facilitator, they are shown their own words, and where those words will go, every time. Today a session writes their words into intents, decision records and issues, and they see them only if they ask.
- iss-2610150558540639The person still sees the question guard's refusals as errors while a session rewrites a question. On 2026-10-15 one question to the product thinker was refused three times before it reached them: the header, three sentences per option, the row limit, a missing Change later line and a named command. Each refusal showed on their screen as a hook error, because the session drafted the question itself instead of through the drafting agent
- iss-2610150616342977reserveAgain's stale-view fallback takes the plain reserve's renewed row with the default lease, not the preserved term (renewalTerm): in the narrow case where the view as last fetched hides this copy's own live reservation, a resume renews it through the plain reserve and can cut the extended day the land fence gave a pull request waiting on a person.
- iss-2610150616423705A resume over an issue someone else has since resolved or wontfix'd renews or reserves a reservation on a closed issue, which then holds until it lapses: reserveResumed reads found_at from whichever status folder holds the issue and reserves it again. Harmless, since no second holder can appear, but origin shows a closed issue as reserved.
- iss-2610150616434848releaseHandedBack: a drain retry of a failed hand-back release that succeeds is not written back to the run record, so the run's last reservation entry stays reservation_release_failed (saying the reservation lapses with its lease) although it was released, and any later releaseHandedBack over the run, finding no reservation_released entry, pushes the release again: idempotent, but it costs a fetch.
- iss-2610150656007932The brief's embark criterion says the amended press release becomes the new repository's .abcd/development/brief/README.md, but the brief-to-lifeboat mapping (internal/core/lifeboat/mapping.go) and this repository keep the press release at .abcd/development/brief/01-product/01-press-release.md, the path the project site reads its brief opening from. The criterion names a file nothing writes.
- iss-2610150656282243abcd land and the build loop decide whether a merge is held for a person's approval (ruling AM1) from the committed ruleset mirror under .abcd/work/rulesets/, never from the forge's live rules. A mirror that has gone stale, saying an approval is required when the forge no longer requires one, lets abcd arm a merge that no person gates. Found by the Opus security reviewer of the abcd land change on 2026-10-15; the loop has the same reading, so this predates abcd land. Route exists without abcd: no, the mirror-based decision is abcd's, so abcd fixes it.
- iss-2610150706489874A project site still shows authorship read from git history, which abcd does not write: the health page's same-author panel names git authors, and record.json carries far more than tallies. On a project build its authorship block lists every author by name, people under "humans" and bots under "bots", each with a profile link wherever their commit address is a GitHub noreply one, and lists every model string the commits declare under "by_model". That is all the data the dropped contributors page showed, so dropping the page hid nothing: anyone can still read it from record.json. The contributors page was dropped from project sites for the same reason, pending the product thinker's confirmation
- iss-2610150726321422The board bare abcd prints is called the status board, but it is the dashboard in the terminal: abcd dashboard already serves the same view to a browser over Tailscale, and the board is moving to that HTML form. Two names for one thing, and the word status is now wanted for abcd status, the people's view of what other sessions announce and hold (itd-2609151838312703 decision 21). The product thinker ruled on 2026-10-15 that the status board should be renamed the dashboard. About 14 files say status board: README.md, commands/abcd.md, docs/how-to/install.md, docs/reference/cli/commands.md and the brief.related itd-2609151838312703
- iss-2610150726331622abcd peers does two unrelated things: it lists records that sibling worktrees and local branches hold that this checkout does not (an agent's duplicate check before filing), and it fetches and lists the reservations on the shared remote. The second duplicates abcd status from itd-2609151838312703, the people's view of what everyone else is doing. The product thinker ruled on 2026-10-15 that peers keeps its name for its future meaning, which sessions are running now, local first and later over a private network such as Tailscale or WireGuard (the session register itd-2609150819440345), and that the local duplicate check belongs under abcd status --local.related itd-2609151838312703
- iss-2610150733180751embark carries neither a source repository's decision records nor its frozen decision log, so re-deriving the lifeboat graveyard after embarking can differ from the source for a repository that has either; seen while moving the lifeboat to the decisions folder (step 4 of the decisions build).
- iss-2610150733190782The cold-reading assembler's exclusion floor now names only the decisions folder; a managed repository's frozen .abcd/work/DECISIONS.md lost its explicit exclusion. No current include row reaches .abcd/work/ beyond issues, so nothing leaks today, but a future glob such as .abcd/work/*.md would admit the frozen log into a cold reading.
- iss-2610150733196835abcd site (its Describe report) names the issue-ledger publication switch but not the new decisions switch, so a person cannot see from the report whether the Decision log page will be published.
- iss-2610150733200904A record text written only in non-ASCII letters, such as a decision in Cyrillic, is refused as having no letters or digits, which is false for that text; the slug cutter keeps ASCII only, and the message describes the slug's emptiness as the text's.
- iss-2610150745549092runner/proc.go (the timer path near :196) and tools/install.go (near :325) kill a command's process group with syscall.Kill(-pid) from a select that races the goroutine calling cmd.Wait: when the leader exits at the moment the timer fires, Wait can reap it first, and in principle the group id could be reused by then, so the SIGKILL would reach another group. The window is tiny and the pattern predates the abcd land change, which moved both onto procgroup.Lead/Kill token for token; abcd land's own gate is immune because exec serialises its Cancel. Route exists without abcd: no, this is abcd's own process handling, so abcd fixes it.
- iss-2610150749052356The generated ADR and drafts indexes dropped hand-written relationship notes the old rows carried ('refines adr-50' on adr-55, 'amends adr-19' and 'extends adr-19, adr-20' on adr-31, adr-39/adr-23 links on itd-22, a reframe note on itd-16), because a row is derived from the record's H1 and status only.
- iss-2610150749053362Several draft intents carry H1 titles that read badly now that the out-of-scope drafts index is generated from each record's H1: itd-70's H1 is the placeholder 'Drawn-out intent', itd-2610070544145422's H1 is cut off mid-sentence ('…and it just works: the'), and eleven drafts have paragraph-length H1s of 300 to 1,093 characters (for example itd-2609150819440345 and itd-149).
- iss-2610150749065106The index generator reads a register with CRLF line endings normalised to LF and writes the whole file back as LF, touching bytes outside the generated markers; the lint step normalises too, so the churn is silent. No register is CRLF today.
- iss-2610150749068082release/indexregions_test.go checks that no generated region's source directory is one the release cut writes by comparing against a hard-coded list of the cut's write paths, so a new write path added to the cut is not noticed unless someone also updates the list.
- iss-2610150756067603A project site switched off with no abcd-written content left is flagged by bare abcd lint as an error and refused by lint site --project, although setup exempts a switched-off site from the empty check; it needs the record emptied after the site was switched on, so it is rare
- iss-2610150812471577abcd checked that a release binary was built by its release workflow, but most of those checks named only the workflow file and never the branch or tag it ran from, so anyone with write access who pushed a branch or a v-tag carrying an edited release.yml could sign a binary the check accepted (`gh attestation verify --signer-workflow` matches the workflow path and ignores the ref after `@`). The checks that named the path only were `.github/workflows/release.yml` (the receipts check, the linux binary and the plugin zip), `.github/workflows/site.yml`, and the release workflow template laid into managed repositories; the bootstrap installer, `install.sh`, the install one-liners and the printed by-hand commands added the tag's commit but not the ref; and `internal/core/update/provenance.go` pinned the ref but also accepted any `refs/tags/v*`. Underneath, abcd's releases were mutable, so a release's binary and `checksums.txt` could be replaced together, and the release environment had no branch policy.
- iss-2610150827113191The build loop's landMerged proves a lane landed only by ancestry; after a squash or rebase merge it refuses and hands the worktree and branch cleanup to a person, though abcd land now proves the same case through the forge (landing.MergedAt: a merged, same-repository pull request at the gated head into the default branch). The two landings disagree about one fact, and the loop's refusal costs a person a manual cleanup on every squash-merged lane. Found by the round 3 reviewers of the abcd land change, 2026-10-15.
- iss-2610150827114224gitutil.ScrubURLCredentials, which abcd land and the build loop apply to git and forge text they print, finds URLs with a regex whose authority ends at the first slash: a password containing a raw slash (https://u:p/w@host/x) is left unscrubbed, and a query holding an at sign (https://host?q=a@b) is over-redacted to https://b. Git percent-encodes such characters in URLs it prints, so the leak needs a hand-written URL, and over-redaction only garbles a message. Route exists without abcd: no, the scrubber is abcd's, so abcd fixes it. Found by the round 3 reviewers of the abcd land change, 2026-10-15.
- iss-2610151023089957Revisit whether a project site should show anything from git history, such as who wrote a record or when it changed. For now a project site shows none of it.
- iss-2610151050383937Two brief surface chapters both carry the number 37: 04-surfaces/37-embargo.md and 04-surfaces/37-reserve.md, each minted on its own branch, and the chapter table in 04-surfaces/README.md lists two rows numbered 37. Nothing refused it, because each branch numbered its chapter after the highest on its own base.
- iss-2610151050390126The check that the release-gate detector fills its ${commands} and ${agents} placeholders only asserts that two substrings occur in brief-surface-crosscheck.js. With the substitution code commented out the check still passes, so a detector that sends its checkers an unfilled prompt would ship green (review note on chore/merge-hotspots, 2026-10-15).
- iss-2610151050395768After the release-gate manifest's derived values stop being stored (the chore/merge-hotspots branch, under review on 2026-10-15), the brief's 04-surfaces/README.md register is the main remaining line every surface-adding branch edits: its chapter table ends on the newest number and two of its rows are single-line inline lists of verbs, so two such branches conflict there. Measured on the ten surface-adding pull requests of 2026-09-24 to 2026-10-15: the table end in 8, the agents-and-hosts row in 5, the one-file-per-verb list in 5.
- iss-2610151050403016The embargo store's path moved into a leaf package, internal/core/embargo/storepath, to break an import cycle when the embargo branch merged main (2026-10-15, PR #1015). The package has no test of its own; its rule is exercised only through the embargo and peers tests.
- iss-2610151050411986After the CI speed lane (#1014) let the plain test step name its slowest packages first, the test that guards that step drops every word starting with - before comparing package sets. A plain step changed to go test -short -run=TestA ... ./... now passes both TestMacOSLegRunsItsSuiteOnlyWhereItLands and TestPlainTestStepRunsTheWholeModule, where the old exact match refused it (review note, 2026-10-15).
- iss-2610151050413162TestRawSessionLeavesNothingBehind fails, rather than skips, when the machine cannot open a pseudo-terminal: a preflight on 2026-10-15 failed only on 'opening a pseudo-terminal: /dev/ptmx: device not configured' with 40 of 511 ptys in use, and the same test passed three times straight after. A transient pty failure therefore fails a whole preflight.
- iss-2610151050427571A lane worktree made with git worktree add -b <name> <path> origin/main tracks origin/main, so a bare git push from it aims at main. On 2026-10-15 a post-preflight push from such a branch was refused only by push.default=simple, because the names differ; under push.default=upstream it would have pushed a feature branch's commits to main.
- iss-2610151411351873internal/ghcontract checks that every field a GraphQL query selects exists on its type, but never checks the field's arguments. abcd land's queue-state query depends on isRequired(pullRequestNumber:$n): the forge refuses isRequired with no argument ('A pull request ID or pull request number is required'), yet a query that dropped the argument would pass every test against the fake forge. That is the class of defect the gh field pins exist to stop (a field the real forge refuses, hidden by a fake). Found by the round 5 implementer of the abcd land change, 2026-10-15.
- iss-2610151422055601The brief at .abcd/development/brief/04-surfaces/06-capture.md:394 says: §3 'Ledger structure' presents the issue frontmatter 'per the issue-ledger schema in internal/core/issueschema' as a field-by-field list of what a record may carry (schema_version through resolved_by). The shipped surface differs: internal/core/issueschema/issueschema.go:93 adds "finding_ref" to the Known allow-list (the key the consistency pass stamps on a filed finding so it is not filed twice); the brief's schema block omits it, and no brief chapter names finding_ref at all. (v0.14.2 release crosscheck, undocumented-surface, raised by opus in a05.)
- iss-2610151422058515The brief at .abcd/development/brief/04-surfaces/03-embark.md:17 says: "What ships is the unpack and the probe" — the shipped-surface callout enumerates two sub-verbs. The shipped surface differs: Three embark sub-verbs ship: `abcd embark --help` lists from, lessons and probe; the chapter's own Sub-verbs table (line 42) and generated appendix list `lessons` as shipped too. The callout's enumeration omits `embark lessons`. (v0.14.2 release crosscheck, false-claim, raised by opus in a02.)
- iss-2610151422061013The brief at .abcd/development/brief/04-surfaces/10-docs.md:121-123 says: "The working verbs accept the `docs-lint.json` to load and the repo to work over; the bare citation parent only routes and takes neither." The shipped surface differs: Only the citation leaves take them: `abcd docs cite confirm` and `abcd docs cite refresh` carry --config and --root. The other working verbs under `abcd docs`, `fidelity` (flags --apply, --autonomous, --intent, --report) and `fidelity record` (flag --verdict-json), take neither, as the chapter's own generated appendix (lines 273-290) shows. The sentence holds for the cite sub-tree but is stated of the docs verb's working verbs generally. (v0.14.2 release crosscheck, false-claim, raised by opus in a09.)
- iss-2610151422061914The brief at .abcd/development/brief/04-surfaces/07-library.md:11-16 says: The library command merges `source` and `memory`, and under adr-40 "neither old name survives as an alias". The chapter then calls `.abcd/memory/` "the memory store" throughout and never mentions another memory surface. The shipped surface differs: `source` is gone from the binary, but `memory` is still a registered top-level verb (`abcd memory --help`: "Count the memory notes in both layers"). It now addresses a different store, the memory notes in `~/.abcd.noindex/memory.json` and `.abcd/memory.json`, and is documented in 37-memory.md. Strictly it is not an alias, but the old name does survive on the verb tree with a different meaning. This chapter does not mention it or tell the two memory stores apart. (v0.14.2 release crosscheck, false-claim, raised by opus in a06.)
- iss-2610151422063401The brief at .abcd/development/brief/04-surfaces/11-history.md:216-219 says: The session-start hook that carries the notice channel 'always exits successfully, because a notice is not a failure and a failing session-start hook shows the user an empty error banner'. The shipped surface differs: The shipped SessionStart hook (hooks/hooks.json -> hooks/session-start.sh) exits 2 when the plugin binary is not installed or when both ~/.abcd and ~/.abcd.noindex exist, and otherwise propagates the non-zero exit of bootstrap.sh or of `abcd hook session-start`/`prompt-router-reset`; only the Go entrypoint itself is the always-exit-0 path. The chapter states the property for 'the hook' without that scope. (v0.14.2 release crosscheck, false-claim, raised by opus in a10.)
- iss-2610151422069890The brief at .abcd/development/brief/04-surfaces/08-abcd.md:413-417, .abcd/development/brief/04-surfaces/08-abcd.md:416 says: A name retired with no alias is answered with what replaced it, and never as a stale binary: ... `memory` and `source`, which merged into `library`. The shipped surface differs: `memory` is a registered, shipped top-level verb (`abcd memory --help`: 'Count the memory notes in both layers...'; listed under 'For agents and hosts' in `abcd --help --agent`; commands/memory.md exists; brief README row 37 marks `/abcd:memory` shipped). Only `source` is a retired name: `abcd source` prints the merged-into-library line, while `abcd memory` runs. The chapter lists a live verb as retired. (v0.14.2 release crosscheck, false-claim, raised by opus+sonnet in a07.)
- iss-2610151422073042The brief at .abcd/development/brief/04-surfaces/21-update.md:9 says: this verb, with its check, is the only **command** that reaches the release origin, and only when invoked The shipped surface differs: `abcd launch --dry-run --fetch-baseline` and `abcd launch ship --fetch-baseline` also fetch from the release origin (both flags shipped: 'read the parity baseline from the tag's published plugin archive, verified against the release's checksums.txt (a network fetch ...)'); commands/update.md names them among the commands that reach the release origin. (v0.14.2 release crosscheck, false-claim, raised by opus in a16.)
- iss-2610151422073415The brief at .abcd/development/brief/04-surfaces/19-identity.md:80 says: An unloadable registry is reported as a warn-tier finding rather than as drift, so the symptom reads as a broken check rather than as a missing tagline. The shipped surface differs: internal/core/repolint/rule_positioning.go:54 reports an unloadable registry through targetRefusal (internal/core/repolint/repolint.go:179), which is SeverityError ('`abcd lint identity` refuses the same registry, so this is an error'), not a warn-tier finding; and `abcd lint identity` refuses such a registry outright. (v0.14.2 release crosscheck, false-claim, raised by opus in a14.)
- iss-2610151422075372The brief at .abcd/development/brief/04-surfaces/21-update.md:3, .abcd/development/brief/04-surfaces/21-update.md:3-6 says: The verb fetches the release, verifies the platform binary against that release's own checksums, and swaps the installed copy atomically; 'The release is verified in full before anything is written' (line 93). The shipped surface differs: `abcd update --help` and internal/core/update/update.go also verify the binary against SLSA build provenance (GitHub attestations API, Sigstore trusted root, pinned to intentdriven/abcd's release.yml and the tag's commit) and refuse with shape `unverified-provenance` (update.go:510, :591) when it cannot be verified, offline included. The chapter never mentions provenance verification, the attestations API / Sigstore TUF reach, or this refusal. (v0.14.2 release crosscheck, undocumented-surface, raised by opus+sonnet in a16.)
- iss-2610151422083596The brief at .abcd/development/brief/04-surfaces/21-update.md:143 says: On a run that reached the release origin, the receipt carries beside action the origin, the tag, the asset and its digest, the target path, and the ownership proof; env_ignored when overrides were scrubbed. The shipped surface differs: The receipt also carries `attested_by`, the verified provenance signer (internal/core/update/update.go:132; commands/update.md tells the host to report it); the chapter's receipt field list omits it. (v0.14.2 release crosscheck, undocumented-surface, raised by opus in a16.)
- iss-2610151422085155The brief at .abcd/development/brief/04-surfaces/22-site.md:103-105 says: "Every repository gets the same pages: the landing page, the record explorer, one page per record, the relationship graph, the timeline, the glossary and the status page." The shipped surface differs: The switchable set does match these seven (internal/core/site/pages.go PageNames). But the build writes more routes than the list names: `contributors/` always (internal/core/site/explorer.go:206, and the attribution gate reads it), and `record/foundations/`, `record/development/` and `references/` whenever their inputs exist (explorer.go:214-227). The chapter itself refers to the references and contributors pages at lines 189-191, but the page set it enumerates names none of the four. Repositories do not all get the same pages either: health, foundations, development, references and glossary each depend on their input. (v0.14.2 release crosscheck, false-claim, raised by opus in a17.)
- iss-2610151422086989The brief at .abcd/development/brief/04-surfaces/21-update.md:48 says: The verb takes an optional release tag; with none, it resolves the latest (no further condition on the bare form). The shipped surface differs: A bare update whose latest release is older than ~/.abcd.noindex/release-mark is refused with shape `older-than-mark` (internal/surface/cli/update.go:107); the update writes release-mark and naming an older tag lowers it (update --help). The chapter documents neither the release-mark record nor this refusal. (v0.14.2 release crosscheck, undocumented-surface, raised by opus in a16.)
- iss-2610151422089301The brief at .abcd/development/brief/04-surfaces/21-update.md:77 says: One further refusal arrives after the dispatch, once the release checksums are in hand: a regular file that none of the three proofs vouches for (the only post-dispatch refusal). The shipped surface differs: At least two more refusals arrive after dispatch: `unverified-provenance` (after the checksums match) and `older-than-mark` (after resolving the latest tag); 'one further refusal' understates the shipped refusal set (commands/update.md lists both). (v0.14.2 release crosscheck, false-claim, raised by opus in a16.)
- iss-2610151422091770The brief at .abcd/development/brief/04-surfaces/36-dashboard.md:96 says: Start refuses outside a checkout abcd manages, when a dashboard already runs, when Tailscale is not running or too old, when the tailscale command sits in the working tree or a world-writable folder, and when the port is Serve's or Funnel's; Stop (line 117) is described with no refusal at all. The shipped surface differs: `abcd dashboard stop --help` names its refusal as 'refuses when another start or stop holds the lock', and both start and stop take a file lock under ~/.abcd.noindex/dashboard/ with a 5s timeout (internal/surface/dashboard/control.go:41, :246, :642). The chapter never mentions the lock or the refusal it raises. (v0.14.2 release crosscheck, undocumented-surface, raised by opus in a27.)
- iss-2610151422092354The brief at .abcd/development/brief/04-surfaces/37-memory.md:6-7 says: Recall of a note through the prompt hook is the same spec's later step; this chapter covers the store and the verb. The shipped surface differs: Recall through the prompt hook is already shipped: internal/surface/cli/rules_prompt.go (recallMemory, header says spc-2610111627213138 step 2) calls internal/core/recall on every prompt, the 04-surfaces/README.md library/memory table says notes are brought into a session automatically when a prompt matches their recall words, and commands/memory.md line 76 describes the prompt-match recall. It is not a later step. (v0.14.2 release crosscheck, false-claim, raised by sonnet in a29.)
- iss-2610151422099918The brief at .abcd/development/brief/04-surfaces/README.md:148, .abcd/development/brief/04-surfaces/README.md says: The help-placement table gives the people block's `release` group as `launch` alone, and `embargo` appears in no row of the table (neither a people group nor the agents-and-hosts block). The shipped surface differs: `bin/abcd-darwin-arm64 --help` lists two verbs under Release: `embargo` and `launch`. commands/embargo.md declares `block: people`. The table's placement of every visible verb leaves embargo out. (v0.14.2 release crosscheck, stale-count, raised by opus+sonnet in a31, b00.)
- iss-2610151422101060The brief at .abcd/development/brief/02-constraints/04-naming.md:226 says: `history.jsonl`: one line per disembark run holding `manifest_sha256`, file list, oracle backend used, verdict. The shipped surface differs: The shipped record (internal/core/lifeboat/voyage.go) carries schema_version, event, at, manifest_sha256, source_name, source_root_sha, dest, files (a count, not a list) and bytes; it has no file list, no oracle-backend field and no verdict field. (v0.14.2 release crosscheck, false-claim, raised by opus in a32.)
- iss-2610151422107680The brief at .abcd/development/brief/02-constraints/04-naming.md:54-59, .abcd/development/brief/02-constraints/04-naming.md:49-54 says: The remaining surfaces are exempt from the maritime metaphor and 'are registered here so the exemption is on the record'; together with the maritime table and the named exemptions this is the full naming register of the shipped verbs. The shipped surface differs: The shipped verb `embargo` (bin/abcd-darwin-arm64 --help lists it under Release; commands/embargo.md exists) appears in neither the maritime table, the named exemptions nor the plain exemption list. (v0.14.2 release crosscheck, undocumented-surface, raised by opus+sonnet in a32.)
- iss-2610151422107714The brief at .abcd/development/brief/02-constraints/04-naming.md:222 says: `aliases`: array of prior names a repo has had, 'Recorded in per-root-sha `meta.json`' (unmarked, so a delivery claim per the truth rule). The shipped surface differs: The per-repo meta.json that ahoy install writes (internal/core/ahoy/apply.go) holds root_commit, name, github and corpus only; no code in internal/core/ahoy reads or writes an `aliases` field, and the index.json entry struct (internal/core/ahoy/store.go) has none either. (v0.14.2 release crosscheck, false-claim, raised by opus in a32.)
- iss-2610151422109691The brief at .abcd/development/brief/02-constraints/04-naming.md:225 says: `voyage/` row (Type column, unmarked): the operations namespace is 'Split by operation: `disembark/history.jsonl`, `embark/provenance.json`, `embark/from/<timestamp>/`'. The shipped surface differs: Only `disembark/history.jsonl` is written (internal/core/lifeboat/voyage.go joins only `<root-sha>/disembark`); nothing in internal/ writes `embark/provenance.json` or `embark/from/`, and 04-surfaces/03-embark.md §7 marks the `embark/` subtree 'not built yet'. The row carries no **(staged)** mark, which the file's own truth rule (line 156) requires for a design target. (v0.14.2 release crosscheck, false-claim, raised by opus in a32.)
- iss-2610151422111534The brief at .abcd/development/brief/05-internals/03-configuration.md:7 says: Beyond those eleven, the binary reads only keys a person opts into: the provider adapter's `oracle` keys and the interview's list style, the implement loop's `pace`, and the runner routes under `roles` and `runner`. The shipped surface differs: The binary also reads `reservation.github_username` from the machine layer (internal/core/claim/holder.go, holderKey, used by the reserve verb) and `consistency.max_request_bytes` (internal/core/intent/consistency_config.go) through the layered config reader; neither key appears anywhere in the chapter. (v0.14.2 release crosscheck, undocumented-surface, raised by opus in a34.)
- iss-2610151422111866The brief at .abcd/development/brief/05-internals/01-agents.md:98 says: A cold-reading definition holds five parts (## Object, ## Question, ## The blindness core, ## Regime, ## Item shape), and a test asserts exactly that composition. The shipped surface differs: All four agents/cold-reading-*.md carry a sixth top-level section, '## Shell commands the guard refuses' (the guard-lessons block added under iss-2610091942156774, noted in internal/core/reading/definitions_test.go). No test asserts an exact five-part composition: definitions_test.go fetches the named sections individually and asserts exactly one fenced JSON block in Item shape, so a sixth section passes. (v0.14.2 release crosscheck, false-claim, raised by opus in a33.)
- iss-2610151422116979The brief at .abcd/development/brief/05-internals/03-configuration.md:542 says: The machine layer config.json's readers are the provider adapter's and the filing-time match's `match` keys ... every other config read resolves the repo-scope `.abcd/config.json` alone. The shipped surface differs: Further config reads go through layered.Load(layered.Config, ...), which includes ~/.abcd.noindex/config.json: oracle.review/oracle.rp (internal/core/oracle/review.go), interview.list (internal/core/layered/interview.go, machine layer only), reservation.github_username (internal/core/claim/holder.go, machine layer only) and consistency.max_request_bytes (internal/core/intent/consistency_config.go); pace.go and runner/config.go call the layered reader too. The chapter's own interview and reviewer-route sections also say those keys are read from the machine layer. (v0.14.2 release crosscheck, false-claim, raised by opus in a34.)
- iss-2610151422118638The brief at .abcd/development/brief/05-internals/03-configuration.md:97, .abcd/development/brief/05-internals/03-configuration.md says: This repository's own config carries four of these blocks — `docs`, `meta`, `oracle` and `repo`. The shipped surface differs: .abcd/config.json carries five top-level blocks: docs, meta, oracle, outbound, repo (jq keys). (v0.14.2 release crosscheck, stale-count, raised by opus+sonnet in a34.)
- iss-2610151422120350The brief at .abcd/development/brief/05-internals/03-configuration.md:615 says: Every file in the user scope whose contents abcd acts on — rules.json, trusted-roots, local-transcript-roots, path-entry, cache-attestation, release-mark, config.json, oracle-routing.json, statusline.json, load-limits, credentials.json and credential-homes.json — is refused behind a symlinked ~/.abcd.noindex. The shipped surface differs: The list omits ~/.abcd.noindex/memory.json, which abcd acts on (memory notes recalled into every prompt) and reads through rules.ReadUserLayerFile, the rules layers' trust checks (internal/core/memnote/layers.go). (v0.14.2 release crosscheck, undocumented-surface, raised by opus in a34.)
- iss-2610151422122793The brief at .abcd/development/brief/05-internals/03-configuration.md:847 says: prompt-router stdout carries 'the rendered block of the domains new this turn, and nothing else'; the --json envelope's fields are text, injected, active and error. The shipped surface differs: `abcd hook prompt-router --help`: plain stdout is the rule block 'followed by a "## MEMORY" block of the memory notes the prompt recalls', and the --json envelope is {"text", "injected", "recalled", "active", "error"}; the chapter does not mention the memory block or the `recalled` field. (v0.14.2 release crosscheck, false-claim, raised by opus in a34.)
- iss-2610151422129661The brief at .abcd/development/brief/05-internals/03-configuration.md:557 says: User scope holds 'user-scope memory for personal cross-project knowledge (a later phase too: the shipped memory store is repo-scope)'; ':1023 the user-scope `~/.abcd.noindex/memory/` is a later phase ... (nothing in the binary resolves it today)'. The shipped surface differs: The shipped `abcd memory` verb (commands/memory.md; sub-verbs add, list, remove) keeps personal memory notes in a machine layer at ~/.abcd.noindex/memory.json (internal/core/memnote/layers.go MachineRelPath), written by `abcd memory add` (with --everywhere for cross-repo recall), plus a repo layer .abcd/memory.json; `abcd hook prompt-router` recalls them. Neither memory.json file appears in the user-scope or repo-scope inventory. (v0.14.2 release crosscheck, false-claim, raised by opus in a34.)
- iss-2610151422133234The brief at .abcd/development/brief/05-internals/05-prompt-quality.md:13-14,56-57 says: The unbumped-body-edit check needs a diff range "which the continuous-integration caller supplies"; "The range comes from the CI caller". The shipped surface differs: The range is armed locally too: the Makefile `record-lint` target runs `go run ./cmd/record-lint -agent-diff origin/main...HEAD` (Makefile:165), so every `make record-lint` and `make preflight` arms the check, not only CI (.github/workflows/ci.yml:477). The brief presents the CI caller as the only source of the range; the 'never from the in-tree config' half still holds (.abcd/record-lint.json carries no range). (v0.14.2 release crosscheck, false-claim, raised by opus in a35.)
- iss-2610151422138325The brief at .abcd/development/brief/05-internals/03-configuration.md:1118 says: Plugin layout: internal/adapter/ holds scanner/, gitleaks/, hosting/, openaiapi/, tailscale/ ('hosting, openaiapi and tailscale are adapters outside the capability seams'). The shipped surface differs: internal/adapter/ also holds repoprompt/ (the RepoPrompt reviewer route, itd-6, listed in internal/README.md:290), which the tree omits. (v0.14.2 release crosscheck, fictional-layout, raised by opus in a34.)
- iss-2610151422138805The brief at .abcd/development/brief/05-internals/03-configuration.md:667 says: Two namespaces are not part of [repo scope]: `logbook/`, a retired name, and `rp/`, staged with its adapter. The shipped surface differs: The RepoPrompt adapter is not staged: internal/adapter/repoprompt ships and the chapter's own 'reviewer route's keys' section (oracle.review = rp) describes it as read by `implement step`. No .abcd/rp/ namespace is written, so only the 'staged with its adapter' reason is stale. (v0.14.2 release crosscheck, false-claim, raised by opus in a34.)
- iss-2610151422139704The brief at .abcd/development/brief/05-internals/05-prompt-quality.md:106-108, .abcd/development/brief/05-internals/05-prompt-quality.md:128-129 says: the four review and research prompts enter the changelog at 0.2.0 (the bump that first gave them the untrusted-input contract) The shipped surface differs: The agent changelog entry '0.2.0 — 2026-08-19 (iss-278)' (.abcd/development/agents/CHANGELOG.md:752-791) lists FIVE prompts: ruthless-reviewer, security-reviewer, docs-currency-reviewer, intent-auditor, sota-researcher. The same chapter says 'five prompts hardened on 2026-08-19' at line 119. (v0.14.2 release crosscheck, stale-count, raised by sonnet in a35.)
- iss-2610151422140743The brief at .abcd/development/brief/06-delivery/02-verification-matrix.md:67 says: Capture filtered list: `abcd capture list` with a state filter prints one line per issue, sorted by id. The shipped surface differs: capture.List (internal/core/capture/workflow.go:819) sorts by id only as a tiebreak and then calls prioritise(), which stably orders unblocked issues ahead of blocked ones and, within each group, higher severity first (workflow.go:1011-1016). The shipped order is derived priority, as 04-surfaces/06-capture.md §5 states, not id order. (v0.14.2 release crosscheck, false-claim, raised by opus in a38.)
- iss-2610151422141736The brief at .abcd/development/brief/02-constraints/04-naming.md:101 says: "three verbs (`launch`, `decide` and `build`) refuse instead of rendering" on a bare call. The shipped surface differs: Bare `abcd reserve` also refuses as a usage error (`abcd reserve --help`: Usage `abcd reserve <record-id>`), and bare `abcd report` refuses anywhere but a terminal. The enumeration this paragraph defers to (04-surfaces/README.md § Bare invocation) names reserve, so the count of three is stale. (v0.14.2 release crosscheck, stale-count, raised by opus in b00.)
- iss-2610151422144124The brief at .abcd/development/brief/06-delivery/01-build-sequence.md:35, .abcd/development/brief/06-delivery/01-build-sequence.md:26-29 says: Three further adapter packages stand outside the capability seams: `openaiapi`, `hosting`, and `tailscale`. The shipped surface differs: internal/adapter/ holds four packages beyond the scanner seam and its gitleaks backend: hosting, openaiapi, tailscale and repoprompt (the RepoPrompt reviewer-route MCP client, itd-6, imported by internal/core/oracle/review.go and listed in internal/README.md:290). The count is three where the tree has four, and the chapter never names repoprompt. (v0.14.2 release crosscheck, stale-count, raised by opus+sonnet in a37.)
- iss-2610151422150430At CHANGELOG.md:16; RELEASE.md:7: The entry says that with `oracle.review = rp` in the repository's or the machine's configuration, a build lane sends its reviews to RepoPrompt. In the code (internal/core/oracle/review.go) the route also needs `oracle.rp.url`, and only ~/.abcd.noindex/config.json may set it: a repository that sets it is refused. With only `oracle.review = rp`, every review falls back to the host. commands/build.md and commands/implement.md state this correctly; the changelog line does not mention the URL. (v0.14.2 release docs-currency review, raised by opus.)
- iss-2610151422151786At CHANGELOG.md:9: The forge-text entry's list of what the check does not cover leaves out the pr and issue close --comment forms, a body or path the line does not fix (`--body "$BODY"`), and a short flag bundled behind another (`-db x`). commands/guard.md lists all of these. Verified: a pr close --comment carrying a tool footer is an allow, while the same text on pr comment --body is blocked. A reader of the release notes could take closing comments to be covered. (v0.14.2 release docs-currency review, raised by opus.)
- iss-2610151422155612At CHANGELOG.md:5-24: Judgement call under the derived-changelog convention, which gives partly delivered intents no changelog line. This binary ships user-visible verbs that the 0.14.2 section never mentions: `abcd embargo` (listed in the default root help under Release, with a full command page), `abcd reserve` and `abcd memory` (in --help --agent), `rules --prompt`, drain reservations, and consistency chunking with --max-chunks. Line 5 says itd-2610112239022766 (embargo) is 'targeted and not shipped', but `abcd embargo` is in the binary. It also reuses the name `abcd memory`: in v0.14.0 and v0.14.1 bare `abcd memory` refused with exit 2; it now exits 0 with a different payload, and the section has no line saying so (the preamble says a break is stated as an Added line). Only docs/how-to/upgrade-to-v0.14.0.md mentions the reuse. / The pages shipped in this range document verbs the changelog and release note never announce: abcd reserve, abcd memory (add/list/remove), abcd embargo, `abcd rules --prompt`, reservation fields on `abcd peers` and the bare board. They exist in the binary and the pages match it, so nothing misleads; the changelog is record-derived, so this follows from which records were… (v0.14.2 release docs-currency review, raised by opus+sonnet.)
- iss-2610151422157749At docs/how-to/upgrade-to-v0.14.0.md:7-9,32-35: The guide says a script that runs an old command name 'gets a refusal that names what replaced it'. The new paragraph covers bare `abcd memory` now running, but on this binary `abcd memory ingest`, `ask` and `lint` refuse as a plain cobra unknown sub-verb (`abcd: unknown command "ingest" for "abcd memory"`, exit 2) with no pointer to `library`. Verified: `abcd source` still names its successor. The paragraph also says only 'a release after v0.14.0' and does not name v0.14.2. / The note says 'A release after v0.14.0' reuses the name memory without naming the release, while the table above still lists `abcd memory` as retired. Verified true of this binary (`abcd memory` answers with a count, `abcd memory ingest` is still unknown command, exit 2). Naming v0.14.2 would be exact. (v0.14.2 release docs-currency review, raised by opus+sonnet.)
- iss-2610151422163904At CHANGELOG.md:23: The entry says the build page 'lists all four refusals the pick commit's worktree stage can raise'. pickCommit (internal/core/implement/loop/pickcommit.go) raises more: a signing prompt or hook still waiting, an entry it could not write, a grounds-writer defect, and a hook refusal that shares the identity message. commands/build.md:128-130 does cover the hook and signing cases, so the page is fine; only the count of four is overstated. (v0.14.2 release docs-currency review, raised by opus.)
- iss-2610151422164851At docs/how-to/install.md:239-247 and CHANGELOG.md:27: Neither page says that a symlinked ~/.abcd.noindex (the dotfiles layout) never gets the .gitignore (homeignore.Lay returns NoHome), nor that an existing .gitignore there is kept as it is while the marker is written. install.md does say a symlinked folder is left as it is two lines earlier, so a careful reader can infer it. (v0.14.2 release docs-currency review, raised by sonnet.)
- iss-2610151422166945At commands/peers.md:84-85: The page says `fetched_at` and `age_seconds` are both absent when nothing has been fetched. The binary emits `"view":{"origin":false,"age_seconds":null}`: reservationView.AgeSeconds has no omitempty, so the key is present as null. A consumer that tests for the key being present gets a different answer from one that tests for null. (v0.14.2 release docs-currency review, raised by opus.)
- iss-2610151422179394At commands/launch.md (version-order paragraph): The example 'v0.14.2 after v0.15.0' reads oddly in the release that is itself v0.14.2; the rule is correct, only the example is awkward. (v0.14.2 release docs-currency review, raised by sonnet.)
- iss-2610151423133433The dependencies chapter says RepoPrompt and codex are two opt-in oracle adapters, but no codex adapter exists: internal/adapter holds gitleaks, hosting, openaiapi, repoprompt, scanner and tailscale, and the runners are claude and opencode. Raised by the Opus doc-fidelity reviewer for the v0.14.2 cut, outside the two intents it judged.
- iss-2610151501121204abcd land times its auto-merge toggle grace from the newest time a required check passed, read from the first 100 check contexts the forge lists. In a repository with more than 100 checks on a pull request, a required check beyond that page that passed last never moves the clock, so the grace can end early and land can toggle an arming the forge was about to queue. The holder report already says when more checks follow; the toggle does not use that. Rare: abcd's own pull requests carry 13 checks. Found by the round 6 reviewer of the abcd land change, 2026-10-15.
- iss-2610151617249338A fix to a plugin-payload file committed after the release roll changes the plugin archive's digest, and nothing before the release run notices. On 2026-10-15 the v0.14.2 cut fixed docs/how-to/install.md after the content commit (a docs-currency finding); make preflight passed, abcd launch receipts passed, the release PR merged, and only the release workflow's verify job refused: the committed marketplace pin named the archive rendered at the roll (beb4343893…), the merged tree rendered another (28755d0cf4…). No tag was cut, so the release could be repaired by re-pinning on main, but it cost a merge-queue cycle and a second release run.
- iss-2610151855227496abcd land's single run, push and then queue, stops on its most common path. On 2026-10-15 it pushed feat/abcd-land at 2abcab16c (18:54:26Z), then in the same run read pull request #1020 and the forge still reported the old head 572cd8c0f, so the enqueue step stopped with 'wait for the forge to see the push' and nothing was armed. A re-run 12 seconds later armed it. Refusing to arm on a stale head is the safe failure and stays, but since a push that moves the head is the normal case, the person must usually run abcd land twice. Found by a real run; the fake forge answers at once, so no test could show it.
- iss-2610152020234609The product thinker ruled on 2026-10-15, at about 20:15 BST: a pull request the land step leaves waiting on a person holds its reservation on the shared remote for a day, mirror or not. Today the land fence (fenceLease in internal/core/implement/loop/reservation.go) renews for lease.Max only where the checkout has a ruleset mirror (.abcd/work/rulesets/), and for the two-hour lease.Default otherwise, per decision 29 and criterion C44 of itd-2609091034175565 (spc-2610031753359849). Without a mirror, a pull request that is only waiting to merge loses its reservation two hours after the fence unless something renews it, and a colleague's drain can then take the record and redo the work.
- iss-2610152024267547ahoy install --outbound-hook leaves git config --local abcd.binary for each person to set by hand in each clone, so the commit-message check warns and lets every commit through until someone does, although the recorded remedy of iss-2609250834251447 said ahoy install would write it to the owned PATH copy, the abcd.guardPath precedent. The product thinker ruled on 2026-10-15 that the installer writes abcd.binary itself, to the absolute path of the provenance-verified abcd copy ahoy installs.
- iss-2610152024327989ahoy install has two opt-ins for the one outbound policy, --outbound-hook for the commit-message check and --outbound-forge for the shell guard's forge-text check, so a repository can be left with one half on and a person has to know to pass both. The product thinker ruled on 2026-10-15 that a single opt-in turns on both the commit-message check and the forge-text check.
- iss-2610152026530442The product thinker, ruling on 2026-10-15 at about 20:15 BST that a pull request waiting on a person holds its reservation for a day (iss-2610152020234609), also asked for this to be captured: if the one-day hold still leaves people duplicating work, count an open pull request for a record as holding it too. Today the pick judges a record held only by its reservation on the shared remote, as last fetched; an open pull request for the record does not hold it. A pull request still waiting after its day, with nothing renewing it, leaves the record open to a colleague's drain. Reading open pull requests at pick time would close that gap, at the cost of a forge call when the pick runs, which breaks the offline pick invariant 7 keeps today. This stays open until the one-day hold is seen to fall short.
- iss-2610152046379890A hosted cloud session's clone carries the host's default vendor identity as its git author, not the person's: the cloud probe of 2026-10-15 found it in the clone's git config, while the forge credited the push to the person's own account through the token. The product thinker ruled the same day that this vendor identity must not be shown anywhere, in no commit, ref, trailer or output, and that no person should have to set it by hand ('Who has to remember what? No manual steps.'). Session announcements (itd-2609151838312703) already fall back to the token's login for their own commits; every other commit a cloud session makes still carries the vendor identity until its setup sets the person's.
- iss-2610152050211710The product thinker ruled on 2026-10-15 that a security-relevant finding identified during development or review is fixed within the same development cycle, and that where this is not possible it is recorded as a private advisory and mentioned nowhere in commits, pull requests or other public text. Today a security finding a review raises is handled like any other: fixed, or captured as an open issue and named in the commit and PR trailers, which publishes a weakness before its fix ships. The rule is taught nowhere an agent reads before it acts.
- iss-2610152058070569Session naming (itd-2610111707085098) has no switch to turn it off: every session abcd's hooks run in is given a persona name unless the person names it by hand, and a person who does not want abcd to title their sessions has no way to say so short of naming every session themselves. The planning of 2026-10-15 left the switch out of scope to keep the build small.
- iss-2610152107197993core.hooksPath in a checkout's .git/config is the primary checkout's absolute .githooks path, so every linked worktree runs the primary checkout's hooks rather than its own. When the primary checkout falls behind main (409 commits on 2026-10-15), a worktree on a current branch runs a stale pre-push hook: the first real reservation push was refused because the stale hook did not know the reservation namespace. Nothing reports the skew.
- iss-2610152125101468A reservation footprint can hold a whole directory (docs, hooks, internal/surface/cli), and the overlap check then refuses every other reservation naming any file inside it. Generated files that every verb-adding branch regenerates, such as docs/reference/cli/commands.md, sit inside such directories, so two unrelated intents held by the same person from two copies could not both declare an honest footprint: on 2026-10-15 the messaging reservation's renewal was refused twice and had to leave out .githooks/pre-push, the ruleset mirror and the generated CLI reference, which it does change.related itd-2610161016394967
- iss-2610152149380984The banlist hook state (hooksPathState in internal/core/ahoy/banlist_scaffold.go) follows the global core.hooksPath when the clone sets core.hooksPath to the empty string. Git runs no hooks at all in that case, but when the global value is .githooks the state reports the banlist hook as armed.
- iss-2610152204573033When the clone's hooks directory is a symlink leading outside the git directory, the outbound install classifies the chained copy hooks/abcd-commit-msg as unreadable and its note advises moving that file aside, which does not help: the cause is the symlinked directory.
- iss-2610152204588951The outbound install's error notes pass git and filesystem errors through fsutil.RedactHome only, so a failure to open a linked worktree's shared git directory prints a home-relative path outside the working tree, against the rule that notes describe such paths in words.
- iss-2610152204590878The outbound 'runs the check' reading of a hook's text does not recognise an unquoted ${bin} lint outbound, so a hook that runs the check still draws the not-wired note and gets the copy of the check saved beside it.
- iss-2610152204593497The chain line abcd advises for a commit-msg hook it did not write falls back to /hooks/abcd-commit-msg when git rev-parse --git-common-dir fails, so a file at that root path would run; no gain to an attacker was found, as only root or the same user can create it.
- iss-2610152205005332planOutboundShim joins a relative core.hooksPath to the install's working directory; if the install runs from a subdirectory the wrong directory is read for the hooks-path check, which can drop the not-wired note. Unconfirmed whether the install's cwd is always the repository root.
- iss-2610152205016226The chained copy's edited-copy and earlier-template refresh paths have no test, and buildAbcd in outbound_shim_test.go fails the test rather than skipping when no Go toolchain is available.
- iss-2610152205019213The --outbound help text (cli.go and the generated CLI reference) does not mention that the install may save abcd's check as hooks/abcd-commit-msg and advise a chain line where git runs a hook abcd did not write; commands/ahoy.md and the brief do.
- iss-2610152215581665A reservation claimed with a date ahead of the reader's clock never lapsed.
- iss-2610152246142642Session naming's prompt hook writes a stderr note on every prompt of every titled session while the machine name register cannot be used: a sessions folder a group or others can write, one another account owns, or a register file that will not parse. Each note is accurate, but the same line repeats on every prompt until the person repairs the folder. Found by the final Opus review of itd-2610111707085098 (2026-10-15), recorded as not blocking.
- iss-2610152255258945A hosted cloud session may not load the abcd plugin that the repository's committed settings file enables: the host's cloud-environments page says cloud sessions do not install plugins declared in a repository's settings, so the plugin half of the cloud-sessions intent's criterion C11 (decision 10) may have no effect there, while the committed hooks and go run still work
- iss-2610152255268094The cloud report's issue-comment fallback finds the repository by parsing origin's URL strictly as github.com, but a hosted session may clone through a proxy URL, in which case the fallback could never post and a session whose push failed would leave its report only in the transcript
- iss-2610152324334460The given record that tells abcd's session names from the person's keeps 512 entries; a session whose record was dropped and is then resumed or forked is read as carrying the person's own name, so it is not held, and after a restart its name can be handed to a second running session.
- iss-2610152324339407A fork of a session the person named by hand is renamed when abcd has given that same persona name to another running session: the fork's own id has no given record, its title matches a name given to a different id, so it is read as an inherited abcd name. abcd cannot link a fork to its parent's empty (person's own) record. Sessions named before the given record existed have no record at all.
- iss-2610152324341567When a session's first prompt arrives with a title already equal to the name abcd reserved for it (the person renamed it to exactly that name), the prompt hook marks the entry sent but records nothing in given, so a later resume reads the title as the person's and does not hold it.
- iss-2610152324354563A session started with --name now makes the session-start hook resolve the repository root (a git call) on its keep path, which only records an empty given entry and needs no repository.
- iss-2610152329316029A session the person named by hand keeps its empty given record under its old id when it is cleared: the record moves only through a live entry, and a person-named session has none. A later resume of the new id, while abcd's session of that persona name runs elsewhere, reads the person's title as inherited and replaces it (C4).
- iss-2610152329329271The session-start hook's keep path, which records a person's own title as an empty given entry, swallows a lock or write failure silently; the lost record later lets a fork or resume read that title as an inherited abcd name.
- iss-2610152329330129A clear of a session abcd named and the person then renamed leaves the old id's live entry (abcd's name) held under the same host, under an id no session carries, until the host process exits; that name is wasted for the process's life.
- iss-2610152329345301The pre-lock filter mayHold admits every clear whose title appears anywhere in given, so such a clear takes the register lock and reads the process table even though a clear can no longer be read as inheriting; extra work, no wrong answer.
- iss-2610152337430521A session abcd named whose resume hook never ran (so the register holds no live entry for it) and which the person then clears is recorded as carrying the person's own name; after naming restarts and a new session is given that name, a resume of the cleared id keeps it, so two running sessions show the same name (C5, C6). It needs an earlier hook failure. Found by the confirmation review of 88f431b21, 2026-10-16, recorded as not blocking.
- iss-2610160006073622The cloud connector's launch step relies on host command-line flags (an environment id and a starting ref) that the host's local help does not list as documented for hosted sessions; if the host ignored them, the brief would start on the person's own computer, where only the brief's first-step place check stops it
- iss-2610160038528534collect runs a cloud-authored copy's code on the person's computer as the person; a later rung could run the collected copy's preflight in an isolated sandbox (a container or a separate account) so that cloud-authored code never runs with the person's credentials.
- iss-2610160039419977The cloud collect's tooling rule folds case for ASCII only, so on a case-insensitive disk a collected path spelled with a Unicode character that folds to an ASCII letter (the Kelvin sign for k, for example) could land on a tooling path the rule refuses in its ASCII spelling
- iss-2610160315304959After abcd land's own push moves a branch, the post-push wait re-reads the pull request until the forge shows the pushed commit, for up to 30 s of pauses. When someone else pushes to the branch straight after, the forge settles on a third head that will never equal the pushed one, and land waits the whole 30 s before it stops with its 'pull the forge's head' remedy. Nothing unsafe follows, since land never arms a head it did not gate, but the stop arrives 30 s late. Found by the Opus reviewer of the forge-lag fix (iss-2610151855227496), 2026-10-16.
- iss-2610160415393242In a checkout without its local tier, abcd peers lists a release reserved with a date more than five minutes ahead as holding merges, while abcd land and the implement land fence do not count it and print a notice; peers --json release_holds carries no field that says the hold was not counted.
- iss-2610160518331794The pre-push hook reads each pushed commit's tree through replace refs, so a local replace ref can make a commit that carries files read as the empty tree in the reservation and status rows, while the push sends the commit's stored objects.
- iss-2610160518336434The embargo store lookup finds the store by the root commit of HEAD, read through replace refs and grafts, so with HEAD on an orphan branch or a replaced root commit it looks in the wrong place, and a store it does not find reads as nothing under embargo: an embargoed record can then be announced or published.
- iss-2610160518345930C4's public-record read (peers scanTree, the ls-tree of origin's default branch) follows replace refs, so a local replace ref can make a record read as present on the default branch when the stored tree does not hold it.
- iss-2610160555504636The embargo check could stop finding its store after a merge brought in an unrelated root commit.
- iss-2610160608319973The brief at .abcd/development/brief/04-surfaces/README.md:476 says the open questions of itd-2610091918433290 name where memory notes are stored and what an agent may write without the person's yes. The intent's Open Questions section says none are left for the product thinker: the four first left there are settled under its Decisions (2026-10-11), and the memory verb ships add, list and remove.
- iss-2610160608359152The design-target callout at .abcd/development/brief/04-surfaces/08-abcd.md:480-482 says the shipped status path reads .git, .abcd/development and the three work tiers 'and nothing else: ... no linked intents, no spec store, and no thresholds'. The shipped board the same chapter documents (lines 153-342) also reads the mode state, peers, the inbox, oracle routing, the reviews block with its twenty-commit threshold (internal/core/reviews StaleAfter = 20) and the planned intents with their specs (internal/core/statusblock).
- iss-2610160608361793The brief at .abcd/development/brief/04-surfaces/11-history.md:192-195 and :203 says both staging entrypoints exit 0 on every path, and that on SubagentStop every failure path is a diagnostic and an exit 0. The registered hook commands, hooks/session-end.sh and hooks/subagent-stop.sh, exit 1 when the plugin binary is missing or a legacy ~/.abcd stands; only `abcd hook session-end` and `abcd hook subagent-stop` themselves always exit 0.
- iss-2610160608368891The brief at .abcd/development/brief/04-surfaces/01-ahoy.md:956 says 'The non-interactive flags pre-answer the prompts:' and lists approve-everything, adopt, marker target, oracle backend, deep scan, visibility, dev mode, the stale-binary override, the PATH directory and the attribution hook as the whole set. `abcd ahoy install --help` also registers --outbound, --readme-parts, --answers, --answered-in and --install-tool, each of which pre-answers a prompt.
- iss-2610160608369772The brief at .abcd/development/brief/04-surfaces/06-capture.md:73-77 says the one exception to the required person-written remedy is abcd's own automatic filers, the consistency pass and every promoted inbox report, which write 'none (filed automatically)'. A third automatic filer writes the same value (issueschema.MachineRemedy): the intake that files a privately sent report into abcd's private issue store.
- iss-2610160608372082The brief at .abcd/development/brief/04-surfaces/11-history.md:255-256 mentions `abcd history discard` only as the confirmed discard of a quarantined file, and describes `staged` only as per-repo or all-repos. The shipped `history discard <staged-filename> --yes` deletes a staged or a quarantined raw transcript, and both `discard` and `staged` take --root-sha to reach a repository whose checkout is gone (commands/history.md:73-77, 190-236).
- iss-2610160608373524The brief at .abcd/development/brief/04-surfaces/19-identity.md:62-63 says '`warn`, the default, reports drift as a warning that does not fail the run'. Bare `abcd lint` is tri-state and exits 1 on warnings alone (its help; internal/surface/cli/lint.go:73-75), so warn-tier drift alone makes the run exit 1.
- iss-2610160608376349The brief at .abcd/development/brief/04-surfaces/27-implement.md:59-61 says that outside a checkout, or in a repository with no commit, every implement sub-verb refuses and nothing is created. `abcd implement load --site preflight` runs and exits 0 outside a checkout: internal/surface/cli/implement_load.go:148-152 resolves the checkout root only optionally, and the load help documents a machine check with no checkout precondition.
- iss-2610160608380578The Exit codes section at .abcd/development/brief/04-surfaces/27-implement.md:400-404 lists 0 done (and every load-check status), 2 refused and 3 contention. `abcd implement load --wait` exits 1 when it gives up after --timeout and, with a command after --, exits with that command's code (implement load --help; the chapter's own lines 280-282).
- iss-2610160608381279The brief at .abcd/development/brief/04-surfaces/05-intent.md:569 says 'Three audit-loop modes, facilitator-elected per intent via the audit_mode frontmatter key', but lists only two beneath it: record-only and loop-to-acceptance.
- iss-2610160608389169The brief at .abcd/development/brief/04-surfaces/30-inbox.md:105-112 says a sender's id in a record family abcd resolves (adr, itd, iss, spc) is written as one word, so it never cites abcd's own record. abcd also resolves dcn ids (recordid.CitedIDRe; record-lint's prose_citation_resolves, internal/core/lint/prosecitations.go:138), but the promotion rewrite's senderIDRe (internal/core/report/inbox.go:714) covers only adr|itd|iss|spc, so a sender's dcn-N is copied as written and cites abcd's own dcn-N.
- iss-2610160608393433The brief at .abcd/development/brief/04-surfaces/04-launch.md:517 says refusal kind stale-intent is raised when 'an intent in planned/ has a spec that has closed'. The shipped rule (internal/core/release/emit.go:102-103) raises it only when a planned intent has no open spec left, every realising spec closed, as 05-intent.md:509 states.
- iss-2610160608394392The brief at .abcd/development/brief/04-surfaces/05-intent.md:571-572 says record-only is 'the default, and today's behaviour' and that an absent audit_mode key resolves to record-only, in a section not marked staged. No shipped code reads audit_mode or audit_budget (no match outside tests in internal/ or cmd/), and the backing intent itd-50 is in intents/planned/.
- iss-2610160608394736The brief at .abcd/development/brief/04-surfaces/05-intent.md:504 states 'surface_history entries are well-formed' with lint code IL012 (warn) as an unmarked invariant, in a list whose unenforced bullets carry (convention). No shipped check reads surface_history and no IL012 code exists, and line 493 says the IL0xx codes are later-phase design.
- iss-2610160608400185The brief at .abcd/development/brief/04-surfaces/04-launch.md:496 and :501 says the patch tier covers 'a release with no intent-tied change' and that a change not tied to any intent falls back to conventional-commit derivation. Nothing in the shipped tree derives a version from conventional commits: the version comes from the records' declared impact (internal/core/changelog/impact.go), and a cut with nothing user-facing is refused as empty-cut (internal/core/release/emit.go:120).
- iss-2610160608404245The brief at .abcd/development/brief/04-surfaces/04-launch.md:498 says every intent carries an impact, set when the intent is shaped and enforced by the record lint (adr-31). At 0de27c795, 91 intents in drafts/ and 4 in planned/ carry no impact key; the record lint's intent_impact_valid checks only the value set, and impact is required only at the close that moves an intent to shipped/, as 05-intent.md states.
- iss-2610160608415797The brief at .abcd/development/brief/04-surfaces/16-lint.md:140 says of the lint verb 'No gate in this repository invokes it'. The Makefile's docs-lint and site-render targets and CI (.github/workflows/ci.yml:505) run `abcd lint docs` and `abcd lint site`, and the commit-msg hook and scripts/check-attribution.sh run `abcd lint outbound`; only bare `abcd lint`, the v1 rule set, runs in no gate. The same page says at lines 71-73 that outbound is wired into CI.
- iss-2610160608416611The intro at .abcd/development/brief/05-internals/03-configuration.md:6 says install writes four keys, --attribution one and --outbound two, and 'four further keys can be hand-set ... Beyond those eleven'. The same chapter counts 'Thirteen keys' at line 22 and 'the remaining six' hand-set at line 30: native_secret_scanning, rules.force_refresh_every_n, match.threshold, match.fields, land.push and land.enqueue.
- iss-2610160608419844The brief at .abcd/development/brief/04-surfaces/21-update.md:9-14 says update, with its check, is the only command that reaches the release origin, and at :92 that its transport redirects only onto the release origin's own hosts; it names no other network destination. update also reaches GitHub's attestations API and Sigstore's TUF repository (tuf-repo-cdn.sigstore.dev) to verify build provenance (commands/update.md:26-28).
- iss-2610160608421679The user-scope inventory of ~/.abcd.noindex/ at .abcd/development/brief/05-internals/03-configuration.md:558, which must agree with 01-ahoy's tree, omits files abcd reads and writes there: oracle-routing.json (internal/core/ahoy/oracle_routing.go), statusline.json, cache-attestation, release-mark (internal/core/ahoy/release_mark.go, enforced by abcd update), the notes archive notes/<root-sha>/ and the .gitignore with its gitignore-laid marker (internal/core/homeignore).
- iss-2610160608423720The brief at .abcd/development/brief/05-internals/03-configuration.md:22 says 'Thirteen keys plus a meta block' and that install asks four questions and writes those values. readme.parts is also read and written in .abcd/config.json (internal/core/ahoy/readme_apply.go; ahoy install --readme-parts, documented in 04-surfaces/01-ahoy.md), and install now asks the README question; the key list, the example JSON and the four-questions count leave it out.
- iss-2610160608426210The hook wiring at .abcd/development/brief/05-internals/03-configuration.md:1171-1175 says hooks/bootstrap.sh downloads the pinned asset verified against that release's own checksums. hooks/bootstrap.sh also holds the download to the build-provenance policy through gh attestation verify, so the checksums are not the whole check.
- iss-2610160608430668The row at .abcd/development/brief/06-delivery/02-verification-matrix.md:104 says the land fence 'renews for a day under a ruleset mirror and the default two hours without one', citing loop.TestTheFenceRenewsWithTheDefaultLeaseWithoutAMirror. No test of that name exists. The fence holds a day with or without a mirror (fenceLease = lease.Max, internal/core/implement/loop/reservation.go:179), and the no-mirror case is held by loop.TestTheFenceHoldsADayWhenThePullRequestIsLeftForAPerson (internal/core/implement/loop/parked_reserve_test.go:188).
- iss-2610160608434377The brief at .abcd/development/brief/05-internals/01-agents.md:45 says each of the eighteen agent prompts declares its inputs and outputs as JSON. agents/docs-currency-reviewer.md asks for a report as a table, agents/ruthless-reviewer.md and its companion code reviewer return prose verdicts, and agents/sota-researcher.md holds no JSON at all, so four prompts declare no JSON contract.
- iss-2610160608438106The brief at .abcd/development/brief/05-internals/08-skills.md:84-86 says the ahoy page's install section prepares a repository by running the binary's audit, install and identity verbs. abcd has no audit verb (`abcd audit` exits 2 as unknown); the install section's Audit phase runs `abcd lint --json` (commands/ahoy.md:202), beside ahoy install and identity init and render.
- iss-2610160608442201commands/update.md:136-138 gives the by-hand check for an unverified-provenance refusal as gh attestation verify --cert-identity <release.yml on main> --source-ref refs/heads/main --source-digest <the tag's commit>, without --deny-self-hosted-runners. abcd's own policy applies that flag (internal/core/update/update.go:645, hooks/bootstrap.sh), and README.md and docs/how-to/install.md include it, so a person following update.md runs a weaker check than abcd does.
- iss-2610160608444348The drain sentence at internal/core/surface/sentences.go:130, 'Writes its state and user-visible drafts', shown by abcd drain --help, commands/drain.md:3 and docs/reference/cli/commands.md, omits a remote write: in a checkout with origin, drain reserves each issue it takes by pushing abcd-reserved/<iss-N> to origin (commands/drain.md:146-162), and the 81-line help never mentions origin or a reservation. build's sentence already says 'Writes the run's state and its reservation'.
- iss-2610160608451996itd-2609091034175565's press release persona quote says 'My laptop and my cloud session count as me, so they never lock each other out', but the shipped reservations refuse a second copy of the same person and name --take-over; the v0.15.0 release page dropped the quote for that reason
- iss-2610160608453195abcd update --help (internal/surface/cli/update.go) says build provenance is pinned to intentdriven/abcd's release.yml and to the tag's commit, leaving out that the signer must be release.yml on refs/heads/main, which commands/update.md, docs/how-to/install.md and internal/core/update/provenance.go require.
- iss-2610160608456302launch's hook-compliance gate warns that hooks/*.sh are not executable in the payload (mode 100644), but hooks.json invokes each as `sh "<path>"`, so the mode is irrelevant; the warning is a false positive (unchanged since v0.14.2)
- iss-2610160608457651A malformed grill citation in abcd ideate is refused with '(want adr-N, itd-N, iss-N, or spc-N)' (internal/core/ideate/record.go:497), but CitedIDRe (internal/core/recordid/resolve.go:41) accepts dcn-N as well, commands/ideate.md lists dcn-N as citable, and the brief (.abcd/development/brief/04-surfaces/18-ideate.md:57-58) says a decision record is cited by its dcn- id like any other record. The refusal tells the caller dcn ids are not citable.
- iss-2610160855131633The brief's staged audit-loop section (05-intent.md, the per-intent audit_mode and audit_budget keys) and 05-internals/03-configuration.md:353-363 still describe the audit loop as a per-intent mode, while itd-50 records that on 2026-09-21 the loop was re-scoped to the last stage of abcd build, not a per-intent mode; the staged text contradicts the intent it cites. Found while fixing iss-2610160608394392, 2026-10-16.
- iss-2610160857121531The brief says abcd update is the only command that reaches the network, but ahoy install also reaches GitHub's attestations API and Sigstore's TUF repository when it checks a downloaded binary's provenance (internal/core/update/provenance.go)
- iss-2610160858232720launch's hook-compliance gate treats a plugin-root file that a hook sources (. "$CLAUDE_PLUGIN_ROOT/x") or only reads as executed directly, so it judges that file's mode and can warn that a sourced file is not executable, the same false-positive shape iss-2610160608456302 fixed for files handed to sh or bash. No abcd hook sources or reads a plugin-root file today. Found while fixing iss-2610160608456302, 2026-10-16.
- iss-2610160910063601launch's install-surface reader (pluginRootRefs) does not see the plugin root reached through ${CLAUDE_PLUGIN_ROOT:-} or a shell alias of it (r="${CLAUDE_PLUGIN_ROOT:-}" then "$r/hooks/..."), the form most of abcd's own hook scripts use; post-tool-use.sh, pre-compact.sh, pre-tool-use.sh and user-prompt-submit.sh each execute "$r/hooks/bootstrap.sh" directly, and the gate sees none of those runs. bootstrap.sh is judged today only because session-start.sh also names it by $CLAUDE_PLUGIN_ROOT; were that line to use the alias, a missing or 0644 bootstrap.sh would pass the hook-compliance gate's existence and mode checks without a warning. Pre-existing; found while fixing iss-2610160608456302, 2026-10-16.
- iss-2610160924043423When a plugin manifest sweeps a directory of hooks ("hooks": "./hooks/"), each script there becomes a manifest entry that wins dedupeEntries, and launch's hook-compliance gate skips every entry that is not a hook-command entry, so a 0644 script that hooks.json executes directly is never judged. The same at 2347eb6c3 and after the iss-2610160608456302 fix; pre-existing.
- iss-2610160924048542No test covers launch's hook-compliance gate across two hook documents (the manifest's inline hooks and hooks.json reaching the same file), so a regression that rebuilt the executed-reference set per document instead of as one union would pass; the code handles the case today.
- iss-2610160925028248abcd reserve holds one record per reservation and caps a person at ten live reservations across every session and copy of that account, so a small documentation pull request that fixes N records spends N of the ten: on 2026-10-16 two four-record follow-up PRs plus two intents another session held filled the cap, and every further reservation by any session of that person was refused until those PRs merged. The cap meant to bound one person's holds instead bounds how many record-sized fixes can be in flight.
- iss-2610160953014402Only the most recent release should stay published: once a release is published, every earlier GitHub release is deleted automatically, its tag kept. Today launch's retention plan keeps the newest release of each minor line (v0.13.4, v0.14.2, v0.15.0 and the rest), and on 2026-10-15 and 2026-10-16 the previous release was deleted by hand at each cut (v0.14.1, then v0.14.2 on the product thinker's ruling).
- iss-2610160953425019abcd update's confirmation prints the replaced binary as 'replaced: sha256 <digest> — in no published release; it is the binary running this command, so it is abcd by construction'. The explanation after the digest is noise to the person reading it: they need to know what was replaced, not why abcd trusted it. Printed at internal/surface/cli/update.go:238 from the ownership proof's prose (internal/core/update/update.go:110).
- iss-2610160957404827abcd drain reads the issue ledger of the checkout it runs in and never checks whether that checkout is behind origin's default branch: from a primary checkout 185 commits behind main, the dry run listed 162 eligible issues from the stale ledger, many since fixed or changed, and a run would judge, reserve and work from that list.related itd-2610161016394967
- iss-2610161015368630A lane that refuses at a step without handing back (a conflicting pull request at arming, the land fence, or a brief refused because the issue is already resolved at the base) is read by laneOutcome as in progress, so every later drain move answers "drive" that lane and the drain opens nothing more; implement step --discard and --release act only on held lanes, so only removing the run directory by hand frees it.related itd-2610161016391855
- iss-2610161015370582A drain's hand-backs and judgements live only in the checkout that made them: routeHandBack promotes the issue to an intent draft in that checkout, uncommitted, then the release pushes a tombstone so the issue reads free everywhere, and eligibility ignores related_intents, so every other account's drain judges or works the same issue again and promotes it to its own draft id.related itd-2610161016394967
- iss-2610161015371794At the per-person cap of ten live reservations a drain move refuses with exit 2 (the cap is not treated as contention), returns before writing its state so the judgement just answered is lost, and advises releasing a reservation, which would free an issue whose pull request is only waiting for a merge.related itd-2610161016394967
- iss-2610161015381750Lanes parked at land are renewed on every drain move from local state alone, whatever their pull request's state, and a lane whose head is not on main is skipped silently, so a pull request closed, dropped from the merge queue or conflicting after arming keeps its issue reserved and counted against the cap indefinitely and next never names it.related itd-2610161016391855
- iss-2610161015387318The host judgement is asked before the issue's reservation is checked, and an issue another account holds is retried on every move with a full check (plan, sibling worktree scan, fetch), so several drains all judge and retry the same head of the queue, since every drain takes the same order (category, severity, oldest).related itd-2610161016394967
- iss-2610161015393523A drain's in-progress lane is renewed only when its own step or receipt runs, so if the host pauses the lane for more than the two-hour default lease another account takes the reservation over five minutes after expiry and works the same issue; the land fence runs only at arming, after the push and the pull request, so the duplicate becomes a public pull request.related itd-2610161016394967
- iss-2610161015397586One unreadable sibling worktree makes the peers check fail for every issue, so a drain judges each issue, passes it over as contended, and ends with nothing eligible left; the primary checkout carries 108 worktrees, 46 locked by another tool.related itd-2610161016394967
- iss-2610161015400509Reservations are made only on the remote named origin, and nothing checks that origin is the repository pull requests target, so an account whose origin is a fork reserves on the fork, invisibly to every other account, and works issues others hold.related itd-2610161016394967
- iss-2610161015410527Drain lanes never merge the default branch before their pull request, and the footprint taken from found_at never names generated files, so lanes from several accounts conflict on generated files: of 259 merges to main since 2026-10-01, 54 touched docs/reference/cli/commands.md, 29 surface.json and 18 the brief's surfaces README.related itd-2610161016391855
- iss-2610161015417715A drain's --pace and --sub-agents reach only the lane opened in its first move; later lanes resolve their pace again from configuration, so the old drain's first lane ran 10080/0 with six sub-agents and its next ran 120/300 with two.related itd-2610161016401115
- iss-2610161015422306The drain's host judgement has no route to a command-line model, so an unattended drain needs a host agent looping; in a plain terminal a person writes the JSON answer, sha256 digest included, by hand; and a hosted session that restarts loses .abcd/.work.local, so its new copy key reads its own reservations as another copy's and the advice names --take-over, which drain does not accept.related itd-2610161016401115
- iss-2610161015422836Issues passed over because other accounts hold them still let a drain stop as empty with complete true, so the next abcd drain begins a new drain with no stored judgements and judges everything again.related itd-2610161016394967
- iss-2610161015433495With a git email that is not a GitHub noreply address, every reservation act calls gh api user again, uncached.related itd-2610161016401115
- iss-2610161015434746abcd peers shows each account's reservations but nothing of a drain lane's stage, its judgements or its hand-backs, so one person cannot see what another account's drain is doing.related itd-2610161016401115
- iss-2610161015448977A failed fetch from origin refuses the drain move instead of entering the drain's outage wait.related itd-2610161016401115
- iss-2610161015457468A resumed drain keeps what it began with for its whole life: its stored pace and sub-agents cannot be changed (--pace is refused while it runs), the issues it handed back stay excluded until it ends, and an issue with an old handed-back run is passed over with 'drive or finish that run' for as long as that run directory exists.related itd-2610161016401115
- iss-2610161125115941hooks/session-start.sh runs the session-start entrypoint even when hooks/bootstrap.sh failed but a plugin binary is present, then exits with bootstrap's non-zero code: the host shows its empty 'startup hook error' banner and drops the notices the entrypoint just printed, the outcome iss-2608241115201044 fixed for the entrypoint's own exit.
- iss-2610161125118921The comment above the session-start hook in internal/surface/cli/cli.go (around lines 2006-2015) still says the loud path deliberately exits 2, while the code below it exits 0 on every path and a later comment says so (iss-2608241115201044).
- iss-2610161127265652Six record-family patterns in the lint and site packages keep their own hand-written copy of the cited families (adr, itd, iss, spc, dcn) instead of reading recordid.CitedFamilies: claimedHandleRe in internal/core/lint/crossstore.go:57, proseCitationRe in internal/core/lint/prosecitations.go:138, recordHandleRe and recordHandleFullRe in internal/core/lint/schema.go:60 and :62, the recordHandleKinds message in internal/core/lint/schema.go:73, and bodyHandleRe in internal/core/site/recordjson.go:34. Each includes dcn today, but each is a copy the next family added to recordid's list would miss, which is how the inbox rewrite and four refusal messages came to omit dcn (iss-2610160608389169, iss-2610160608457651).
- iss-2610161207130167A deadline-bound stored git read (gitutil.RunCappedBytesAsStoredContext, which the status reader's walk and batch reads use) first runs the object-read guard's git version probe and, on a git older than 2.44, a git config read, both outside the caller's context: with a git that does not answer, a read given 300 ms returned after 20 s. The prompt hook still answers inside its budget, since PromptNotes selects on the deadline, but the reading goroutine outlives it and the function's contract that git is killed when the context ends does not hold for those two commands.
- iss-2610161332024554The brief session page puts technical setup in front of a product thinker before they can see the brief: its first screen asks for a relay address (a term the page never explains), then for a GitHub personal access token, and the brief appears only after hosting and picking a file. Tested by the product thinker on the hosted-sites draft, who could not tell what the page was for or what to enter. A person who only wants to work on the brief should arrive with the relay already chosen and sign in with one GitHub button.
- iss-2610161332060895The user-scope inventory in 03-configuration.md omits interviews/ (setup answers that change the machine) and backups/ (harness settings copies the status line takes), which 01-ahoy's tree lists, though the chapter says the two are one list and must agree.
- iss-2610161332064271Both user-scope inventories (03-configuration.md and 01-ahoy's tree) omit files abcd reads or writes under ~/.abcd.noindex: ideas/<root-sha>/ (private ideate verdicts, internal/core/ideate), sessions/names.json (the session-name register, internal/core/sessionname/register.go), filter-roots (internal/gitutil/status.go), load-wait.json (internal/core/implement/load_wait.go) and dashboard/ (run.json, seen.json, control.lock; internal/surface/dashboard/control.go).
- iss-261016133207947401-ahoy's user-scope tree marks worktrees/<root-sha>/<name>/ NOT BUILT, but the build loop creates each lane's worktree there today (internal/core/implement/loop/lane.go, WorktreeStoreRel) and ahoy inspects the store (internal/core/ahoy/store_worktrees.go); only the store's verbs and reclaim are unbuilt, as 03-configuration.md's worktree-store section says.
- iss-2610161411407429The auto-release detect step's error message does not say what to do when re-running the release fails the same way again.
- iss-2610161411584562The managed bare+semantic release profile keeps the tag-push trigger but has no pushed-tag job, so a hand-pushed tag signs the receipts and then fails its own pin to the default branch ref.
- iss-2610161411593211The auto-release detect guard that runs gh run list --event push can no longer fire, because verify is always skipped on tag runs; its header comment describes the old behaviour.
- iss-2610161411595610Releases signed before the release-chain fix carry a tag-ref signing identity, so the new pinned provenance checks and the emergency redeploy refuse them; the release runbook does not say so.
- iss-2610161444081367A local brief session's relay (abcd session start) refuses any request whose Host header is not the computer's tailnet name or its loopback address, with 421. Which Host header Tailscale Serve passes to the loopback backend was not verified on a live tailnet (the build sandbox could not run the tailscale command), so if Serve sends a form the allowlist does not name, every request through Serve is refused and the session cannot be reached.
- iss-2610161444092883The reworked brief session page was not proven end to end against real GitHub: no device-flow or web-flow sign-in, hosting, joining, editing or sending back ran in a browser, because the build sandbox reached neither github.com's sign-in endpoints nor a real GitHub App. Headless screenshots of the start screens on loopback and Go tests against a fake GitHub are the only evidence.
- iss-2610161457198410The rules package's load-idiom test fails with exit status 3 and an empty stderr when pgrep runs but cannot read the process list. After the 2026-10-16 screen-server restart, every session started before it got 'pgrep: Cannot get process list' (sysmond unreachable). The test only checks that pgrep is on PATH, then waits ten seconds for two processes pgrep can never see, so make preflight failed with no reason given.
- iss-2610161457209287A person's reservations do not say which of their sessions or checkouts holds them. Several sessions run under one account, and every hold reads holder <the product thinker's login> with an opaque copy key. On 2026-10-16 two live intent holds (the messaging and cloud-sessions intents) sat at the ten-reservation cap while no session could tell whose they were. Two peers had to ask each other in turn before one was released.
- iss-2610161457307727After the 2026-10-16 crash the person could not tell which terminal tab held which session. Sessions message each other by the host's peer names (abcd-22, abcd-2c), but those names show nowhere a person can see. Every resume and every reboot gave each session a new peer name (abcd-22 became abcd-b4, then abcd-a2). Matching each tab to its work took a round of messages to every session, and closing the old copies had to be done by process id.
- iss-2610161457311626Two live processes can run one session transcript at once, and nothing warns either. On 2026-10-16 the person resumed sessions in new tabs while the old processes were still alive, so seven pairs, one per session, briefly shared a transcript. Each copy could have dispatched agents, committed or pushed as the other, and only a cross-session message caught it.
- iss-2610161458426987A cloud hand-back run again within the same second, saying the same things, writes a report identical to the one already committed, because finished_at counts whole seconds and nothing else in the report changes. git commit then has nothing to commit, and hand-back says git or a commit hook refused the commit and falls back to the tracking issue. The merge queue hit this in TestHandBackPushesToWIPBranchThroughTheHook on a fast Linux runner; the test now pins the clock and makes the second report differ, but the script's message still misnames the cause.
- iss-2610161458469092TestHandBackPushesToWIPBranchThroughTheHook missed its first push twice in three runs while the machine's load was about 128 just after a reboot: origin held nothing on the work-in-progress branch. The test printed none of hand-back's output then, so the cause is unknown; 31 later runs at load 20 to 50 passed. The test now prints hand-back's output when that push misses, so a recurrence shows its cause.
- iss-2610161501104088Nothing tells an agent that the host's scratch folder is wiped on reboot. The host hands each session a scratchpad under /private/tmp and asks it to keep temporary files there. Agents keep everything there, scripts reused across sessions and turns included. On 2026-10-16 a reboot wiped it, taking the preflight queue script, the PR watcher, PR text files and every frozen review copy. The bundled rules send runtime output to .abcd/.work.local/ and verifier copies under ~/.abcd.noindex/, but none says that the host's scratchpad does not survive a reboot or a new session.
- iss-2610161535126075adr-2610161400542916 still lists the shared abcd-owned GitHub App as a product decision put back to the product thinker, though the product thinker ruled on 2026-10-16 that each team registers its own app (itd-2610091016262335 Decisions)
- iss-2610161535233301abcd lint reports privacy-hygiene errors for the tailnet test addresses (100.64.0.0/10, shared address space, not a documentation range) in internal/surface/session/server_test.go and internal/surface/cli/session_surface_test.go, as it does in the tailscale adapter's tests
- iss-2610161555125041After the 2026-10-16 reboot, with machine load near 160, abcd's UserPromptSubmit hook ran past the host's 120-second timeout. The host discarded its output, so that prompt got no rules, no status block and no memory recall, and nothing said which part was slow. The hook execs abcd hook prompt-router once the binary is present. The router's own stages are each bounded (the status read at 600 ms, the root-commit lookup at 2 s), but nothing bounds the router as a whole.
- iss-2610161555138660Every abcd hook shows the status message 'abcd: checking the plugin binary; a first run downloads it, so this can take a while', even when the binary is already installed and the hook only runs the prompt router. When the router timed out on 2026-10-16, that message pointed the person at a download that was not happening.
- iss-2610161612200864Agents stall at the host's permission prompt when they write a command the host cannot check. On 2026-10-16 a background agent ran a bash -c script built from variables that deleted files. The host could not check it, so it asked 'This shell -c script runs rm and could not be checked. Do you want to proceed?', and the agent waited for a person. No bundled rule teaches the forms the host can check.
- iss-2610161612203555An agent abcd starts without a terminal has nobody to answer the host's permission prompts. A command the host cannot check is then refused, and the lane stalls or fails. The product thinker chose to have abcd answer those prompts for the agents it starts, using its existing guard rules.
- iss-2610161614039496An agent wrote its own preflight queue script although abcd's waiter already did that. The script lived in the host scratchpad, a reboot wiped it, and its queued runs never started. No bundled rule tells agents to use abcd's commands before writing helpers.
- iss-2610161629014256The ahoy version.upgrade gap compares the setup version and the running binary as plain strings, so a plugin older than the repository's recorded setup version is reported as an upgrade, and running setup would then record the older version.
- iss-2610161632245527abcd should find out what the forge can do instead of asking the person or assuming. On 2026-10-16, setting up a throwaway lab to test abcd land, the agent asked the product thinker whether the team organisation allowed private copies; the product thinker did not know and should not have to. A read-only query answered it (members_can_fork_private_repositories is false for the organisation's own repositories), and a real attempt showed a private fork of a repository the person owns works anyway. The general want: abcd tests the forge's functionality itself (can repositories be private, can they be forked privately, is a merge queue available) and goes with the route that delivers the wanted outcome; only when no route exists does it ask, offering the options. Likely an intent; it needs a state-of-the-art pass on forge capability detection.related itd-2610161647248332
- iss-2610161634043273The load gate's queue orders waiters by pid, so a waiter with a high pid starves once the machine's process ids wrap. machineload.QueueAhead counts another waiter as ahead when its pid is lower than this one's. After a reboot on 2026-10-16 the ids wrapped: waiters started between 16:07 and 17:26, with pids 50460 to 71218, all queued ahead of one started at 16:04 with pid 96274. That waiter could only wait out its timeout while lower pids kept arriving. The docs and the LOAD rule promise one waiter at a time in queue order.related itd-2610170634394993
- iss-2610161639025702Preflight throughput sets the pace of all work on this machine, and nothing keeps it in bounds. On 2026-10-16 the load gate admitted one make preflight at a time, each took about 40 minutes, and about 20 waiters were queued across seven sessions. Every reviewed branch had its own preflight, so a seven-step feature needed seven full runs, and records-only branches paid the same full cost as code. Sessions waited hours, and the queue's ordering after the reboot starved late waiters (fixed separately on fix/load-queue-start-order). No rule tells sessions to batch work, and no part of preflight scales its cost to what a change touches.related itd-2610170634394993
- iss-2610161645224876The messaging press release promises that a colleague's session sees an announcement such as 'merging the login fix' before the session that made it pushes. The build guarantees it only before the work merges into the main line, at the land step. The product thinker chose on 2026-10-16 to make the build keep the promise rather than reword it.
- iss-2610161652341096A drain opens one lane per issue, even when several eligible issues touch the same files. Each lane pays its own branch, review, preflight and pull request, and the lanes then contend for the same footprint, so issues in one file are fixed one after another, each waiting on the last one's merge. The product thinker asked on 2026-10-16 that a drain bundle the issues that touch the same files and fix them in one go.blocks iss-2610161653005769
- iss-2610161653005769When a feature's build changes files that open issues also name, those issues stay open until a separate drain lane gets to them, even though the build has the files open, reviewed and tested at that moment. The product thinker suggested on 2026-10-16 that a feature's build trigger the drain on its own files, so that every eligible issue in the code the feature touches is fixed while the feature is being built and tested.blocked by iss-2610161652341096
- iss-2610161655393137abcd's own drain rule (adr-2609291342092738) holds abcd at the strict baseline, taking nitpick and minor and handing every security issue back, and a test pins it there, so urgent fixes that need no decision wait for a person. The product thinker ruled on 2026-10-16 that abcd's own repository takes every severity and security, most urgent first.
- iss-2610161709506207The opencode runner stamps the model it was asked for as the model that answered: internal/core/runner/opencode.go:85 sets ans.Model = o.model after parsing, so the route receipt's model field can never differ from the request, and a run routed through opencode to OpenRouter or a local server cannot show that a different model, provider or fallback served it.related itd-166 · related itd-2610161733316518
- iss-2610161732283346abcd should warn when the machine's forge login, or the team's settings, hand agents more power than abcd needs. On 2026-10-16 the product thinker found, only by asking, that this machine's gh login carried admin:org (change the team organisation's settings, members and roles) and that the organisation let members delete repositories. abcd never calls the organisation API, so it needs neither. The product thinker turned member deletion off in the web UI, chose to remove admin:org, and ruled that team settings change only through the website, never through the command line. abcd's install and health checks should surface these risks unprompted, read-only, and leave the change to the person in the browser. Related: itd-2610161647248332 (abcd finds out what the forge can do).
- iss-2610161734179773During an interview the orchestrating agent tells the person about the question drafter's internal round trips: the drafter refused a draft for running one row over the 24-row limit, and the agent narrated that refusal, its reasoning, and the redraft it was resuming. The person does not need any of it. Only the finished question should reach them; a refused or redrafted question is the agent's own business.
- iss-2610161734413178abcd cannot hold an OpenRouter call to one named upstream provider, and it records only part of what served it.related itd-2610161733316518
- iss-2610161734428291No local model can be pinned for a tool-using build role. Nothing records the weight file's sha256 or Hugging Face revision, the quantisation, the runtime and its version, or the served context length, and the known traps go unchecked:related itd-2610161733316518
- iss-2610161739587645During interviews abcd asks the product thinker and the technical facilitator questions that have one clearly best answer. On 2026-10-16 the product thinker said to ask only where there is a clear trade-off, or several equally valid options. The GRILL rule already says a decision with one defensible answer is recorded, not asked. But the planning interview's own steps in commands/intent.md tell the host to confirm the press release, ask for the mechanism claim, the scope conditions and the grounds, and walk every acceptance criterion one question at a time, so a host following the page asks single-answer questions by design. The question-drafter agent drafts whatever it is handed and does not push back when only one answer is defensible.
- iss-2610161756384596abcd's load gate admits a fixed number of preflights, one, whatever the machine can carry. The product thinker asked on 2026-10-16 that abcd know how many concurrent preflights, race runs and sub-agents are feasible from the resources it actually has, instead of a number a person sets and re-sets by hand (the machine-wide cap moved six times in two weeks: six, eight, ten, twelve, ten, fourteen).
- iss-2610161801358637A runner takes one model per machine, so a model matrix cannot be configured: internal/core/runner/config.go keeps a single Model per enabled runner, readable only from the machine layer, and roles name runners rather than models. Building one intent with several opencode-served models, or reviewing it with several runner-served reviewers, would mean rewriting the person's machine file between copies, and two copies could never run at once. itd-2610161733316518 needs it.related itd-2610161733316518
- iss-2610161806164689On macOS 27.0.1 Spotlight still catalogues every file under abcd's home by name, although the .noindex name keeps it from reading their contents, so the shipped claim of itd-2610030720038073 that Spotlight skips the home holds only in part. On 2026-10-16, after a reboot at about 15:45, mdfind -onlyin ~/.abcd.noindex returned 589,828 entries, 199,371 of them changed that day: lab copies (21,393 in one lab made at 10:04), worktrees, transcripts, scratch and a clone's git objects. A content search for a word that appears in each of the 208 AGENTS.md copies there found none of them, while the same search found the word in a checkout outside the home, so contents are not imported. Each new file still costs the catalogue a little work, which is far less than a content import, but a lab or worktree copy creates tens of thousands at once. The intent's scope condition names macOS 27.0 with a dated receipt and says each later version holds the claim only once its own receipt is dated; 27.0.1 has none, and the receipt that exists measured indexer CPU, not what the index holds.
- iss-2610161815513446The shell-c-variable-delete refusal does not read an eval string inside a bash -c or sh -c script as a script of its own, so a delete whose target a variable decides, written through eval inside the -c string, passes the guard and the host still stops to ask a person before it runs.
- iss-2610161815523252A find command whose -exec runs sh -c or bash -c with a delete a variable decides gets only the unrecognised-launcher warning, not the shell-c-variable-delete refusal, so the agent is not handed the rewrite and the host still stops to ask.
- iss-2610161815530723Inside a bash -c or sh -c script, find with -delete on a path a variable decides is not refused by shell-c-variable-delete, because find is not among the deleting commands the refusal reads.
- iss-2610161815541336A variable inside an unquoted here-document within a bash -c or sh -c script is not counted when the shell-c-variable-delete refusal decides whether a variable chooses what the script deletes.
- iss-2610161821254457Inside a bash -c or sh -c script, a delete that reads its names from a file redirected into it (xargs with a delete command and stdin from a file an earlier variable-built command wrote) is not refused by shell-c-variable-delete, because only a pipe or a here-document counts as feeding the delete; the host still stops to ask before such a script runs.
- iss-2610161831078335abcd land refuses when the checkout's local origin/HEAD is stale or missing and tells the person to run git fetch and git remote set-head themselves (land.go, the forge-default check), though abcd can settle the gap by asking origin which branch is its default. The product thinker has ruled twice against a refusal that hands a person a manual step abcd can resolve itself (adr-2609301720596683, adr-2610030720195401). The refusal for the branch being the default also appends a set-head hint that has nothing to do with that case. Found by a peer session and confirmed on main, 2026-10-16.
- iss-2610161839527371Each prompt reads every kept status announcement to decide what to show, at about 0.17 ms per announcement, so at the 2,000-announcement keep cap the prompt hook spends about 340 ms of its one-second budget on this read alone (measured in the messaging step 3 fix round, 2026-10-16).
- iss-2610161849042422gitutil.RemoteHeadBranch runs git ls-remote through gitutil.Net directly rather than through abcd land's Options.Git seam, so landing tests cannot record the call or fake an answer: they need a real local bare origin for every case, and the unreachable-origin and malformed-answer cases are reached only by building such a repository. Found by the Opus reviewer of the origin/HEAD fix (iss-2610161831078335), 2026-10-16.
- iss-2610161904304682On a 320 px phone, the Shared design's toolbar for a guest overlaps: the Documents and Your suggestions buttons collide. 390 px is fine.
- iss-2610161904308800When the session roster changes, the invite card's contents are rebuilt, so a focused button inside the open invite card loses keyboard focus.
- iss-2610161904318905In the Guided design on a phone, opening a bottom sheet (documents, suggestions, people, invite) does not move keyboard focus into the sheet, unlike the Send, invite and trust dialogs.
- iss-2610161904322876The session page hides the editor's gutter, so on Windows and Linux, where Ctrl+Shift+[ and ] now switch the page's design, there is no way left to fold a section of the brief.
- iss-2610161925418114An agent builder for repositories abcd manages: some of them need customised agents to do their work, for example for deployment or documentation, and abcd offers no guided way to define, check and keep such repository-specific agents alongside the ones it bundles.
- iss-2610161928115039abcdesign.app hosts more than brief editing: the product thinker's direction (2026-10-16) is that its sessions become the place a team does design work together, with brief editing as the first kind, judging blinded model copies as the second (itd-2610161733316518), and later kinds such as comparing design mocks two at a time. Its record and first-release scope today cover the brief only, so each new kind would otherwise be designed alone.blocks iss-2610161935066063 · related itd-2610161733316518
- iss-2610161928560772When an app pushed the tip of a status branch, the forge's activity record never names that push, because the pusher check passes over app actors; so every status fetch asks the forge about that branch again and shows the line that the record does not yet name the tip.
- iss-2610161928572852If a crash keeps a status branch's read mark but loses one of the seen files written beside it (they are written without a flush), the commit that file stood for is never read again, because the next walk starts past the mark.
- iss-2610161928586752The branches_left_to_read count that abcd status reports when an intake leaves branches unread has a test in the claim package but none at the command line, so its JSON field and text line are not held at the surface.
- iss-2610161930038953The headless approver reads the command line it is asked about, not the writes of a script that line runs: a script the approver lets run is read for the registry's hazards only, so a file the script writes, a protected one included, is not checked by the approver. The OS sandbox for launched agents, spc-2610161751056096, is the change that bounds those writes. <!-- record-lint: forward-looking -->
- iss-2610161930104545A command that writes into a directory (tar -x, unzip -d, cp -r, git apply, git checkout) is judged by the headless approver by the directory it writes into, not by the files that land inside it, so a protected file arriving inside that directory is not checked. The OS sandbox for launched agents, spc-2610161751056096, is the change that bounds those writes. <!-- record-lint: forward-looking -->
- iss-2610161930115246The file tools a headless role is granted (the --allowedTools list of the claude launch, internal/core/runner/claude.go) write files without asking the approver, so the approver's protected set does not cover what those tools write. The OS sandbox for launched agents, spc-2610161751056096, is the change that bounds those writes. <!-- record-lint: forward-looking -->
- iss-2610161934500065An optional abcd theme for Claude Code, offered during ahoy install: a custom theme that renders, for example, indented text in responses in an even lighter grey, so abcd's own output reads distinctly. A theme would be written into the host's own settings, which the product thinker's 2026-10-05 ruling reserves to the consented status line alone, so it needs the same explicit opt-in.
- iss-2610161935066063Product thinkers have no shared place to discuss, review and approve intents together: a draft intent is read and signed off by one product thinker in a planning interview at a terminal, so a team of product thinkers cannot comment on a draft, see each other's views, or record a joint approval before it is planned.blocked by iss-2610161928115039
- iss-2610161938458308An intent cannot say that it ships after another without being blocked from building: blocked_by makes abcd build refuse every step until the named intent ships (startBlockedRow in internal/core/intent/startcheck.go), and builds_on says nothing about order, so an intent whose one step needs another's capability (the model-matrix run's judging step needs abcdesign.app's session) has no edge that holds its shipping and frees its other steps.related itd-2610161733316518
- iss-2610161947572570Every repository abcd manages should carry an enforced single-source-of-truth rule: each fact has one canonical home, and every other place it appears is generated from that home and checked, never hand-copied. Today abcd holds pieces of this for itself (the Markdown-is-the-source rule in the bundled documentation domain, its own one-canonical-primitive principle, generated blocks with drift checks), but a managed repository gets no stated rule and no gate that catches a hand-edited copy drifting from its source.
- iss-2610162027075062The agent-launch entries in the guard's registry recognise a harness by its program name, by the package that ships it, and behind the launchers the registry steps, so a harness binary copied or linked under another name and started by that name is not recognised as a harness at this layer; the OS sandbox for launched agents, spc-2610161751056096, is what bounds what such a run can reach. <!-- record-lint: forward-looking -->
- iss-2610162030024268hand-back.sh decides whether the committed pre-push hook refused a push with printf of the push output piped into grep -q '^pre-push:', under set -o pipefail. grep -q stops reading at its first match, so when the output runs to many lines past the pipe's buffer after that line, printf is killed by SIGPIPE, pipefail fails the condition, and the report's reason drops the words saying the hook refused it. A reproduction with 400KB of multi-line output missed five times in five; ordinary push output is far smaller, so no test drives it yet.
- iss-2610162306239284The load gate's stand-back window (the open pause plus the start tolerance) is measured from the look, not from the waiter's own re-check read, so a waiter whose path from that read to starting its mark is slow under load (about 2.5 s) discards a concurrent lower-pid opener it did see, and both run their commands, which can bring back two preflights each waiting on the other's running waiter; no test pins the window's bound.related itd-2610170634394993
- iss-2610170212055447The brief intent chapter at .abcd/development/brief/04-surfaces/05-intent.md:271-272, :318 and :544 says nothing runs the intent-auditor on its own. But a spec close that ships an intent runs the auditor itself and ingests its verdict when the auditor's route reaches a provider connection (internal/surface/cli/route.go:301-306), and a build run audits on the lane whose landing closes the intent's last open spec (internal/core/implement/loop/validate.go:220-229).
- iss-2610170212063646The brief verification matrix at .abcd/development/brief/06-delivery/02-verification-matrix.md:56 says running the intent-auditor automatically is deferred. A spec close that ships an intent runs the auditor itself when the auditor's route reaches a provider connection (internal/surface/cli/route.go:301-306), and a build run audits on the lane whose landing closes the intent's last open spec (internal/core/implement/loop/validate.go:220-229).
- iss-2610170220118643TestHandBackScrubLeavesNoDomain failed once on the merge queue's macOS race run (Actions run 38991791855, 2026-10-17T02:10Z) for a docs-only pull request: the comment's 'Why the push failed' section carried the pre-push hook's refusal but no 'remote:' line, so the test stopped at cloud_handback_test.go:754 before checking the scrub. The same package's TestHandBackPushesToWIPBranchThroughTheHook has a recorded load-related miss (iss-2610161458469092); this is a second hand-back test whose push output arrives incomplete.
- iss-2610170309575029The glossary term .abcd/development/brief/glossary/interview/session.md defines a session as an exchange with the abcd grill sub-verb, started when a person invokes /abcd:intent grill (lines 4-9), but abcd intent --help lists no grill sub-verb and the glossary README now calls it a design target, not shipped.
- iss-2610170309579031The glossary term .abcd/development/brief/glossary/interview/embark.md describes the opening phase of a grill session that a person starts by invoking /abcd:intent grill (lines 4-32), but abcd intent --help lists no grill sub-verb and the glossary README now calls it a design target, not shipped.
- iss-2610170309583748The glossary term .abcd/development/brief/glossary/core/persona.md gives a usage example of a persona using /abcd:intent grill before every plan submission (lines 36-37, where a quoted product lead also credits the grill), but abcd intent --help lists no grill sub-verb and the glossary README now calls it a design target, not shipped.
- iss-2610170309585684The glossary term .abcd/development/brief/glossary/core/intent.md gives /abcd:intent grill itd-27 as a working usage example (lines 37-38), but abcd intent --help lists no grill sub-verb, itd-27 was superseded by itd-94, and the glossary README now calls the grill a design target.
- iss-2610170454064770The brief surface index's Bare invocation list (.abcd/development/brief/04-surfaces/README.md, section Bare invocation) names the verbs whose bare call refuses or acts instead of rendering, but bare abcd hook prints its usage only and is in neither that list nor the bare-render exception table (internal/surface/cli/barerender.go). hook is hidden and operator-internal, and the list never says hidden verbs are left out.
- iss-2610170507498232The comment on voyageEntry at internal/core/lifeboat/voyage.go:27-31 says the full file list lives in the lifeboat's own _provenance.json, pinned by the manifest hash. The Provenance struct (internal/core/lifeboat/plan.go:66-86) holds no file list: the list is the lifeboat's own tree, which verifyManifest (internal/core/lifeboat/embark.go:181-235) walks and re-hashes against manifest_sha256. The wrong comment was copied into the brief's naming register during PR8 review.
- iss-2610170619247185An agent session told to work autonomously overnight sat idle for about ten of the eleven and a half hours between 20:48 BST on 2026-10-16 and 07:13 BST on 2026-10-17, while it held owed work it could have done alone.related itd-2610170638184486 · related itd-2610180912189125
- iss-2610170635209097The cloud launch connector reads the host's JSON answer one line at a time when it looks for "is_error": true, so an answer that exits 0 and spreads that pair over two lines, as pretty-printed JSON does, is read as a started session; a refused start could then be reported as started.
- iss-2610170657019661A message addressed to the product thinker, a question above all, still carries mechanism details (file names, flags, internal terms, how the code does it) where the product thinker needs only the choice and what each answer leads to, in plain words. Questions put to the product thinker must always be simplified: cut the mechanism and state the decision by its outcomes.
- iss-2610170711334760The per-session checklist that autonomous sessions keep on disk (the draft intent "Every session keeps a checklist on disk", on branch chore/capture-agent-builder and not yet on main) must survive a crash: a session killed mid-write, a host or terminal restart, or a machine reboot must leave the last complete checklist readable and re-injected on the next start, never a truncated or half-written file and never an empty one. The design states this; nothing yet shows it holds. The product thinker requires a state-of-the-art pass and a lab before the claim is confirmed.
- iss-2610170713227840abcd has no established procedure for design work, so each visual design question is run from memory. Three times now the same process has been rebuilt by hand: the control-panel lab in another managed repository, the brief session page for abcdesign.app (lab-261016142621-a46cdaa, three rounds), and the phone and tablet answer screen (lab-261017071130-6fd3032). The process: a written round brief with hard rules (self-contained HTML, mock data, light and dark, both device sizes, a mock-only screen switcher, URL-selectable screens); five distinct directions from one agent; a render script that screenshots each screen with headless Chromium; a gallery page opened for the product thinker; the product thinker's pick; five variations of the pick; and a pairwise comparison tool whose export is the evidence. Each time the brief, the render script, the gallery and the tool were copied from the previous lab by hand, and the first lab also showed the product thinker can choose without the pairwise step, so that step's place is still open. The product thinker asked on 2026-10-17 for this to become an established procedure.related itd-2610171228577260
- iss-2610170717491755An idea judged private with abcd ideate cannot later be made public: the verb has only record, which writes once to the store chosen, so moving a private verdict into the repository means copying the file by hand, unchecked; and nothing lists a person's ideas with which are private and which public, since where a file sits is the only record of it.blocks iss-2610290730539347
- iss-2610170717501963Preflight runs on macOS only, so behaviour that differs on Linux reaches CI first: on 2026-10-16 and 17 three such failures cost a merge-queue round each: a test expecting git's wording for a broken .git file (Linux git prints '(null)'), a test argument over Linux's 128 KiB limit, and test fixtures committing in a bare repository with no git identity (macOS falls back to user@host, Linux refuses).
- iss-2610170717515674The reservation cap (MaxLive, 10, in internal/core/claim/crowd.go) counts every live reservation one person holds across all of their sessions and copies, so one person running seven sessions on one account hit it all night: a session's fix waited for slots, two drain issues went unreserved, and sessions released and re-took holds to make room.
- iss-2610170718356567An automated git call in an abcd-managed checkout raised a macOS keychain prompt asking the person for their github.com credentials, which confused them: nothing they had started asked for credentials. At 08:12:45 on 2026-10-17 the system log shows git-credential-osxkeychain (Homebrew git 2.52.0) asking for the github.com keychain item under the account all abcd sessions run as; the person denied it. Their own global git config sends github.com credentials to the gh helper and clears the keychain helper, so the call ran without that config (a temporary HOME, as tests set, or an isolated global config) while still reading the system gitconfig, which names osxkeychain. The likeliest source is a test run in a peer's worktree that reached https://github.com; the exact test is not yet confirmed. A person who learns to approve such prompts would hand a GitHub credential to a test or a background process.
- iss-2610170718526430The product thinker has no convenient way to file an issue, a new intent, an idea for the ideate gauntlet or a lab request away from a terminal, for example from a phone. The planned dashboard (itd-2610032150577708) lets them read the record on a phone and leave a note on a brief line, but not start any of these records, so a thought on the move waits until they are back at an agent session.
- iss-2610170725144804The live-reservation cap is fixed at ten per person (claim.MaxLive in internal/core/claim/crowd.go), counted by username across every session, laptop and cloud copy. A project with one maintainer running many parallel sessions under one GitHub identity hits it with no one else to protect: on 2026-10-17 all ten were held by the maintainer's own sessions, mostly finished work waiting to merge, and a new reserve was refused. The cap is right for abcd once several people share a project, but the maintainer cannot raise or lift it today.
- iss-2610170730017996TestMarkingAFloodShownFitsThePrompt in internal/core/claim fails on a loaded machine: at a load average of 15 to 20 the read and marking of 300 announcements took 281 to 536 ms, past its 500 ms bound or the prompt's deadline. It fails the same way on an untouched copy of origin/main at 998883ef0, so it is a wall-clock bound that depends on the machine's load, not a defect the code under test introduced.
- iss-2610170814081317With stacked branches, abcd land announces items that are already merged: after the parent branch lands by a squash or rebase merge, its original commits are not on origin's default branch, so land reads their Refs:, Resolves: and Delivers: trailers again when the child branch lands and posts merging for them, for example merging iss-1 for an issue already merged and resolved.
- iss-2610170833197571When origin's root .gitattributes cannot be read as a declaration (over 256 KiB, holding a NUL byte, or not a regular file), every reserve warns that generated files were not recognised, even when that file declares no linguist-generated at all, so a repository that never declared any generated file gets a warning on every reserve
- iss-2610170833428011Every reservation view with a live footprint re-reads and re-matches origin's whole tree against the root .gitattributes (the claim package's generated-file reader), about 0.3 s on a large tree (150,000 files) and at most about half a second by the matching budget, and nothing keeps the answer between views although it can change only when origin's default branch moves
- iss-2610170921271252Before its push, an issue lane re-fetches origin's default branch every time it arrives at its landing with no landing state, and whenever that branch has moved it merges it and sends the lane through a fresh validation round, with no limit. With the default branch moving every 30 to 60 minutes, a slow lane, whose validators take longer than that, can run round after round of validators and never reach its push.
- iss-2610170926295770A reservation made by hand lapses while its holder waits in abcd implement load --wait: nothing renews it, so a preflight queued behind the gate for longer than the lease leaves the record unreserved while its work is still in progress. On 2026-10-17 a cloud-scripts fix waited about two hours for its preflight, and both of its reservations lapsed for about an hour before the holder renewed them by hand; no one else took them, but any peer could have.
- iss-2610170926360632After every fallback to the tracking issue, the cloud hand-back's closing line says the push failed, so the report was posted as a comment, even where no push was tried: when no person's identity is set, when the report's path is a symlink, when the commit failed, when the committed hooks are not active, and when an unchanged report's commit carries another Assisted-by. The stderr line before it gives the real reason, but the closing line names the wrong one, and so does the heading the posted comment gives that reason, "Why the push failed".
- iss-2610170930394303Setup saves its four config values (visibility, docs_target, oracle_backend, scan_deep) all together or not at all, so when one of them was deferred with 'decide later' and another is answered, neither is written: the answer reaches the setup answers record but never .abcd/config.json. A full ahoy install does this today, and the new ahoy install --only-waiting inherits it, so an answer a person gives after an update can silently not take effect.
- iss-2610170934491794abcd ahoy connect runs its verification call before any provider block exists, so a server that refuses the usage-in-stream request (stream_options.include_usage, added by itd-166) fails setup, and the refusal names the stream_usage setting on a block the person can only add by hand.
- iss-2610170937296561The headless approver refuses a case statement whose pattern is a glob as program-name-unread: case "$1" in a) echo a;; *) echo other;; esac is refused, with or without the leading ( before each pattern, while the same statement with a plain pattern (b) in place of *) is approved. The guard reads the glob pattern after ;; as a command name it cannot fix, so an ordinary default branch cannot run headless.
- iss-2610170948520608In a drain, a lane opens on the reservation the drain took to ask its judgement and pushes nothing at its start, so the reservation names no lane stage, and peers see none for the lane until its first renewal, about half a lease later.
- iss-2610171043574168The routed drain judge cannot run for a checkout or temporary directory whose real path holds a parenthesis or a comma: the path-scoped Read and Edit grants and the checkout denies are refused by the runner's tool-name check, so every move hands the request to the host.
- iss-2610171047088861The drain's renewal keeps its own copies of when a reservation is half through its lease and of the term a renewal pushes (renewalDue and renewalTerm in internal/core/implement/loop/reservation.go), where claim's halfThrough and renewalTerm (unexported until something outside claim calls them) now hold the same two rules for the load gate's renewal: two copies of one rule can drift apart.
- iss-2610171047098960abcd implement load --wait renews the caller's reservations only while it waits: once the gate opens and the gated command runs, nothing renews them, so a make preflight that runs longer than half a two-hour lease can still let a reservation made by hand lapse before its push.
- iss-2610171105560765abcd's wait and timeout defaults are fixed numbers, while what they wait for grows with the project. The load gate gives up after 30 minutes by default and after 2 hours in preflight, and go test kills a package at 10 minutes unless told otherwise. On 2026-10-17 two preflights here lost hours to these limits without any check failing: one waited the full 2 hours at the gate and gave up, and another was killed when one package took about ten minutes on a loaded machine. As a managed project gets more packages, tests and concurrent sessions, every fixed default is outgrown in turn, and each time a person or session must notice it and raise it by hand.
- iss-2610171110154902A host approval prompt for a shell command stalls an autonomous run. The host asks the person to approve a command it cannot check (an unread script, a compound line), and with nobody at the terminal the run waits until someone returns. Auto-approving a repeat was considered and rejected: it lets any agent past every check by retrying, so the refusal is repeated every time instead and the agent is told how to rewrite the command.
- iss-2610171200535090A person cannot mark a hand-steered session as autonomous. The approval-prompt refusal turns on only while abcd's own build or drain runs, so a session the person tells to work alone and leaves still stalls on the host's approval prompts. The product thinker named a switch on the mode verb as the likely shape.
- iss-2610171200549757A command the guard cannot read is refused outright in an autonomous run, even where a sandbox would make running it safe. The guard already reads shell scripts a command runs, but not other interpreters' files or file text substituted into a command; the sandbox environment under way for autonomous agents would bound what such a command can touch.
- iss-2610171249310666In a hosted cloud session set up by abcd's setup script, abcd announce and abcd reserve cannot push: the pre-push hook refuses every push from a shallow clone, and hosted sessions start from a shallow clone. reservation_shape returns failure as soon as git rev-parse --is-shallow-repository is true, so an empty-tree status or reservation commit is asked for a make preflight receipt that a hosted session never has. Seen live on 2026-10-17: a claude.ai/code session ran abcd announce asking #1 and was refused until it ran git fetch --unshallow by hand (.git grew from 23 MB to 63 MB); the announcement then reached origin as an empty-tree commit on abcd-status/<login>. commands/announce.md says announce works from hosted sessions, and acceptance criterion 13 of the announcements intent needs it to.
- iss-2610171249334225In a hosted cloud session, git run as the normal user that abcd's cloud setup script creates (runuser -u abcd) cannot reach origin over HTTPS: the session's proxy CA bundle sits under /root, which that user cannot read, so every networked git command fails with a certificate error before anything is sent. Seen live on 2026-10-17 when a claude.ai/code session ran abcd announce; it got through only after the session pointed the CA variables at the system trust store, which already holds the same CA, for that one command. The setup script made the user, so abcd added this failure.
- iss-2610171250466572abcd embargo publish can never publish an advisory handled the way the security rule asks: its plan includes an advisory only when the advisory's record is resolved in the release, but the security rule keeps that record out of every committed tree until the advisory is published. On 2026-10-17 the plan for v0.15.0 left out an advisory whose fix had shipped in v0.15.0 with the reason that its record is not resolved there, and it was published by hand through the forge API instead, as the release-chain advisory was before it.
- iss-2610171250479046The embargo store never learns that an advisory was published outside abcd embargo publish: after a draft advisory was published on GitHub on 2026-10-17, abcd embargo intake and a fresh publish plan both left the store's state at draft, and abcd embargo check still refuses the advisory's id in text, so the record cannot be restored to the public ledger with the gates passing. commands/embargo.md says a plan records published_at for an advisory GitHub already reports published.
- iss-2610171545099084A runner pointed at a local model leaves the weight fingerprint, quantisation and runtime version out of its record entirely, where the provider adapter's loopback route lists them as not configured; the intent audit of itd-166 (ac-4) found it with the opencode runner on local/qwen3-coder. A runner cannot tell from its own output that a model is served locally, so the fix needs the local pin's notion of which providers are local.
- iss-2610171626272190The v0.15.1 release review found the brief at .abcd/development/brief/02-constraints/04-naming.md:49-51 out of step with the shipped code. It says: The namespace root refuses any positional that is not a record id, so `status` is not a registered command. In the code: `abcd status` is a registered top-level verb (root --help, Records group: 'List everyone's announcements, reservations and releases being cut'), with commands/status.md and .abcd/development/brief/04-surfaces/39-status.md.
- iss-2610171626280696The v0.15.1 release review found the brief at .abcd/development/brief/02-constraints/04-naming.md:54-59 out of step with the shipped code. It says: The remaining surfaces are exempt ... `banlist`, `build`, ... `statusline`, and `update`. They are registered here so the exemption is on the record (and line 9-10: an exemption is a decision rather than an omission). In the code: Six shipped top-level verbs appear nowhere in the naming register, neither as maritime nor as exempt: `announce`, `embargo`, `land`, `memory`, `reserve`, `status` (all in root --help --agent and commands/; documented in 04-surfaces/38-announce.md, 37-embargo.md, 38-land.md, 37-memory.md, 37-reserve.md, 39-status.md).
- iss-2610171626290714The v0.15.1 release review found the brief at .abcd/development/brief/04-surfaces/README.md:151 out of step with the shipped code. It says: The help-groups table places only `launch` in the people block's release group In the code: `abcd --help` lists both `embargo` and `launch` under Release:, and surface.json records `abcd embargo` with group `release`; embargo appears in no row of the table
- iss-2610171626291023The v0.15.1 release review found the brief at .abcd/development/brief/04-surfaces/08-abcd.md:232-259 out of step with the shipped code. It says: abcd peers' one network act is a fetch from origin of every abcd-reserved/ branch (pruned) and of the default branch, which updates the remote-tracking reservation branches and stamps when it ran; the listing is reservations, per-person li… In the code: abcd peers --help (and commands/peers.md:15-19) says the fetch also reads origin's release tags v* and writes them under refs/abcd/release-tags/, and the listing adds a line for each release being cut (a live rel-vX.Y.Z reservation). The fetch and refs are documented in 37-reserve.md:315, but this chapter's enumeratio…
- iss-2610171626303019The v0.15.1 release review found the brief at .abcd/development/brief/04-surfaces/08-abcd.md:523 out of step with the shipped code. It says: In the itd-20 design-target note: 'There is no alias routing either: `status` is refused and `help` prints the verb list'; line 590 adds 'Nothing routes them today'. In the code: `status` is a shipped top-level verb (bin/abcd-darwin-arm64 status --help: 'List everyone's announcements, reservations and releases being cut'), and the chapter itself says so at 'abcd status is its own verb' (39-status.md); it is not refused.
- iss-2610171626311681The v0.15.1 release review found the brief at .abcd/development/brief/04-surfaces/01-ahoy.md:516 out of step with the shipped code. It says: The ~/.abcd.noindex inventory 'is stated as a table under The two .abcd/ scopes in 05-internals/03-configuration.md; the two are one list and must agree.' In the code: 05-internals/03-configuration.md 'The two .abcd/ scopes' (line 596ff) states the user-scope inventory as a prose paragraph, not a table, and it omits two entries the 01-ahoy tree lists and the binary writes: interviews/ (internal/core/interview/interview.go homeRecordsLeaf) and backups/ (internal/core/ahoy/statusline_…
- iss-2610171626317765The v0.15.1 release review found the brief at .abcd/development/brief/04-surfaces/06-capture.md:396-432 out of step with the shipped code. It says: The frontmatter block 'per the issue-ledger schema in internal/core/issueschema' lists every field a record may carry; it has no finding_ref In the code: internal/core/issueschema/issueschema.go Known allow-list carries finding_ref (the consistency finding's cfk- key, written by the pass's filer); no brief chapter mentions it, only .abcd/work/issues/README.md:94
- iss-2610171626323993The v0.15.1 release review found the brief at .abcd/development/brief/04-surfaces/05-intent.md:412 (press-release template, ## Grounds comment) out of step with the shipped code. It says: Grounds is 'Required at the readiness gate for a press-release intent'. In the code: internal/core/intent/ready.go groundsCheck builds its row with Advisory: true, so a missing Grounds section never withholds readiness. The same page says so at line 317: 'the grounds row ... advisory and never withhold readiness'. Only bucket, acceptance_criteria, spec_link, spec_body and open_questions gate.
- iss-2610171626324658The v0.15.1 release review found the brief at .abcd/development/brief/04-surfaces/07-library.md:174-177 out of step with the shipped code. It says: How a scaffolded hook finds abcd, and whether it does so by default, is a ruling owed to the product thinker (iss-2609250834251447) In the code: iss-2609250834251447 is in .abcd/work/issues/resolved/ with a recorded ruling: `ahoy install --outbound-hook` opts in, never installed by default, finds abcd only through git config --local abcd.binary, and fails open with one warning; the chapter still presents the ruling as owed
- iss-2610171626336875The v0.15.1 release review found the brief at .abcd/development/brief/04-surfaces/16-lint.md:37-42 out of step with the shipped code. It says: The verbs that write stay under the docs, site and identity verbs (the citation baseline, the site render, the recording of the identity block), and 'No check runs under those verbs any more'. In the code: `abcd docs fidelity` is a shipped check under the docs verb ('Judge the brief against every shipped surface and the saved docs review'; 10-docs.md lists it as bucket gate), and `abcd identity render` prints every drifted surface's correction and writes nothing. The list of what stays under those verbs also leaves out …
- iss-2610171626344967The v0.15.1 release review found the brief at .abcd/development/brief/04-surfaces/37-memory.md:21 out of step with the shipped code. It says: `list` is a shipped sub-verb of /abcd:memory; the naming constraint (.abcd/development/brief/02-constraints/04-naming.md:90-94) forbids a plain unfiltered `<verb> list` at design time, a sub-verb having to do something the bare invocation … In the code: `abcd memory list` takes no flags and no argument ('refuses any argument') and lists every note in both layers unfiltered; neither 37-memory.md nor the bare-invocation enumeration in 04-surfaces/README.md records it as an exception to the rule.
- iss-2610171626347542The v0.15.1 release review found the brief at .abcd/development/brief/04-surfaces/37-reserve.md:84-93 out of step with the shipped code. It says: Each reservation commit's trailers name the record (Abcd-Reservation), holder, copy, footprint, lease (Abcd-Claimed-At, Abcd-Expires-At) and the Assisted-by label; a release adds Abcd-Released-At; a hand-back adds Abcd-Handed-Back and Abcd… In the code: A drain lane's renewal of the reservation also writes an Abcd-Stage trailer (internal/core/claim/stage.go keyStage, one of worktree|brief|implement|validate|land, validated by validateStage on read). The reserve chapter never names it; its only documented home is .abcd/development/brief/04-surfaces/08-abcd.md:241-242.
- iss-2610171626353212The v0.15.1 release review found the brief at .abcd/development/brief/04-surfaces/39-status.md:130 out of step with the shipped code. It says: Exits: exit 0 when the fetch succeeded or no origin; exit 1 when the fetch failed; exit 2 outside a git checkout or with an operand. In the code: internal/surface/cli/status.go also exits 1 when what was fetched could not be read (ReadStatus error) and in a checkout without its local tier (v.NoTier), and `abcd status --help` says so ('exit 1 when it failed, when what it fetched could not be read, or in a checkout without its local tier'). The brief omits both e…
- iss-2610171626356145The v0.15.1 release review found the brief at .abcd/development/brief/04-surfaces/39-status.md:28 out of step with the shipped code. It says: The verb fetches 'each status branch whose name is a GitHub username in lower case'; only a non-lower-case-username name is left unfetched. In the code: The binary fetches only the first 500 such branches (internal/core/claim/status.go maxStatusBranches = 500); branches past 500 are counted and not fetched, and their tracking copies deleted, as `abcd status --help` states. The brief never mentions the 500 cap.
- iss-2610171626364475The v0.15.1 release review found the brief at .abcd/development/brief/04-surfaces/39-status.md 'What it shows' out of step with the shipped code. It says: lists announcements, doubtful branches, then the reservations block and the grants line In the code: abcd status --help also reports a live drain lane's stage and each holder's hand-backs from the last day; JSON also carries unread_names, branches_not_read, branches_left_to_read, announcements_not_read, not_dropped, local_tier_missing, read_error that the doc's key list omits
- iss-2610171626370813The v0.15.1 release review found the brief at .abcd/development/brief/06-delivery/01-build-sequence.md:35-38 out of step with the shipped code. It says: Three further adapter packages stand outside the capability seams: openaiapi, hosting and tailscale In the code: internal/adapter/ holds four non-scanner, non-backend adapters: openaiapi, hosting, repoprompt (the RepoPrompt MCP reviewer route, itd-6) and tailscale (gitleaks being the scanner's external backend); 05-internals/02-adapters.md:34 and 04-universal-patterns.md:175 list repoprompt
- iss-2610171626374131The v0.15.1 release review found the brief at .abcd/development/brief/05-internals/01-agents.md:137 out of step with the shipped code. It says: The intent-auditor 'has three roles ... Each role has its own verb ... Only the first ships.' In the code: Two roles ship: the same chapter marks role 2 (`abcd intent consistency`) as '(shipped, itd-48)' at line 162, the binary registers `intent consistency`, and agents/intent-auditor.md declares Role 2 (cross-document). Only role 3 (`intent shape`) is unshipped.
- iss-2610171626380056The v0.15.1 release review found the brief at .abcd/development/brief/06-delivery/02-verification-matrix.md row 'Capture resolve' out of step with the shipped code. It says: 'the optional intent, spec, commit and release references write the structured provenance' In the code: abcd capture resolve --help has --intent, --spec, --commit and --shipped-in (a migration-only release stamp); there is no release-reference flag by that role, and --production-mode is undocumented in the row
- iss-2610171626389087The v0.15.1 release review found the brief at .abcd/development/brief/06-delivery/02-verification-matrix.md:100 out of step with the shipped code. It says: Reservation on a fork origin row: 'a plain reserve that renews, `--renew` and a release never ask the forge', naming `--renew` as a reservation flag. In the code: No `--renew` flag exists: `abcd reserve --help` lists only --footprint, --holder, --lease, --release, --take-over (a renewal is the same command run again from the same copy), and no non-test Go source registers or names `--renew`.
- iss-2610171626391435The v0.15.1 release review found at CHANGELOG.md:54-56,61: Four Fixed lines are written as fixes to behaviour no earlier release had. 'A status fetch reads an app's push ... no longer asked about again' (iss-2610161928560772) concerns `abcd status`, which did not exist at v0.15.0. The three cloud lines ('no longer reported as started', 'no longer reports a refused commit', and the author identity line) concern scripts/cloud, which `git ls-tree v0.15.0 -- scripts/cloud` shows did not exist then either. A reader infers the features shipped earlier. The 'no longer' wording also contradicts the section's own preamb…
- iss-2610171626398856The v0.15.1 release review found at CHANGELOG.md:19-72: INCOMPLETE (judgement call). The 0.15.1 section has no Added line for user-facing surfaces that are new since v0.15.0 and present in this binary. (1) `abcd status`, a top-level verb in `abcd --help` with a user-invocable commands/status.md (block: people); commands/status.md does not exist at v0.15.0. (2) `abcd announce` (commands/announce.md). Both come from the planned itd-2609151838312703 and its open spc-2610150728396006. (3) `abcd implement load --race-gate` and the `load.preflights` / ABCD_LOAD_PREFLIGHTS setting (internal/core/implement/load_slot…
- iss-2610171626406129The v0.15.1 release review found at commands/peers.md:72-108: INCOMPLETE. The payload list never names `release_holds`. The verb emits it (internal/surface/cli/peers.go:48, with the holdRow fields release, subject, holder, copy, effective_expiry, unreadable, own, unsighted and text at :99-109). `abcd peers --help` says it lists 'a line for each release being cut (a live rel-vX.Y.Z reservation, which holds every other session's merge until its tag is on origin)'. The changelog says '`abcd peers` shows the hold' and '`--json` release holds carry `own` and `unsighted`'. An agent following this page is never told to r…
- iss-2610171626416207The v0.15.1 release review found at commands/peers.md:78-80: STALE. The page says `released_by` is '`tombstone`, or `default-branch` when the record is already resolved...'. The code also emits `tag` (internal/core/claim/release.go:46, ReleasedByTag) for a release reservation whose tag vX.Y.Z is on origin, and commands/reserve.md documents it as '`released_by: tag`'. Fix: add `tag` (a release whose tag is on origin) to the list.
- iss-2610171626419054The v0.15.1 release review found at commands/launch.md:112-114,122-124; commands/reserve.md:82-85: INCOMPLETE. Both pages describe the release hold as binding the implement loop's land step only. launch.md says 'every other session's land step (an `implement step` arming a merge ...) refuses to arm' and 'The hold binds abcd's own land step'. reserve.md says 'an `implement step` at the land fence in any other copy ... exits 3'. In the code, `abcd land` is held too: internal/core/landing/releasehold.go:11-29 calls claim.FetchMergeHold. commands/land.md documents 'While a release is being cut, exit 3', and the changelog line names both 'the implement lo…
- iss-2610171626424230The v0.15.1 release review found at README.md:69; commands/announce.md: INCOMPLETE. The README says '`abcd status` needs git 2.29 or later, which reads a fetch's branches from its standard input (`git fetch --stdin`)'. `abcd announce` fetches the status branches by name through the same path: internal/core/claim/announce.go:95-96 sets ns.only and calls fetchWith, and remote.go:765-766 switches to `fetch --stdin` whenever a namespace has ns.only. So announce needs git 2.29 too once origin holds any status branch, and on an older git it refuses with an error that names 'the status fetch'. commands/announce.md does not mention…
- iss-2610171626433972The v0.15.1 release review found at commands/status.md:53-54: Change narration on a user-facing page: '`branch` is the full branch name, `abcd-status/maya` (it was `maya` before step 3's fix rounds)'. It narrates an internal build step of an unreleased spec; `abcd status` is new in this release, so no user ever saw `maya`. It breaks the present-tense rule, and docs-currency-lint misses it because the page is under commands/. Fix: delete the parenthesis.
- iss-2610171626439671The v0.15.1 release review found at commands/launch.md:115-116: The page is addressed to the person cutting the release and says '`/abcd:peers` shows "release vX.Y.Z being cut by @you: merges are held"'. Run from the cutting copy, peers renders Hold.Line(), which is 'you are cutting release vX.Y.Z from this copy: every other session's merges are held' (internal/core/claim/release.go:122-126; peers.go:470). The quoted line is what other copies see. commands/reserve.md:91-95 states both correctly. Fix: say that other sessions see the quoted line and this copy sees the 'you are cutting' line.
- iss-2610171803053186The check job's ubuntu leg needs 45 minutes since the drain bundle grew the implement loop package's race run past the 30-minute ceiling it had kept; the workflow names a faster suite as the remedy for a leg near its cap.
- iss-2610172133042562abcd recognises no generated file in a repository whose root .gitattributes has a byte outside ASCII anywhere, even in a comment line git ignores. abcd's own file has em dashes in its comments, so on abcd itself every reserve reports 'not recognised: generated files (.gitattributes on origin/main holds a byte outside ASCII)' and the shared CLI reference and surface manifest are never let through as shared.
- iss-2610172134259284The owed-drain row of the brief intent chapter at .abcd/development/brief/04-surfaces/05-intent.md says the drain form of the audit sub-verb runs no reviewer and that with no auditor available every entry stays owed. But when the auditor's route reaches a provider connection the drain sends its head's request there and ingests the verdict (internal/surface/cli/intent_drain.go:66-82), as the same chapter's 'An auditor routed to a provider runs there' passage already says, so the row contradicts both the code and its own chapter.
- iss-2610172148157726The release changelog composer writes a fix to a surface that did not exist at the anchor tag as a Fixed line saying the behaviour 'no longer' happens, so a release's notes describe a fix to something no earlier release had. v0.15.1's section has such lines for abcd status and the cloud scripts, all new since v0.15.0, because each record carries impact: fix and nothing ties an entry's section to whether its surface existed at the anchor.
- iss-2610172321064097The intent chapter's section 7 heading and opening paragraph (.abcd/development/brief/04-surfaces/05-intent.md, 'The intent-auditor agent (three roles, three verbs)') say the auditor owns three roles, each with its own verb, without saying which ship. Two do: the audit (role 1) and the consistency pass (role 2) are registered sub-verbs of the intent verb, while the shape role (role 3) has no registered verb and its own subsection calls its surface a later phase. A reader of the opening alone takes all three verbs as shipped.
- iss-2610172322209537The verification matrix's 'Surface discipline (sweep)' row (.abcd/development/brief/06-delivery/02-verification-matrix.md) lists the shipped sub-verbs that break the no-show/no-unfiltered-list rule as history show, inbox show, a plain history list and unfiltered banlist list, but leaves out memory list: the command tree registers it, and it takes no filter and no argument and lists every note in both layers, a plain unfiltered list beside a bare memory that already renders the counts.
- iss-2610180052110870A record declined in wontfix/ as a duplicate of an intent cannot be moved to resolved/ when that intent ships: capture resolve refuses it as already in wontfix, yet the issue-drift gate refuses a shipped intent whose related_issues name a wontfix record, so the only way through is a hand move of the record (done for iss-2608290811463906 when itd-166 shipped).
- iss-2610180149420731The glossary term .abcd/development/brief/glossary/core/lifeboat.md calls the interview-context embark 'the grill sub-verb term for the opening move' (lines 52-53), presenting the grill sub-verb as shipped, though abcd intent --help lists no grill sub-verb and the glossary README and the embark entry call the grill a design target.
- iss-2610180150052406The interview context's index .abcd/development/brief/glossary/interview/README.md says the context holds terms specific to 'the grill/interview sub-verb of /abcd:intent', with session and embark among them (lines 3-5), presenting the grill sub-verb as shipped and conflating it with the interview sub-verb, though abcd intent --help lists no grill sub-verb and the session and embark entries call the grill a design target.
- iss-2610180150254460The glossary term .abcd/development/brief/glossary/core/intent.md says an intent is frozen at promotion time, an immutable input artefact never edited after /abcd:intent plan is run (lines 20-21), but shipped sub-verbs edit planned intents: abcd intent target writes a planned intent's target_release line, intent edge writes its blocked_by and builds_on lists, intent hold writes a held line on a draft or planned intent, intent plan on a planned intent stamps its scope conditions, and intent interview runs on a planned intent and edits its record.
- iss-2610180155437281The brief surface chapter .abcd/development/brief/04-surfaces/05-intent.md says both the press-release intent and the frozen PRD are immutable input artefacts post-promotion (line 489), but no shipped check freezes an intent at planning: the planning interview edits a planned intent's record (internal/surface/cli/intent_interview.go:121 admits drafts and planned), and the hold, target, edge, link, reclassify, plan and ready sub-verbs write its frontmatter, scope-condition identities or grounds (internal/core/intent/hold.go, target.go, edge.go, reclassify.go, grounds.go, lifecycle.go Plan and Link).
- iss-2610180542030806The macOS leg of the check job runs one race-enabled pass, so the tests that assert only without the race detector (cost guards that skip under -race or drop their CPU bound there, 43 of them on 2026-10-18) run there and assert nothing: their bounds are checked on the ubuntu leg only, never on macOS. The workflow comment said dropping the plain pass dropped no test, which those tests had made untrue.
- iss-2610180545134593The implement loop package's tests are bound by git subprocesses: the slowest, TestPollingWithoutAnAnswerNeverHoldsTheIssuePastOneLease, runs Drain 120 times (a 4-minute poll over four 2-hour leases, kept inside the 5-minute take-over margin on purpose) and took 67s plain on a loaded machine, 31s on a quieter one with 3.84s of its own CPU; the next three take about 20s each, and the package is the slowest in both of the ubuntu leg's passes (320-410s plain, 470-650s race on 2026-10-18), with none of its 500 tests parallel.
- iss-2610180712063858TestTheHooksDeadlineStartsWithTheHook (internal/surface/cli/status_hook_test.go, the second half's assertion) failed on the merge queue's Linux check for docs-only pull request #1089 (merge-group run 39104650787, job check (ubuntu-latest), 2026-10-18T06:44Z): under the one-second hook budget the next prompt rendered 'status unavailable: no time was left to read it at this prompt' instead of the announcement. The test took 1.83s, and the package 253s beside a 349s implement/loop run on the same runner, so the shared one-second budget was spent by load before the read, and the test cannot tell that from a deadline started too early.
- iss-2610180735158998TestThePromptHookShowsEachAnnouncementOnce (internal/surface/cli/status_hook_test.go) runs the prompt hook at the shipped one-second budget with the status read capped at its shipped 600 ms, and asserts the announcement is shown, so a loaded runner can spend the read's share and fail it the way iss-2610180712063858 failed. Its budget is part of what it tests (the hook returns inside its second with an origin that would hang), so stretching the budget there is a choice about what the test proves, not a tolerance fix.
- iss-2610180913341869Follow-up to rpt-2610121533020069: the copied main review ruleset does not stop the owner's own PRs, and may not stop anyone's
- iss-2610180913363115abcd should automate taking a managed repository public: prepare, gate, hand over the visibility switch, then apply settings
- iss-2610180913376757A /abcd:design verb: design rounds, a person-only assessment, and a committed design historyrelated itd-2610171228577260
- iss-2610181122454939Two tests' 'origin that would hang' never hung: TestThePromptHookShowsEachAnnouncementOnce (internal/surface/cli/status_hook_test.go) and TestThePromptNeverWaitsOnTheNetwork (internal/core/claim/status_test.go) set origin to 'ext::sh -c sleep\ 30', but git-remote-ext escapes a space only as '% ', so git ran sh -c 'sleep\' 30, and sleep printed its usage and exited at once. A network call from the code under test would have failed fast instead of hanging, and a call that fails fast beats the clock too, so the hook test's no-network claim was not checked at all; the claim test's trace of git's subcommands covered only git run through its traced helper.
- iss-2610181153278714TestThePromptThatNamesTheSessionCarriesTheStatus (internal/surface/cli/status_hook_title_test.go) requires the status line in each of its four subtests under the shipped hook budget (one second) and status read cap (600 ms), with no override, so a loaded runner can spend the read's share and leave the status unavailable, failing it the way iss-2610180735158998 failed.
- iss-2610181153288506TestThePromptNeverWaitsOnTheNetwork (internal/core/claim/status_test.go) holds two wall-clock bounds to a bare second: that the block never waited on the network, while its read runs under the package's stretched budget, and that a held read returns at the hook's one-second deadline, about 150 ms after the read's cutoff. A loaded runner can fail either although nothing is wrong.
- iss-2610181318043459The SubagentStop hook prints 'abcd history: cannot read transcript' when the host keeps no transcript file, as in a session started with --no-session-persistence: the history capture treats a transcript path that does not exist as an error and reports it on every subagent stop, although there is nothing to capture. Seen in the live capture of the overnight-stall fix on 2026-10-18.
- iss-2610181517504705A status move (abcd capture resolve, and the other moves between status folders) writes the record at its new path with the atomic writer's default mode 0644, not the mode the record had, so a record kept 0600 in the embargo store comes out readable by group and other, and every embargo sub-verb then refuses the store until the person runs chmod 600 on it. The store's folder is required to be 0700, so no other account can reach the file; the cost is the refusal and the manual step.
- iss-2610181711260494The check job's macOS leg has little headroom before its 50-minute warning: across nine merge-group runs on 2026-10-18 it took 35.2, 36.5, 38.9, 42.3, 42.4, 43.0, 43.9, 49.4 and 44.8 minutes, and the run of #1099 came within 0.6 minutes of the warning. Nearly all of it is the one race-enabled pass over the whole module, 41.9 to 47.4 minutes in the last three; the plain-only guard step after it takes under a minute. The warning fires at 50 and the job ceiling is 60.
- iss-2610181757540736The check job's race passes are set by their total work: the macOS pass keeps a steady 2.80 to 2.85 of its runner's three test slots busy and the ubuntu one about 3.4 of four, so no reordering shortens them, and their slowest packages (internal/core/implement/loop, internal/surface/cli, internal/core/claim, about 46% of the macOS pass) spend most of it in git processes. A first cut, a default-branch name per claim operation and a batched view (#1099, #1100), took one drain test from 1,107 git processes to 830 but the whole of the loop and claim packages only from 126,334 to 119,327 (5.5%), which CI could not tell from the difference between runners; a cut measured on one test overstates the package.
- iss-2610181802344551A context-bound git command can outlive its caller's deadline: isolatedGitContext runs the partial-clone guard (lazyFetchGuard) first, and the guard's own git version probe and its floor-config read run with no context, so a git that hangs holds a caller on a deadline (the status verb, the prompt hook's reads) for as long as git hangs, though the command itself is killed at the deadline. Found when TestRootCommitContextKillsGitAtTheDeadline, run alone, took 20 s against a 500 ms deadline because its hanging fake git answered the guard's probes.
- iss-2610222000271964abcd drain run from a plain terminal stops at its first move: it reserves the first eligible issue, writes a host-judgement request, and waits for an agent session to answer it, so a person who types abcd drain in a terminal gets no fixes (seen 2026-10-22 20:47 BST on a second machine: 213 eligible, 0 lanes opened, iss-2610120138028442 reserved for 2h and left). The person wants abcd drain to work from the plain terminal by launching claude sessions itself to judge each remedy and drive each lane.related itd-2610222215485265
- iss-2610222001116066abcd has no single verb that cleans up a repository: after the 2026-10-22 crash this checkout held 189 worktrees (most on merged branches, some dirty), 86 reservation branches on origin (66 expired, 20 released), unmerged local branches, and inbox reports not yet pulled into the ledger, each needing its own manual pass. The person wants an abcd sweep verb that does everything a good cleanup needs: worktrees, branches, reservations, pulling in the inbox items, and so on.related itd-2610222214476887
- iss-2610222008081888abcd build refuses an intent as held by a peer when the only holders are long-lived local branches cut before the intent left drafts/, which hold the default branch's older copy of the record unchanged since their merge-base. On 2026-10-22, build itd-2610150602547271 was refused (exit 3) naming feat/hosted-sites-design, feat/hosted-sites-setup and fix/fence-day-lease as holding it in drafts/; none of the three changed the record since its merge-base with origin/main (1183-1185 commits behind). peersCheck in internal/core/implement/loop/check.go counts every Location in a bucket other than this checkout's, so any stale branch refuses every intent planned after it was cut; with ~190 worktrees on one machine this blocks most builds and build next.
- iss-2610222012245116abcd capture remedy <iss-N> given no fix text only fails with 'requires at least 2 arg(s)': nothing reminds the product thinker what the issue is or asks them for the remedy, so a person who comes to write the fix for an ineligible record (one with no remedy, or 'none (filed automatically)') has to go and read the record themselves, often written in code terms they cannot follow.
- iss-2610222014550692A release reservation (abcd reserve rel-vX.Y.Z) holds only merges armed after it: a pull request whose auto-merge was already on, or that already sat in the merge queue, still merges into the default branch mid-cut, from any copy or account, a running drain's included. Today the cutting session has to list and rule on those by hand right after reserving and again before merging the release pull request (commands/reserve.md, /abcd:launch 'Before step 1'), a manual step that is easy to miss on an every-other-day cadence.
- iss-2610222018028530Go toolchain 1.26.9 fails govulncheck on GO-2026-6809 (crypto/x509: distrust compromised intermediate certificates), a public Go standard-library advisory fixed in go1.26.10. govulncheck v1.7.0 reports it on every pull request's govulncheck job. Found on pull request 1107's govulncheck job, 2026-10-22. The external-contribution runbook's contained test image (.abcd/work/intake.md) also named go 1.26.7, two bumps behind go.mod, and moves with it.
- iss-2610222021318139The away-mode Stop hook allows a stop silently when git does not answer for the repository's root commit. Resolve now returns ErrNoRootAnswer or ErrGitTimedOut (wrapped) instead of ErrNoRootCommit, and hook_stop.go returns nil on any Resolve error under a comment that says the folder is not a checkout abcd can key a store on. On a loaded machine where the rev-list is killed, an away session stops with nothing on stderr and nothing in the away record, though the hook's help says every allowed stop is explained. owedread.go drops the same error the same way, so recorded branches leave the stop check without a note.
- iss-2610222022157889abcd reserve refuses in a fresh worktree: AGENTS.md sends a concurrent session to a plain git worktree add under the machine-scoped store and then to abcd reserve before any work, but a worktree just added has no .abcd/.work.local/ (the tier is gitignored and per-worktree), so tierPresent in internal/core/claim/copykey.go refuses with 'is not a directory in this checkout, so there is nowhere to keep this copy's key; run abcd ahoy to set it up' and nothing is pushed. Every new worktree hits it on its first reservation; on 2026-10-22 the go-1-26-10 worktree's reserve was refused this way, and a mkdir of the tier (made as a side effect of a preflight log directory) cleared it, with no ahoy run.
- iss-2610222026223032Autonomous work does not reliably survive the host's automatic compaction: after a compaction a long-running session keeps only a summary, and the work it was in the middle of (which lanes it dispatched, which PRs it is watching, what it promised a peer, the next step of a multi-step plan) survives only if the session happened to write it down. The person wants every autonomous session's work to survive auto-compaction, for example through a to-do list kept in the checkout's local tier (.abcd/.work.local) that the session reads back after a compaction. Related: the draft intent every abcd session keeps a checklist (itd-2610170638184486), being planned on 2026-10-22.related itd-2610170638184486
- iss-2610222031486962A guard warning reaches the person as a host error and is cut short: a warn (for example unrecognised-launcher) leaves the PreToolUse hook on stderr with exit 1, which the host renders as 'PreToolUse:Bash hook error / Failed with non-blocking status code: Warning by the abcd guard (unrecognised-launcher): This command line starts with a program the guard does not recognise, and what follows it could not be read: Th…'. The person sees an error for what is only a warning, the text is truncated before it says what to do, and a non-blocking stderr message may not reach the agent that ran the command, so the warning changes nothing. Seen by the product thinker on 2026-10-22.
- iss-2610222040438015spc-2610150728396006's C15 says the status-branch ruleset (.abcd/work/rulesets/status-protection.json) is applied through the rulesets' own apply verb (invariant 10), but abcd has no such verb: the ruleset was applied by hand on 2026-10-17 with gh api (it is live as ruleset 25302453), the way the rulesets README tells a person to; so the criterion names a mechanism that does not exist and cannot be checked as written
- iss-2610222040438242The cloud launch connector (scripts/cloud/connectors/claude/launch.sh lines 10 and 51, pinned by internal/cloudscripts/cloud_send_test.go:113, and stated as the launch form in itd-2610120738075547 and spc-2610120941441282 step 12) passes whatever environment id the person configured to `claude -p "<prompt>" --environment <id> --ref <branch> --output-format json`. Claude Code's CLI reference and cloud-environments pages, read on 2026-10-22, document that form for a self-hosted environment only: `--environment` takes a `ccpool_` id and Claude Code rejects an Anthropic-hosted `env_` id there, and `--ref` applies only with it; the test fixture itself used an `env_` id. So a person whose cloud environment is Anthropic-hosted, the usual case, gets a refusal at launch. Found while preparing the product thinker's hosted run for 2026-10-23.
- iss-2610222040450844The rulesets README (.abcd/work/rulesets/README.md) still says status-protection.json is 'Not yet applied' and that its id joins the list below once it is, but the ruleset has been live since 2026-10-17 as 'status protection' (id 25302453, enforcement active, read through the API on 2026-10-22), so the committed mirror's documentation contradicts the forge
- iss-2610222047465878The implement loop's samePath (internal/core/implement/loop/loop.go:1024) decides whether two paths name one directory by comparing their cleaned, symlink-resolved strings, so on a case-insensitive file system (macOS APFS by default) two spellings of one directory that differ only in case compare unequal. Its callers in the loop are unattended.go:64 and :75 (is this session a running build's lane), judgement.go:327, ratelimit.go:155, configwatch.go:273 and schedule.go:115. For the permission-prompt refusal the failure is open: an unattended lane whose host reports its directory in a different case is not recognised, and the host's prompt shows and waits, which is the behaviour before the refusal existed. Paths there normally come from git and the host's own working directory, so a mismatch is unlikely. ahoy has its own samePath that compares os.Stat results with os.SameFile, which handles case and links together; embargo's compares resolved strings and refuses on a mismatch, failing closed. Found during the review of the permission-prompt refusal, deferred from that change so as not to alter a helper six other loop call sites share.
- iss-2610222106115276The cloud hand-off cannot start a session on the Anthropic-hosted cloud environment: Claude Code names an environment at the start only for a self-hosted one (--environment takes a ccpool_ id and rejects Anthropic-hosted env_ ids, CLI reference read 2026-10-22), and the documented way to start an Anthropic-hosted session from a terminal, claude --cloud "<task>", takes its environment from the /remote-env default and its branch from the current checkout, and documents neither its output on creation (no machine-readable form is documented for creating, only for sending to an existing session) nor whether it exits or attaches; so scripts/cloud/connectors/claude/launch.sh refuses an env_ id rather than guess, and the planned hand-off (itd-2610120738075547) works only on a self-hosted environment until the create form is probed live
- iss-2610222125175640After macOS process ids wrap, the load gate's queue is no longer first-come-first-served and an old waiter can be starved by every new starter. On 2026-10-22 waiters started 19 s and 9 min earlier held pids 8034 and 12051 while hour-old waiters held 58628 and 73003. The fix for iss-2610161634043273 orders the queue by start time but counts a queued waiter as ahead only when it is ahead by start AND has the lower pid (internal/core/machineload/queue.go, queueOrder/queuedAhead), so after a wrap neither waits on the other; the open-moment stand-back in implement.WaitLoad (openLook, internal/core/implement/load_wait.go ~546) then yields to the lower pid, so the hour-old waiter stands back for each young low-pid starter until its backoffs run out or its timeout (8 h) ends, and a release-blocking preflight can be held all night.
- iss-2610222212301498The --route prediction parity test (internal/core/implement/loop/route_parity_test.go) checks predictHand against fake stage bodies, not the real validateStage and implementStage. If validateStage's hand-out order changed (openRound's roles reordered, or a Stay or Goto returned before its Await), a --route for a reviewer role would be accepted and then silently not used: no refusal, and no route_unused entry, since nothing is unsure without a landing ahead. The real bodies agree with the prediction today; the gap is that no test would notice them drifting apart.
- iss-2610222251373104A plain make preflight on a shared machine can wait at the load gate indefinitely: its gate is bounded at two hours (Makefile, implement load --wait --timeout 2h), and when other accounts' preflights queue ahead with eight-hour waiters, each about an hour long, it times out and its retry joins the back of the queue, behind every waiter that arrived meanwhile. A drain lane's implementer timed out once and was re-queued behind three more on 2026-10-22. commands/implement.md says to run make preflight plain, while the wrapper form (implement load --wait --timeout 8h -- make preflight) keeps a queue place without the two-hour bound.
- iss-2610222359046244abcd build (and abcd reserve) refuses a reservation by naming only the first footprint path that overlaps a live reservation, so a build whose footprint collides with several reservations is refused once per collision: on 2026-10-22/23 the merge gate's build (itd-2610150602547271) was refused in turn on internal/core/implement/loop/land.go (iss-2610120138028442), internal/surface/cli/cli.go (iss-2610171110154902; a second reservation, for an issue filed on the unmerged fix/autonomous-permission-ask-denied branch, held it too, unnamed) and internal/core/landing/config.go (iss-2610222014550692, a directory footprint), each discovered only after the previous one was routed round. <!-- record-lint: forward-looking -->
- iss-2610230014564359The worktree store's spec (spc-2609301811532881) never mentions the embargo store, which lives inside the same lane as ~/.abcd.noindex/worktrees/<root-sha>/embargo/ (internal/core/embargo/storepath, Name = "embargo"): a later step's add could take the name embargo, and list, prune and quiet-candidate scans could judge or reclaim the embargo store's detached worktree as a stale lane, so an unpublished advisory's private records could be archived or removed; found by the ruthless review of the store's step 1 on 2026-10-23, which judged nothing reaches it yet because lane names cannot be embargorelated itd-2609091014076309
- iss-2610230015129841No test at the command level covers implement step handing its reviewer route into the routing load: changing loop.LoadTiering(roots, review) to loop.LoadTiering(roots, nil) in internal/surface/cli/build.go leaves every CLI test green, though with oracle.review: rp and a reachable URL every ruthless and security review would then record a tier and its brief ask for one while the rp route takes the review. The logic is covered at step level through Drive; only this one-line hand-off at the front door is not.
- iss-2610230015137603When the rp reviewer route is configured and reachable as a step starts but its call then fails, the review falls back to the host, and the round's record still says the rp reviewer route took it with no tier, so the host runs that review without a tier and a later failed round never escalates it: tier escalation (itd-2609170822093401 criterion 10) does not apply to a review that fell back. The behaviour predates the escalation work; the escalation fix round covered only a route with no URL.
- iss-2610230016523625Lanes lose whole preflight slots to repo-wide audit tests that fail late. A preflight queues behind every other preflight on the machine (an hour or more on 2026-10-22), then spends its first long stretch on the unit stage before a test that reads the whole tree fails on a sentence: TestSurfaceChapterProseStatesNoShape failed two lanes' preflights on 2026-10-22, each for a command name in the build brief's prose, and the lane then had to queue again from the back. The same lesson came up on 2026-10-18, when lanes were tested package by package and missed the repository-wide audit tests until preflight. Nothing lets a lane run the fast, repository-wide gates and audit tests on their own, in seconds or a few minutes, before it takes a preflight slot.
- iss-2610230016544142Directory-level reservation footprints over-reserve and serialise unrelated lanes. On 2026-10-22 four lanes were held up by footprints naming whole directories or packages when their work changed a few files: the worktree store against the merge gate, the sweep-reservations branch holding all of internal/surface/cli against a store build adding two new files there, a release hold against internal/core/landing, and a planning branch holding whole record directories. Each was cleared only by hand-narrowing the footprint to the files the branch changed. Specs' footprint lines and abcd reserve both take a directory as readily as a file, and nothing warns when a directory is named.
- iss-2610230016561927A build run serialises every lane on the previous lane merging into main. The ready rule for a lane's predecessors (the DR6b default needs, read with landedInRun as being an ancestor of the default branch) holds each step until the step before it has passed the merge queue, so a six-step spec spends roughly 20 to 25 hours in serial queue time at the preflight and merge-queue times seen on 2026-10-22, most of it waiting rather than building; the merge-gate build was the case that night.
- iss-2610230048490215make precheck chooses the command and site packages' audit tests by a word in their names (PRECHECK_AUDIT_TESTS), and nothing checks that a new test reading the committed tree carries one: an audit test named outside the pattern runs in preflight but not in precheck, so a lane can pass precheck and still lose a preflight slot to it. A structural detector was tried and set aside: about 250 command-package tests reach the repository root, most to run scripts and hooks rather than to audit prose, so 'reads the root' does not tell an audit from a behaviour test.
- iss-2610230059199116A build run renders each lane's brief from the intent and spec as they stand at the lane's base on the default branch, so a refinement recorded during the run (a narrowed footprint, a new requirement or test line on a later step, a decision citing the spec) never reaches the run's own later lanes until it is merged to the default branch by some other change. On 2026-10-23 the merge gate's run (run-2610222359421510, itd-2610150602547271) recorded step-4 security requirements and step-wise footprint decisions on the orchestrating branch; lanes 2-6 would have been briefed without them, and a separate records pull request had to be cut to carry them to main ahead of lane 2.
- iss-2610230223231843A drain state written by a newer abcd is refused as a file that does not parse, with a remedy that throws the drain away. readDrain (internal/core/implement/loop/drain.go) decodes the drain state strictly and refuses any schema_version other than its own, so a newer abcd's drain state (a later drain schema, or a field a newer build adds to a stored route) reads as "does not parse as the drain's state" with the remedy "restore it or remove it", which deletes the drain record of the newer run. The run state already refuses a newer writer's file before any strict decode, naming it a newer abcd's and saying not to remove it (decodeState); the drain state has no such check.
- iss-2610230235262742The run state's version checks (metered, pinned, overridden and rounded in internal/core/implement/loop/state.go) each repeat their own walk over the lanes' receipts and validation rounds, and readStateIn repeats one case per check and version bound. A place that stores a route added later (a third slot holding a RouteRecord) has to be added to each walk by hand, and one missed walk silently accepts an older file carrying a newer field instead of refusing it.
- iss-2610230351350588An implement step refused at land while the lane waits for its full check (exit 3, 'nothing written') still renews the lane's reservation on origin, but the renewal is not logged in the run record as reservation_renewed: on 2026-10-23 abcd peers showed the reservation renewed until 05:51Z while implement record's last reservation line still read 04:33Z, so the record understates how long the run held the issue.
- iss-2610230410035051A release hold records a merge-queue pull request's withdrawal as the queue form only, though merge-when-ready in a queue repository is auto-merge plus a queue entry; re-arming it is a direct enqueuePullRequest, which the forge refuses when the pull request is not ready (checks stale after the base moved), so it stays withdrawn and the person's wish to merge when ready is lost.
- iss-2610230410049950The remedy text a release-hold finding gives for a queued pull request, run gh pr merge N --disable-auto, may not take it out of the merge queue, and it disarms the pull request with no withdrawal recorded, so nothing re-arms it after the tag.
- iss-2610230410054046Nothing re-checks the release merge hold when the release pull request is merged: the launch merge-hold check runs in launch --dry-run, ship and the render only, so a merge armed after the dry run and before the merge click is not refused.
- iss-2610230426248185abcd implement load --wait prints 'waiting for capacity: ...' once, at the first look that finds the gate shut (OnWait), and 'load gate: the machine looks free; checking everything again in Ns before opening' once (OnSettle); a waiter whose re-check finds a new blocker goes back to waiting silently. On 2026-10-23 a waiter's log read 'the machine looks free' for over half an hour while two other waiters' preflights ran ahead of it, so the log, the only thing a session reads while it waits, said the opposite of what was happening.
- iss-2610230519103295abcd session setup and blueprint now write the relay's Render Blueprint to render.yaml at the repository's root, but a team that deployed from the earlier location, .abcd/relay/render.yaml with Render's Blueprint Path set to it, keeps that stamped file untouched and unmentioned, so Render goes on syncing the old path while setup points at the Deploy button, which would create a second service (internal/core/session/blueprint.go, found by the Opus review of spc-2610141709430146 step 6 on 2026-10-23)related itd-2610091016262335
- iss-2610230519116460abcd session setup checks the relay's blueprint files only after GitHub has created the app, so a blueprint refusal (an edited Dockerfile or render.yaml) exits 2 before the steps that name the app's install and settings pages are printed, losing them on the one run that created the app (internal/surface/cli/session.go, found by the Sonnet review of spc-2610141709430146 step 6 on 2026-10-23)related itd-2610091016262335
- iss-2610230519122686When abcd session setup gives up after three failed exchanges with GitHub for the new app, GitHub may already have created it, and the refusal names neither the app nor a way to record its client id, so a rerun registers a second app and the first must be found and deleted by hand (internal/surface/session/appsetup.go, from the Opus and Sonnet reviews of spc-2610141709430146 step 6 on 2026-10-23; the retry itself is fixed)related itd-2610091016262335
- iss-2610230643534431A cutter whose copy pushes through an app (a hosted session's installation token) records every withdrawal on a commit an app pushed, so abcd can neither admit nor re-arm any of them: each is named app_pushed once and left for the person to re-arm by hand after the cut. Whether such a copy should withdraw at all, or how its withdrawals could be vouched for, needs a design decision.
- iss-2610230643540706The forge's activity record is read as one page of 100 entries. A release branch with more than 100 activities is read partial for ever, so every withdrawal on it reads not yet verified on every act and is never re-armed by abcd.
- iss-2610230643556343Two releases reserved at the same moment both pass the one-release-at-a-time check, since each reads the view before the other's push lands; and a view that cannot be read lets a release reservation through unchecked.
- iss-2610230643562468github.Pushers passes over an activity entry with no actor or a malformed field without saying so. The release hold now requires the record's pushes to run unbroken down to the branch's first push, which catches a missing link, but not two missing entries that cancel out (a push and the rewind over it); only a count of the entries passed over closes that.
- iss-2610230651407493While a lane's landing is held by another copy's release reservation (rel-vX.Y.Z), every implement step pushes a fresh renewal of the lane's reservation to origin, whatever its age: on 2026-10-23 the branch abcd-reserved/iss-2610120138028442 took five renewal commits between 06:02:43Z and 06:02:57Z and one per later step, each for two hours. commands/build.md says a renewal is pushed only once half the lease has passed, and that the land fence, when it holds, renews for a day; neither holds on the release-hold path, so a lane held for a day writes dozens of commits to the reservation branch.
- iss-2610230716454430The build runner (runner.claude) still follows ruling RN2's key-only rule (dcn-2610020000000016): it runs claude with --bare on an API key, and a person with only a subscription runs the role in their own session. On 2026-10-23 the product thinker ruled that a terminal drive runs on the person's subscription by default behind a wall, with an API key optional per configuration (dcn-2610230716408975). The two routes now differ, and the product thinker has not said whether the build runner takes the same default.related itd-2611040344170206
- iss-2610230724404433Draining the ledger with parallel lanes on 2026-10-23 needed five things done by hand, because no abcd verb does them: (1) abcd drain opens one lane at a time, so the extra lanes were started as separate abcd build <iss-N> runs, and the issues for them were picked by hand, checking each found_at against every live reservation (two picks were then refused for overlapping a peer's footprint); (2) driving five runs meant a hand-written helper, .abcd/.work.local/scratch/drain-step.sh, that steps one run until it awaits an agent and prints a one-line summary, since implement step prints a long JSON document per call and has no form that steps every run in progress; (3) the per-person reservation cap (10) was already passed by one person's sessions across two accounts, and raising it meant hand-writing ~/.abcd.noindex/config.json with reservation.max_live, a file nothing creates or validates in advance; (4) each implementer had to be told to run make preflight through implement load --wait --timeout 8h, as iss-2610222251373104 records; (5) the host's wake-up prompt carried the list of run ids by hand, since nothing lists the runs a drain session is driving.
- iss-2610230734298145The command surface needs another consistency review on three axes. (1) Human verbs versus agent verbs: which commands a person types and which only an agent drives (the plugin pages' user-invocable split), and whether each is named and documented for its real audience. (2) Verbs versus nouns: some commands are actions and some are things, for example abcd drain (a verb) beside abcd lab (a noun), with no stated rule for which form a command takes. (3) Consistent flags: the same idea should be spelt the same way on every command, for example a select-everything flag (drain takes --max for a cap; is there an --all?), --dry-run against a bare read-only form, --apply, --json, --release and --take-over. Raised by the product thinker on 2026-10-23.
- iss-2610230736247888The away-mode owed-work reader treats a local-branch listing cut short by its time budget as a plain listing failure: when the budget runs out during git for-each-ref, it notes that the local branches could not be listed but never marks the reading incomplete, so the stop judgement reads it as no own branches and nothing owed instead of failing open on an incomplete reading. A pull-request listing cut short the same way is noted as judged from disk alone. Seen as a failure of TestReadOwedHonoursDeadline in a make preflight run under load on 2026-10-23, and reproduced every time with a context spent before the read.
- iss-2610230745597968Questions still break abcd's asking limits after several rounds of fixes, on two accounts on 2026-10-23. (1) In a repository abcd manages, on another account, an agent bundled four separate issues into one question without going through the abcd:question-drafter agent, and the question check refused 21 parts at once: headers that were not role chips, no Decide later option, no Now: or Change later: lines, and question text that did not quote the thing being decided; the status line meanwhile read 'waiting on the product thinker'. (2) In abcd's own checkout, a question was refused because its text did not end with the question, and it also ran 25 rows against the 24-row limit (header and frame 8, question text 7, options 10), which the check reports but does not refuse, so it would have been shown and a narrow window might cut it; at the same time an abcd:question-drafter run spent 9 minutes 32 seconds and 174.2k tokens recounting over-limit tabs with a hand-written rows script. Earlier rounds include iss-2610071538055431, iss-2610100626327722, iss-2610161734179773 and the open iss-2610090816296964.related itd-2610230756259215
- iss-2610230814124362TestTheStoredLineReadEndsWithItsContext (internal/gitutil/stored_each_test.go:56) failed in a make preflight of feat/local-model-pin-r2 on 2026-10-23 with 'git ran 0 times; want once, for the first read only', at a load of roughly 27 to 40 on 16 cores, and passes on origin/main and on that branch when run alone. The test counts git invocations, so a run that never reaches git, or whose count is read before git is invoked, under load reports zero.
- iss-2610230814127624Two status-line deadline tests fail under machine load and pass in isolation: TestStatuslineSlowBranchStillRendersThePartialRow (stdout empty, the call returned in 2.003s against a 2s git budget) and TestStatuslineKillsTheRootCommitGit (the root-commit git timed out at 2s, so the 'git did not say whether abcd manages the checkout' note was replaced by 'git did not name the checkout within 2s'). Both failed in a make preflight of feat/local-model-pin-r2 on 2026-10-23 at a load of roughly 27 to 40 on 16 cores, and both pass on origin/main and on that branch when run alone. The first is the test iss-2610090642407850 resolved on 2026-10-09; its timing margin is gone again under load, and the second shows the same root cause: a real 2-second budget raced against git on a loaded machine.
- iss-2610230816405438The release hold's full loop (an armed merge withdrawn at reserve, commented on, and re-armed after the tag) has no private live test: on a free personal plan a private repository can take neither branch protection nor auto-merge, so a scratch repository has nothing to arm. Only the comment writer itself (post and read-back) has run live, on 2026-10-23; the loop runs on fakes only.
- iss-2610230826159867A resolved issue's resolved_by.commit goes stale when the commit it names is rewritten before it reaches the default branch, and nothing follows it. On 2026-10-22/23 lane C re-stamped records by hand three times: twice after rebasing a stacked branch onto a moved parent, and once after re-wording an unpushed commit to drop a scoped prefix. Each time RS003 found the stamp unreachable and the ledger gate failed until the sha was edited by hand. Two designs are open and not chosen here. A lookup by patch-id follows a reworded or rebased unpushed commit to its new sha, but does not survive a squash merge, which already rewrites the cited commit out of existence and which RS003 reports. Stamping at land time instead (resolve names the change, the land step writes the merged sha) survives a squash but needs the land step to own the stamp.
- iss-2610230839002949An intent's build reserves its spec's whole Footprint packages line once, for every lane of the run, and never reads a step's own packages line, so the reservation cannot start at the first step's files and widen step by step. Building that needs a reservation per open lane (the union of the steps in flight, since steps marked needs: none run beside each other), a widening act as each lane opens (a reserve with the union and the tip's term, as widenReservation already does, since claim.Request.Narrow refuses to widen), and a narrowing as each step lands. That is more than the directory-warning fix for iss-2610230016544142 could carry, so it is filed on its own.
- iss-2610230851422913The brief's rules section (04-surfaces/README.md, 'The rules verb') describes only the bare and `<DOMAIN>` forms; the registered `abcd rules --prompt` flag appears nowhere in the brief.
- iss-261023085143897738-announce.md says a hosted session runs no hook, but the cloud setup script sets core.hooksPath=.githooks (scripts/cloud/connectors/claude/setup.sh:315), so a hosted session abcd set up runs the pre-push hook.
- iss-261023085144655817-guard.md says a broken guard never bricks a session, but hooks/pre-tool-use.sh exits 2 (blocking) on every shell and question call while a legacy ~/.abcd folder exists, until it is moved.
- iss-261023085145178827-implement.md:378 says three sub-verbs drive the loop, then describes four, and the binary ships four (status, step, receipt, record).
- iss-261023085148089026-mode.md says every refusal of the away verbs exits 2 and lists them, but omits a queued step over 500 characters, a full queue, a record that would pass 64 KiB, and no home folder or root commit.
- iss-2610230851520489The Stop hook also runs while the person is present: a turn ending with work owed is allowed with one line naming the next item; commands/mode.md describes it only as the away mode's check.
- iss-261023085152942603-configuration.md's user-scope inventory of ~/.abcd.noindex/ omits four folders the binary writes: away/, sessions/, dashboard/ and after-update/.
- iss-2610230851531652docs/how-to/install.md says every live-session hook needing the binary tries the bootstrap, but stop.sh, stop-failure.sh and subagent-stop.sh never do, and its list of what a broken install loses omits the away mode's stop check.
- iss-2610230851537506The guard now blocks starting claude --dangerously-skip-permissions, codex --yolo, opencode run --auto and the OPENCODE_* settings, and reads bunx, bun x and pnpm exec, but no user-facing record carries the change, so the next release's changelog has no line for it.
- iss-2610230855093864A drain reserves an issue with the path its found_at names, and when that path is a tracked directory the drain shows no directory warning anywhere: reserveKey builds the drain's hold without the claim result's Directories (internal/core/implement/loop/reservation.go around line 603), and the drain's text and --json renderings never print its start's reservation warnings. The build and reserve verbs warn of a directory footprint; the drain leaves it unsaid, by design so far because a drain narrows each lane to the files it changed once it reaches its landing, but until then the directory holds off every other reservation inside it, unannounced.
- iss-2610230856272073A build run's dependent lane cannot start until its predecessor has merged into the default branch: readiness reads a predecessor as landed only when its lane is done, its pull request an ancestor of the default branch, so a step that needs another waits a whole preflight and merge-queue cycle (about one to two and a half hours each on 2026-10-22) before it opens. Stacked changes are standard practice for dependent work (Graphite, Sapling and ghstack stacks, and merge queues taking a stack in order), and on 2026-10-22/23 that shape was rolled by hand twice: merge-gate steps 2 and 3, and model-matrix step 2 stacked on the route branch. Building it is more than a fix: the dependent lane's pull request is based on the predecessor's branch, the stack merges in order, and a lane rebases (and re-stamps what it resolved) when the predecessor changes.related itd-2610230856403803
- iss-2610230856411104Open specs with two or more steps declare no step's needs, so every build run of them is fully serial by default (ruling DR6b: a step with no needs line waits for every earlier step). On origin/main on 2026-10-23 only 5 of 169 specs declared any needs line. The open specs most affected are the merge gate's and the model matrix's, which are being built now. No one is adding needs lines to the open specs yet.
- iss-2610230927379322The merge hold that abcd land respects (claim.Hold, read by releaseHolds) still reads a release as ended as soon as any tombstone sits on its reservation branch, whoever pushed it. The release hold now ends a release only on a tombstone its holder pushed or on its tag, for the second-release refusal, the launch reading and peers, so the two readings of one release can disagree: land lets merges through while the launch check still names the release as being cut. The land hold already ends when its lease lapses, so it is a time-boxed courtesy and the withdrawal is the hold that keeps merges out; the disagreement is in what each surface reports.
- iss-2610230935429241spc-2609202134338445 step 3 (the process driver) is unlanded and its remaining part waits on the ADR that step 11 (--auto-plan) mints, a later step. A needs line can name only earlier steps, so the build loop can open step 3 before step 11 has minted the ADR it waits on. Its other later dependency, step 7's receipt verifier, is already landed. Found while declaring the open specs' needs lines, 2026-10-23.
- iss-2610231003000222The worktree store's merged judgement keeps for good a branch whose merge it cannot see from the reflog or the forge: a branch rebased locally and then merged leaves no commit entry of its own in its reflog, and so does a merged branch whose reflog has expired; with no forge answer the content tests are always false once the tip is an ancestor of the default branch, so prune keeps the worktree on every run although its work has landed. Found by the Opus review of the store's steps 3 and 4 on 2026-10-23; it errs on the safe side, never reclaiming what it cannot prove.related itd-2609091014076309
- iss-2610231004012419abcd reserve cannot widen a live reservation from another copy of the same person on the same machine. A second worktree that reserves the same id with more footprint paths is refused as if the hold sat on another computer (internal/core/claim/remote.go:403, 'you are already building it on another computer; pass --take-over'), and a take-over moves the hold, which can disturb the run that owns it. Two sessions hit this on 2026-10-23 in the hand-rolled coordination log: abcd-54 at 10:04 could not add the worktree store's step 3 and 4 files to its live itd-2609091014076309 hold from a second copy, and borrowed an unrelated open record's reservation to announce them; abcd-f1 at 10:26 and 10:41 had its own hold read from a sibling worktree as another computer, and added the paths from the reserving worktree instead. Related: iss-2610161457209287 (holds do not say which of a person's copies has them).
- iss-2610231004140527The live-reservation cap is counted per GitHub login across every session, copy and account that pushes under it (internal/core/claim/crowd.go), while each machine sets its own ceiling in reservation.max_live. On 2026-10-23 six interactive sessions on one login reached 30 live holds and abcd-43's reserve was refused at 10:40; abcd-ae raised the ceiling to 40 by hand, the third raise since 10-22 (hand-rolled coordination log, 10:40 and 10:41). A drain run under another account that pushes with the same login is counted against the same holder under its own, possibly lower, ceiling, which no session here can read, so the interactive sessions can hold the drain at its cap with nothing on either side saying so. Graded minor when filed, because the drain waits at the cap rather than failing (iss-2610161015371794), and whether the drain shares this login and at what ceiling is not yet confirmed; it was confirmed the same day, and the grade raised (below). This revisits the ruling recorded in iss-2610170717515674 (one ceiling per person, raised in the machine's configuration); related: iss-2610160925028248 (one reservation per record spends the cap) and iss-2610161457209287 (holds do not name their copy).
- iss-2610231011465325The worktree store's merged judgement reads a branch's own commits from its reflog, and a reflog can carry another branch's history: a branch copied from a branch that was itself created, then force-reset and left until its unreachable reflog entries expire, keeps the source's creation entry and commit entries, so it is judged merged by ancestry with no commit of its own, and prune could remove its clean worktree with its ignored files. Every commit it holds is already on the default branch, so no commit is lost. Found by the Opus review of the store's steps 3 and 4 on 2026-10-23, after three earlier reflog shapes were closed.related itd-2609091014076309
- iss-2610231038335615Reading the reservations writes into the shared git object store: claim.View names the empty tree through gitutil.EmptyTree, which runs git hash-object -w, so every read of the reservations (abcd peers, the status line, the sweep's dry run) writes or refreshes the empty-tree object under .git/objects. A read only compares tips against the empty tree's name and never needs the object to exist, and the sweep spec's criterion 11 allows writes only under the abcd home and the local tier.
- iss-2610231057580368scripts/check-reviews-cases.sh case 'RD004 a NUL byte after the sha' failed once inside make preflight on a loaded machine (load about 30 on 16 cores, 2026-10-23) although the output carried RD004, then passed on three standalone reruns; a likely cause, unconfirmed, is grep -q under set -o pipefail closing the pipe early and failing the printf that feeds it, which a busy machine makes more likely.
- iss-2610231057586567internal/core/afterupdate/afterupdate.go:72 declares its own rootSHARe full-SHA pattern, a third private copy of what gitutil.IsFullSHA answers, beside the two the 2026-10-23 drain lane for iss-2610140813542607 removed from history/store.go and lifeboat/voyage.go.
- iss-2610231113504812Usage errors repeat operands and flag values on stderr
- iss-2610231114293603The build loop's lane stage reports a lane worktree as not added when the repository's post-checkout hook fails: git runs that hook after it has made and registered the worktree and created the branch, then exits with the hook's status, and the lane stage reads the exit as git could not add the worktree. A rerun adopts the standing worktree, so the lane recovers, but the first message is false and the run spends a step on it. Found while fixing the same case in the worktree store's add on 2026-10-23, which now finishes a worktree git made and says the hook failed.
- iss-2610231125086511Two concurrent runs of the worktree store's add for the same name race: the second run's git fails because the branch already exists, and the adopt-after-failure path then claims the first run's worktree, reports that the checkout hook failed with git's branch-exists message, which is false, and lays the local tier inside a worktree the first run may still be checking out. Found by the Opus review of the store's step 2 on 2026-10-23.related itd-2609091014076309
- iss-2610231125096250When the worktree store's add finishes a worktree git made after a failing checkout hook, and the finishing itself fails (the start record or the local tier cannot be written), the refusal drops the hook's exit status, so a person sees only the finishing failure and not that the hook failed first. Found by the Opus review of the store's step 2 on 2026-10-23.related itd-2609091014076309
- iss-2610231127555243The live-reservation cap still counts one total per GitHub login across every account that pushes as it, while each machine reads its own reservation.max_live, so a drain on another account under the same login stays held at its own ceiling whenever this machine's sessions hold more. iss-2610231004140527 made that visible: abcd peers counts the reader's holds by copy and warns from four fifths of this machine's ceiling, and the cap refusal groups the held records by copy. Whether the count itself should change is a ruling the coordinator is taking to the product thinker: keep one ceiling per person (the ruling recorded in iss-2610170717515674) or count per account and machine.
- iss-2610240823574047ahoy install run from a plain Terminal cannot wire the status line or a PATH entry: with no CLAUDE_PLUGIN_ROOT the plugin root is missing (plugin.root_missing), stepPathEntry returns early, ~/.abcd.noindex/path-entry stays absent, and the status-line offer is answered yes through all its element switches only to be refused afterwards (no PATH entry on record). The person learns of the prerequisite after answering every question.
- iss-2610240824005655ahoy install hides the git identity fix behind the generic settings approval: the identity mismatch is listed only as one line under 'Change the settings listed above?', a no there means the identity question is never asked, and nothing says that declining the settings approval also declines the identity pin the person wanted to keep.
- iss-2610240824047504in a source checkout of abcd, go run ./cmd/abcd ahoy install is always refused as a stale binary, because go run never stamps VCS build info, although AGENTS.md makes go run the only sanctioned way to run abcd there; every run needs --allow-stale-binary.
- iss-2610240824571059ahoy install offers a tool install through Homebrew on an account that cannot write to Homebrew: on this machine /opt/homebrew is owned by the admin account, so brew install gitleaks fails on every run, and the failure note relays Homebrew's own sudo chown advice, although abcd never escalates privileges. The registry has one install step per platform (Homebrew), so an account without admin rights has no route that works.
- iss-2610240827243654The documented CLI install one-liner (README and docs/how-to/install.md) is far too complicated to be a one-liner: a single sh -c string of roughly 3,000 characters that unsets proxy variables, refuses a symlinked ~/.abcd.noindex, maps uname output to a release asset, downloads it and checksums.txt, verifies the checksum, probes gh attestation verify for four flags, resolves the latest tag and its commit through the GitHub API, verifies build provenance, prints a long fallback warning, installs to ~/.local/bin and writes ~/.abcd.noindex/path-entry. Nobody can read, audit or safely retype it, and a reader cannot tell what they are agreeing to run.
- iss-2610240830397793the committed identity pin names one person, so it misleads every other contributor: .abcd/config/identity.json pins the product thinker's identity, ahoy install reports any other contributor's identity as a required git_identity.mismatch gap and proposes they commit as the pinned person, and the committed .githooks/pre-commit refuses their commits with 'fix: git config user.name "<login>" && git config user.email ...', telling them to commit under the maintainer's name. That contradicts the attribution rule that every commit is honestly authored by the human who made it, in a repository that takes outside contributions.
- iss-2610240859590333A session wrote records into the main checkout's working tree on main while another live session (abcd-0d) was working in the same checkout, because nothing enforces the rule that a concurrent session works in its own worktree. On 2026-10-24 this session ran capture, intent, decide --adr and go generate from the main checkout: an issue record, an intent draft, an ADR and two regenerated index regions landed in the shared tree, the regenerated indexes folding in a peer's untracked draft. Nothing refused or warned. capture, intent and decide write into whichever checkout they run in; the guard judges shell commands and questions, not where records are written; and the CONCURRENCY rules domain, which carries the rule, recalls only on prompts about worktrees, peers or sessions, so a prompt saying 'file the decision record' never injected it. The agent also skipped the required scan (session listing and abcd peers) before mutating. The rule held only as prose.
- iss-2610240916382802ahoy reports an empty install_mode for a working, recorded PATH entry whenever no plugin root resolves: detectInstallMode returns "" when !pluginOK, so after a successful README install (~/.local/bin/abcd on PATH and named by ~/.abcd.noindex/path-entry) a plain-terminal or session run still says nothing is installed.
- iss-2610240932215918The claude runner cannot run on a Claude subscription, so a person without an API key has no route to any role abcd runs from a plain terminal: the planning interview, a build's implementer and validators, the drain's judge.
- iss-2610240932444000`abcd intent interview` never hands the interview to a host session, and its refusal names only a runner, so a person sent to the verb is not told that the session they are in may conduct the interview.
- iss-2610240932493158The two-way pair that marks an issue as promoted (the issue's `related_intents` naming an intent that names it back in `related_issues`) cannot tell an issue the intent delivers from an issue the intent only cites as evidence, so an evidence-only issue reads as promoted and `capture promote` refuses it.
- iss-2610240946046901Four of the product thinker's rulings of 2026-10-14 in iss-2610140652230444 are carried by no record once itd-2610240922461281 takes the review set: the top class consulted (1) for a third read of release-blocking security changes (the shell guard, installing and updating the binary, secrets, what is published), (2) before a design-heavy plan locks, and (3) when the executor fails twice with the same failure fingerprint; and (4) code is written by the middle class. The review-set intent carries only the fourth consult case (the pair disagrees), as its judge. Each of the four sits at a seam outside the review round (a release gate, the planning interview, the fix-round loop, the implementer's route), so each is its own piece of work; deferred out loud here rather than left inside a draft's Decisions where a reader of the issue would not find it.
- iss-2610240959030370before a new release, abcd must verify that all dependencies and especially those it pins to an abcd-managed repository are moved to the latest, verified version -- verified meaning that they are guaranteed to work with abcd. It should stay with a previous version if the newest one breaks abcd.
- iss-2610241103012197A verdict abcd reserves for the person (embargo triage, and any verb whose record names who decided) is handed back as a bare choice, so a person without the code-level context cannot make it. commands/embargo.md says only 'The verdict is the person's decision. Ask for it; never choose it yourself.', and the asking rules (internal/core/question/asking.go:74-76) allow a recommendation only when the person asks for one. In a session on 2026-10-24 the person, handed four triage verdicts, answered 'why leave to me? I can't decide that.'; a per-item recommendation with its reasons, then a plain yes, settled all four at once.
- iss-2610241104098581Sessions treat merges as held for a release cut whose holder has crashed: on 2026-10-24 local session abcd-0d told every session that v0.15.2 is being cut so merges are held, while the only marker of that cut on origin is the reservation rel-v0.15.2, held by copy 07cd3b4c167cec332f8c01cf42ad41d6 (a computer that crashed), last renewed 2026-10-23T08:52:49Z and expired 2026-10-24T08:52:49Z, with no standing announcement, no release branch and no newer tag. Nothing names a cut as abandoned: abcd status lists rel-v0.15.2 as an ordinary expired reservation, so a session reading it, or relaying a hold heard earlier, keeps work waiting on a session that no longer exists, and two finished pull requests (the drain spec's landed marks, the fix for iss-2610110918418459) sat waiting for a ruling from it.
- iss-2610241107191205A lapsed hold or reservation must be lifted without a person, or autonomous work waits on a holder that no longer exists. On 2026-10-24 a computer that had reserved a release cut (rel-v0.15.2) and dozens of issues and intents crashed. Its leases lapsed, yet sessions on another machine kept waiting on it: one session relayed the release hold to six others as live, from a read made before it lapsed, two finished pull requests waited for the dead cut's ruling, and a build was held behind the crashed copy's work. The product thinker ruled the same day that lifting a lapsed hold is autonomous: no person is needed to declare a lapsed holder gone. The reading side already counts a reservation five minutes past its expiry as released. What is missing is that every reader, verb and agent instruction acts on that, and that spent branches leave origin without a person. This record carries the ruling that the whole path runs unattended.
- iss-2610241107435264A crashed copy strands records it reserved but never pushed, and nothing says so. After the 2026-10-24 crash, origin holds expired reservations whose footprints name records that exist nowhere on origin. Under reservation iss-2610222001116066 they are:related itd-2611041549461012
- iss-2610241110300570With seven sessions sharing one machine, a drain lane's definition of done waited over an hour at the preflight load gate ("waiting for capacity: 3 make preflights are running"), and the drain's 120-minute window elapsed while its first lane was still in progress. The gate admits one preflight at a time by default, so each session's preflight queues behind every other's: on a busy account a one-line nitpick fix takes hours to reach its reviewers. Nothing measures or reports that wait, so a run cannot tell a lane stuck at the gate from one still working.
- iss-2610241111367195abcd reserve refuses in a fresh store worktree: a worktree made with git worktree add under ~/.abcd.noindex/worktrees/<root-sha>/ has no .abcd/.work.local/, so reserve says 'nowhere to keep this copy's key; run abcd ahoy to set it up' and pushes nothing, although AGENTS.md tells every concurrent session to make exactly such a worktree and reserve before starting.
- iss-2610241130157455Plain go test runs that sessions start outside the load gate keep the one-minute load above the gate's limit, so the gated preflights starve: on 2026-10-24 three preflights of this account waited 18, 36 and 54 minutes at 'abcd implement load --wait' (load 26 to 76 against a limit of 20 on 10 cores) while three ungated 'go test -timeout 40m' runs of other sessions (internal/surface/cli, internal/core/identity and its neighbours) ran beside them, and the session filing this had itself run internal/core/implement/... and internal/surface/cli ungated earlier the same morning. The gate counts a running make preflight and a go test -race run as occupancy, but a plain go test only as load, so the runs that skip the gate are the ones that hold it shut for the runs that use it.
- iss-2610241133284600On 2026-10-24 the main checkout of abcd had no git hooks installed: core.hooksPath was unset in every config scope and the common .git/hooks held only samples, so the committed .githooks (commit-msg, pre-commit, pre-push) ran for no commit and no push made from it or from its linked worktrees. Several sessions were committing and pushing that day. Nothing said so: commits went through silently, a commit message naming an issue without a Refs: line (RS004) was accepted at commit time, and a push to origin was made with no preflight receipt, which the pre-push hook exists to refuse. The gap surfaced only because make preflight's lint-issues gate failed afterwards. How the setting was lost is not known; the setup redesign under way the same day touches the hooks. abcd ahoy reports install state but did not flag it, and no commit verb checks it before writing.
- iss-2610241134315056ahoy install reports 'clean' in a clone whose committed hooks are not armed: in abcd's own checkout on 2026-10-24 the detection pass read banlist.hooks_path as 'unarmed' (core.hooksPath unset, so .githooks/pre-commit and pre-merge-commit never run) both before and after setup, yet no gap was listed and the install summary said 'abcd is set up in this repository'.
- iss-2610241157493381TestHookSessionEndRetriesATransientRootFailure fails on an unchanged branch from origin/main (2026-10-24): the session-end hook's retry after a simulated transient git failure finds 'no time is left to ask again' and stages nothing, so the retry budget is spent before the retry on a loaded machine (several concurrent sessions and test runs); the test asserts timing-dependent behaviour against wall-clock time.
- iss-2610241158083013the shell-settings edit checks the profile file and then replaces it atomically, leaving a short window in which a symlink swapped in at the path would be replaced by a regular file rather than refused (the replace renames over the leaf, so it never writes through the link, but the person's link is lost).
- iss-2610241212094133with no git identity configured anywhere, git invents one from the account and host name and exports it into the pre-commit hook, where it reads exactly like an identity a launcher supplied, so the per-machine identity gate lets an invented identity commit when no record exists; only the Go check reports it, as git_identity.unset.
- iss-2610241212237390there is no command to write a per-repository identity record under ~/.abcd.noindex/identity/<root-sha>.json; a person with a work and a personal identity can only create it by hand or through the legacy-pin migration.
- iss-2610241212339218the shell identity gate in .githooks/pre-commit refuses any group-writable folder on the way to the identity record, which is stricter than the Go guarded reader the rest of abcd uses, so the two gates can disagree on the same record.
- iss-2610241212419547TestHostVersionWarning failed once on a timing check during a loaded test run (load average 20-28) and passed when run alone: a wall-clock assertion that depends on machine load.
- iss-2610241214065079The load gate meters only a preflight's test stages; every stage before them runs ungated. On 2026-10-24 seven sessions on one 10-core machine each ran make preflight, and all seven ran their lint gates, the smoke and cold-reading eval lanes (five to six minutes each) and build and vet at once, holding the load average near 25. Tests timed out under that load (internal/surface/cli passed go test's ten-minute default), and every preflight then queued behind one test slot, so one nitpick fix waited over an hour. Raising load.preflights to 2 widens only the test slot; nothing bounds the stages before it.
- iss-2610241214563687The product thinker wants the number of preflights a machine runs at once to follow the evidence, not stay fixed. On 2026-10-24 they set load.preflights to 2 in ~/.abcd.noindex/config.json, which applies to every abcd-managed repository on the machine, and asked that load monitoring keep it right: raised when the machine has room, lowered when it is overloaded. Today the count is a fixed number a person writes (default 1, at most 2), and the gate measures load only to decide whether to wait, never to learn: nothing records how long stages waited or ran, whether tests timed out, or what the load was, so no one can tell whether 2 is too many or too few.
- iss-2610241215547722The product thinker wants a self-optimisation function built into abcd: it monitors CPU utilisation, token use and everything else that can be monitored, and optimises the setup over time. Today every tuning knob is a fixed number a person writes (the preflight slot count, the sub-agent ceiling, the pace window, fix rounds, the review set), and nothing measures the outcomes those knobs drive, so each value is a guess that never improves. The 2026-10-24 test run, seven sessions on one 10-core machine, showed the cost: the load average held near 25, tests timed out, a nitpick lane waited over an hour at the load gate, and the sub-agent cap was negotiated by hand between sessions. iss-2610241214563687 (an adaptive preflight slot count) and iss-2610140652230444 (reviewer catch rates measured per model) are two instances of this one capability.
- iss-2610241228178135make preflight's eval lanes run go test with no -timeout, so they inherit go test's ten-minute per-package default. On a loaded machine (load 21 to 31 on 10 cores, several sessions testing at once on 2026-10-24) the smoke lane's evals package ran past ten minutes with no test hung: TestEveryCommittedEntryFitsItsDeclaredWindow alone took 128 s, and the package was killed with 'panic: test timed out after 10m0s', failing a preflight whose change touched no eval. The unit and race lanes declare -timeout 20m and 40m; the eval lanes' ceiling is a default nobody sized.
- iss-2610241228359748Which abcd runs is confusing because several installs coexist and nothing says which one wins: the plugin can be installed at user scope and at project scope at once, each with its own plugin-root binary, and there is also a PATH binary (ahoy install) and, in abcd's own checkout, a source build (go run). Observed 2026-10-24: the person updated the plugin to v0.15.1, but the update landed as a new project-scope install for this repository while the user-scope install stayed at 0.13.3, and the session went on loading the user-scope copy (command pages still named .../abcd/0.13.3/abcd, its hooks bootstrapped there at 14:23); the 0.15.1 directory had never bootstrapped and held no binary; and the binary inside the 0.13.3 directory reported v0.14.1, so even the directory name did not say which version ran. Nothing in the board, ahoy or the command pages surfaced any of this. The person wants it unified (for example: does a repository-scope plugin win over a user-scope one, and how does the CLI on PATH relate to either?). Earlier rulings each settled one rung on its own (dcn-2609080000000001 the owned-only PATH rung for the hook shims, adr-2609151706587280 the cache-to-PATH attestation, iss-2610070547057816 dogfooding a source build in abcd's own checkout) without addressing the underlying problem: no single, stated precedence across plugin scopes, the plugin-root binary, the PATH binary and a source build.
- iss-2610241229056581a piped answer stream (yes | abcd ahoy install) is never shown the new plan screen; it still meets the old one-approval-per-category order, so the scripted path and the terminal path ask different questions.
- iss-2610241234397418The private banned-names list (.abcd/.work.local/private-names.txt, the keyed store the pre-commit name guard checks) can only be filled by hand, entry by entry, so on a fresh install it starts empty and every commit warns that the guard checks nothing. abcd could propose its entries itself: review the repository, its history, its record and the person's other local material for the names that must never reach a committed file (private repositories, collaborators, clients, internal hosts and project code names), and offer them for the person to confirm. How to find such names well, and without leaking them while looking, is a state-of-the-art question (named-entity and PII detection, secret scanners, private-term mining), not one to answer from memory.
- iss-2610241235133916TestHookSessionEndRetriesATransientRootFailure fails on main whenever the machine is loaded: the session-end hook begins a retry only when its pause and a detection costed at the first detection's time end inside the 1.2-second sessionEndRetryBudget, and at a load average of 25 the first detection alone used that up, so the hook skipped the retry ('no time is left to ask again'), staged nothing, and the test failed reproducibly, on main and on a merge alike. Every make preflight on a busy machine therefore fails in internal/surface/cli, and the skip path itself had no test.
- iss-2610241239492159abcd guard has no hazard for deleting a branch or a worktree: git push origin --delete, git branch -D and git worktree remove are all allowed whatever the target holds, so the safety of a cleanup rests on the agent remembering its own checks. On 2026-10-24 a hand-run sweep's check-then-act loop invoked abcd guard check with the wrong syntax, read the nonzero exit as an objection, printed it and deleted seven remote branches anyway; the deletes were safe only because the survey before them was right, and the hook would have allowed them regardless. A guard has to be enforced at the hook, not hoped for in a script.
- iss-2610241240133009In a source checkout every abcd invocation is go run ./cmd/abcd, and go run turns every nonzero exit into 1: the binary's exit 2 (guard unevaluable, a usage error) and exit 3 (reserve: back off) both arrive as 1, the same code as a guard block. Measured 2026-10-24: guard check on an unterminated quote exits 2 as a built binary and 1 under go run. The dogfooding rule therefore makes the documented exit-code contract unreadable to the agents it governs, and a script that branches on exit 3 never sees it.
- iss-2610241240234678abcd peers lists a worktree whose branch has zero commits past an older main as merged (fix/external-review-events, created 70 minutes earlier by a live session and not yet started): an unstarted lane reads as spent work, which invites any sweep that trusts the listing to delete a peer's fresh worktree.
- iss-2610241242146829the third-party tool download rules in internal/core/tools/fetch.go are a second copy of the updater's in internal/core/update (allowed hosts, size and time limits, no proxy, CA overrides ignored), because update imports ahoy which imports tools; two copies of a trust policy drift apart.
- iss-2610241242226828at abcd ahoy remote apply and site setup any gh on PATH counts as present: only a missing gh is offered abcd's verified copy, so an incompatible older gh is used there without a word, unlike gitleaks at ahoy install.
- iss-2610241242295613a tool install is refused when the bin folder already holds a program of that name that abcd did not install, with no other route offered.
- iss-2610241256347199No verb that adds or moves a record in an indexed directory regenerates the index that lists it. Only go generate ./internal/surface/cli (cmd/abcd-gen-surface, through lint.RegenerateIndexes) rewrites the generated regions, such as the drafts list in .abcd/development/brief/06-delivery/03-out-of-scope.md and the ADR index. So filing a draft intent, planning one out of drafts/, or minting an ADR with decide --adr leaves a region stale, and record-lint's index_drift blocker refuses the next make preflight. On 2026-10-24 a hand-filed draft (itd-2610240933025076) failed preflight this way. The region then conflicted on a rebase over main, because every branch that files a draft edits the same list.
- iss-2610241300265072the Go identity reader trims surrounding whitespace from the recorded name and email but the shell pre-commit gate's sed does not, so a hand-edited record with a leading or trailing space passes abcd ahoy --identity and blocks every commit in the hook (fails closed).
- iss-2610241300370199an identity pin that holds only production_mode, or a machine identity, is owned by no one under the migration rule, so it is never removed and its production_mode never moves to .abcd/config/provenance.json, and every contributor is told the repository stores a commit identity that is not theirs.
- iss-2610241410173320A peer session took another session's uncommitted issue record into its own branch commit and removed it from the shared checkout without announcing it, so the filing session found its record gone when it came to land it and could not land it without risking a record in two status folders
- iss-2610241411469889The capture page tells the agent to ask the product thinker for a missing remedy, but the prompt that ran it did not recall the GRILL domain, so the agent asked without the question layout and the question guard refused it on five parts before the remedy question could be shown
- iss-2610241412028278A session holding several push-ready branches drives each through preflight and landing by hand: on 2026-10-24 this session had four (docs/itd-82-landed-steps, fix/landing-marks-step-landed, fix/lapsed-release-hold, fix/name-ungated-tests), and with the rule relayed that day of one preflight per session at a time it started each preflight itself, watched for the 2-hour gate timeout (three runs timed out and had to be restarted by hand), ran 'abcd land' after each that passed, and kept the order in its own notes and wake-ups. No verb holds a session's queue of branches, so the chaining, the re-queue after a timeout and the landing all depend on the session staying alive and remembering.
- iss-2610241414105439A dependabot pull request (#1105, a go-deps bump touching only go.mod and go.sum) has sat for four days failing the attribution gate, because its re-author job failed. Nothing tells a person or an autonomous session why it failed or what to do: the pull request just shows two red checks. During the 2026-10-24 run it needed a session to diagnose it and redo the bump by hand.
- iss-2610241414124940The preflight load gate can starve every waiter on a busy machine and holds its only slot for a hung command. It opens only while the one-minute load is below twice the online cores (20 on 10 cores), but the preflight stages it does not gate (lint, record gates, evals, build, vet) run before it, so seven sessions' preflights on 2026-10-24 kept the load near 25 and the gate never opened: one drain lane's preflight ended 'load gate still shut after 2h0m0s: load 20.9 is not below 20 (2 x 10 online cores); 3 make preflights are running'. Later the same day, at 14:04 UTC, the load was 8 on 10 cores and about nine preflights were still queued, their logs unchanged for 45 minutes, because the one open slot (~/.abcd.noindex/load-wait.json, form command, opened 13:19 UTC, held to 14:19) belonged to a package test run that had used about 11% CPU for 45 minutes; load.preflights was 2, yet only one slot was open, possibly because waiters started before the setting was written read one slot when they began. Nothing reclaims a slot whose holder is idle, and nothing lets the gate open when the load it waits on comes from the ungated stages of its own queued runs. Adjacent records on an unmerged branch cover the ungated stages running unbounded and the unmeasured wait, which this issue does not restate.
- iss-2610241414129778abcd capture accepts a --found-at path that does not exist in the tree without saying so: on 2026-10-24, during the setup redesign build, a capture naming a file that had not been written yet produced a record whose location points nowhere, and the mistake was noticed only later by hand.
- iss-2610241414222401Nothing counts the sub-agents running across concurrent sessions on one machine. On 2026-10-24 the person set a combined cap (8, then 10, then 12), and the sessions kept within it only by messaging each other their counts by hand: about twenty cross-session messages, guesses at each other's numbers, and one session asking permission before each start. Any session that did not hear a message could exceed the cap unseen.
- iss-2610241414414823When a copy crashes, its open pull requests stay open and drift: by 2026-10-24 two of them (#1110 and #1116) conflicted with main after 89 and 128 commits, and nothing noticed or repaired them. A session had to find them, merge main into each by hand, resolve the conflicts and queue them, while the work they carried (a major issue's fix among it) stayed unmerged.related itd-2611041549461012
- iss-2610241415121917A narrow test run waits at the load gate behind whole preflights from other sessions: on 2026-10-24, during the setup redesign build, a single-package test run queued through abcd implement load --wait sat behind several full preflights at a load average above 100, never started, and was cancelled by hand, so a few seconds of checking cost the lane most of an hour.
- iss-2610241415434937Building an issue the person has just filed takes a pull request round trip first, with nothing in the capture or build output saying so up front. On 2026-10-24 a person asked a session to capture an issue and then build it. abcd build refused three times in a row, each on a different ground found only by running it. First, the default category the capture gave the issue (observation) is outside the drain rule's fixable set. Second, the issue lane fetches origin's default branch, so a record that exists only in the working tree cannot be built at all, and the record had to go through its own branch, preflight, pull request and merge queue (a queue run that failed once on an unrelated flaky test), about three hours. Third, once it landed, the severity the capture gave it (major) is above the drain's nitpick and minor, so the issue was a person's all along. None of the three was visible when the issue was filed, and the person's intent, to file and then build, needed four round trips to learn that it could not be built.
- iss-2610241419324875A test run admitted through the load gate keeps the shared test slot for as long as its command runs. On 2026-10-24 an agent's go test -timeout 60m of the loop suite, started at 13:19 UTC, held the slot through load-wait.json for 45 minutes while about nine preflights from every session queued behind it. It was a long, slow run, not a hung one: its goroutine dump showed it still working through tests at 30 to 70 seconds each under load, mostly in git subprocesses, so its test binary showed little CPU. The waiters could not tell whether it was working; a peer session noticed and asked its owner, who stopped it. Nothing in the gate tells the waiters how the holder is doing, nor tells the holder's owner that others are waiting.
- iss-2610241423411800On a new machine or account the private banlist starts empty: install lays the store's header and no entries, and the pre-commit guard then checks nothing while printing only a warning. On 2026-10-24 a new account's guard checked no entries during a day of autonomous commits from seven sessions. The defaults it should hold are known in advance: this machine's names (computer name, local host name, the tailnet domain, interface MAC addresses), every local user account, and the names of the machines on its network. The person wants them collected by rule at each commit and each test run, not stored as a word list, so a new account, machine or device is covered without an edit. A hand-rolled prefill of seven keyed entries was written on this machine to test the guard; it refused a canary commit by key. Bare generic account names (admin, dev) cannot be word patterns: dev matches development, and the scanner's tests use [redacted-path] and dev@host as fixtures, so accounts must be matched in context (a home path, login@host).
- iss-2610241424131241abcd banlist add refuses a valid POSIX ERE that contains an escaped parenthesis followed by a question mark, such as \(?ar\)? for an optional literal parenthesis: checkPattern's static screen tests strings.Contains(pattern, "(?"), which matches the escaped form as if it were a Perl (?...) group, and the private layer refuses it as Perl-style.
- iss-2610241424265464A commit message that names an issue id without a Refs: or Resolves: line passes the commit-msg hook and is refused only by lint-issues RS004 inside make preflight. On 2026-10-24 that cost a whole preflight run (tens of minutes under the load gate) for a one-line amend, on a machine where preflight capacity was the scarce resource.
- iss-2610241424428420A build or drain lane whose footprint overlaps a peer's live reservation backs off with exit 3, and nothing tells it when the reservation is released: on 2026-10-24 a planned build waited on a drain lane's reservation of internal/core/implement/loop, and the two sessions coordinated by cross-session messages, the drain promising to say when it released. A session with no peer messaging, or a hosted one, can only poll abcd peers.
- iss-2610241426406882The after-merge fidelity audit of itd-6 could not decide a criterion, so its check is still owed: ac-1 INCONCLUSIVErelated itd-6
- iss-2610241427397332The after-merge fidelity audit of itd-3 judged a criterion unmet, so its check is still owed: ac-5 NOT_MET, ac-6 NOT_METrelated itd-3
- iss-2610241430042742abcd reserve refuses every shipped intent as finished on origin's default branch (exit 3, nothing pushed), yet an owed fidelity review writes into the shipped intent's file (its Audit Notes block) and can capture an issue, so the work an intent audit drain does can never be reserved, despite the AGENTS.md rule to reserve an intent before working on it. Two sessions paying owed reviews, or running intent condition, can pick the same shipped intent and each spend a whole review on it, with only the ingest's replace-or-noop keeping the record whole. Seen on 2026-10-24: reserve itd-3 before its owed audit exited 3 with 'itd-3 is finished on origin's default branch'.
- iss-2610241430326301The intent-auditor definition's output rule 1 (agents/intent-auditor.md) says a reply with zero or two fenced json blocks makes the ingest fail the receipt closed, every criterion recorded INCONCLUSIVE, but intent audit ingest --verdict-json decodes the file as bare JSON (internal/core/intent/audit.go, IngestVerdictBytes) and refuses a fenced reply as not parseable JSON, writing nothing, and commands/intent.md tells the host to save the single JSON block without saying the fence lines must go. Only the provider route strips a fence (internal/adapter/openaiapi/client.go, unfence). A host that saves the auditor's reply as it came back is refused, and the fail-closed path the auditor is told about does not exist on the harness route. The consistency ingest decodes bare JSON the same way.
- iss-2610241431221889The after-merge fidelity audit of itd-24 judged a criterion unmet, so its check is still owed: ac-2 NOT_MET, ac-7 NOT_METrelated itd-24
- iss-2610241457170255The quiet-holder notice of iss-2610241419324875 still leaves waiters unable to tell how a load-gate holder is doing in the case that prompted it. A slow holder whose tree keeps starting short git children counts as working and is never reported, which was the 45-minute run of 2026-10-24; silence is no positive sign that a holder is working, since a waiter that joined in the last ten minutes has not measured it yet; only a same-account hold record is watched, so a holder seen only in the process table (another account's waiter running its command) is never named; and each waiter needs ten minutes of its own samples before it can say anything.
- iss-2610241518233773The product thinker asked how a memory page larger than the recall's per-turn budget (about 64 KB) could come about, and why one would be needed. Pages are written by abcd library ingest, which fetches up to 10 MiB of a source, distils it into pages through a model, and writes them, and by hand; nothing holds a page to the recall's budget, and the store reads pages up to 4 MiB. So a long paper or web page can become one oversized page that the recall then sets aside, as PR #982 builds it. No such page is needed: the limit belongs where the page is made, not where it is read.
- iss-2610241519088123The host still cancels abcd's SessionEnd hook on a loaded machine, so the session's transcript is neither staged nor stored, and nothing says so. On 2026-10-24, at a load average of about 21 on 10 cores, session ad158fbf ended with 'SessionEnd hook [sh .../hooks/session-end.sh] failed: Hook cancelled' under the 0.15.1 plugin, whose hook is identical to the current source; its 559 KB transcript reached neither the staging area nor the store, though the host's own copy is still on disk. The host gives a SessionEnd hook 1.5 seconds in all, and a timeout set in a plugin's hooks.json does not raise it (the host's hooks reference, read 2026-10-24). Before it stages anything, hook session-end detects the repository through ahoy.Detect and git, with up to two retries inside a 1.2-second budget; under this load starting the binary alone takes about 0.36 s and each git call about 0.15 s. The August fix (iss-2608230817034768) took redaction off the exit path but left this lookup on it, and the comment at internal/surface/cli/hook_subagent.go:95-110 says the hook could ask the host for more time, which the reference says a plugin hook cannot.
- iss-2610241524383006make preflight's smoke lane runs before the load gate under go test's default ten-minute timeout, and at a one-minute load of 18 on ten cores the whole evals package ran out of time (TestEveryCommittedEntryFitsItsDeclaredWindow among the tests still running), failing a records-only branch's preflight after about twenty minutes
- iss-2610241529139689Setting up the reservation sweep's GitHub App took the product thinker about twenty minutes of wrong turns on 2026-10-24. The only instructions are hand steps in the sweep's design record, and GitHub has since moved them: private keys now sit under Credentials, then Key pairs, and installing an App owned by one organisation skips the choice of account. Nothing checked what already existed: an earlier App, the environment's branch rule and both secrets were set up on 2026-10-17, and only the ruleset's bypass actor was missing, so a second App was created and the first is now orphaned. The person asked for the setup to be precise; it should not depend on a person following settings pages at all.
- iss-2610241537197997Concurrent preflights on one machine all fail: on 2026-10-24 a records-only branch's preflight reached its test stage while six other preflights and several direct test runs shared a 10-core machine at a load near 20, and six packages (cloudscripts, ahoy, autonomy, claim, embargo, implement/loop) hit their 20-minute per-binary timeouts, so the run failed on nothing its own change touched. The load gate admits each preflight's test stage once the load dips under its limit, and the stages before it run ungated, so every admitted run then competes with the rest and none can finish inside its timeouts. Wrapping the whole run in the gate's command form, which one session found by hand, serialises them.
- iss-2610241544410026The product thinker asked for the forge settings abcd depends on to be captured as verbs and nouns, with clear, verified steps and direct URLs, after a hand setup of a GitHub App on 2026-10-24 went wrong on stale instructions. The verified catalogue is the research note .abcd/development/research/notes/2026-10-24-forge-settings-catalogue.md: 21 settings, each named forge-neutrally (default-branch protection, release-tag protection, reservation-branch protection, deploy environments and their secrets, automation apps and their bypass, and the rest), its live state read through the API, GitHub's current documented steps quoted, and its direct settings URL. The product thinker named the verb family abcd git, so that GitLab and other forges can be configured in a later update, depending on what the user hosts on.
- iss-2610241544441841The default-branch protection's required checks differ between the committed mirror and the live ruleset: .abcd/work/rulesets/main-protection.json and the comment in ci.yml require wip-guard, but the live ruleset (id 19969675) requires nine checks without it, matching the rulesets README's count. The live ruleset was last changed on 2026-10-11, before the commit that added wip-guard to the mirror on 2026-10-15, so the mirror records a requirement GitHub does not enforce.
- iss-2610241544508861The default-branch review rule differs between the committed mirror and the live ruleset: the mirror and the rulesets README record an admin bypass, but the live ruleset (id 21045110) has none, and its history shows the bypass was removed on 2026-08-24. The owner's pull requests still merge without a review (#1119 touched code-owned files), so the README's explanation of why is wrong, and the live ruleset carries a setting the mirror lacks.
- iss-2610241549052683Twelve decisions are recorded twice, under two ids with byte-identical bodies: dcn-2609290000000011 and dcn-2609290000000020 (the Group J rulings, J12 among them), dcn-2609290000000012 and dcn-2609290000000021 (ruling J13), and ten more pairs dated 2026-09-27 to 2026-09-30. The old .abcd/work/DECISIONS.md already held each of these entries twice before c2fdca9e1 migrated every entry into a record of its own, so each duplicate became a second record. None of the twelve higher ids is cited anywhere, but abcd decide lists each ruling twice and a reader cannot tell which id is the record.
- iss-2610241549107888The root machine records index in .abcd/README.md lists five config/ records and two optional absent ones (pii.json, scripts-closure.json) but not config/oracle-routing.json, an optional record the shipped binary reads and ahoy offers to write (internal/core/ahoy/oracle_routing.go:14, :51), nor the other optional config/ records added since, so the index a reader starts from lags the directory it indexes.
- iss-2610241549164432Draft itd-165 still says an inconclusive verdict deliberately creates no record and that no audit verdicts exist yet (.abcd/development/intents/drafts/itd-165-an-intent-that-fails-its-own-fidelity.md:24, :26), while ruling DQ1c superseded the first reading (dcn-2609300000000027), commit b68b3d402 built an issue filed for every failed or undecided after-merge audit, and 119 shipped intents now carry acceptance rollups. The draft reads as the plan for behaviour that already ships differently.
- iss-2610241549220956commands/reading.md:202-203 says exceeds_window is what the cold-reading eval lane fails on, but since c738e111e the window eval logs a breach as a warning and passes (evals/coldreading_window_test.go:4-10, :73), on the product thinker's ruling of 2026-10-12. That ruling has no decision record; it lives only in the commit message and the test's comment.
- iss-2610241549275970commands/library.md:319-321 tells the agent that the lifeboat licence gate governs a kept original's export. The brief's 05-internals/07-memory.md:118 and the Memory ingest row of 06-delivery/02-verification-matrix.md:86 say that gate refuses to publish one without an allowlist entry. No such gate exists: disembark packs no memory (internal/core/lifeboat/plan.go copies only ADRs, issues, specs, retrospectives and intents), as the brief's own 04-surfaces/07-library.md:358-363 says.
- iss-2610241549334990A spec's Footprint packages line is reserved exactly as written. An entry carrying a note or prose therefore becomes a footprint path with that text in it. A build of spc-2610111627213138 would reserve internal/core/memnote (new). A build of spc-2610120941441282 would reserve internal/surface/cli (the pre-push hook's fixture tests), and its parenthetical containing a comma would split into the two entries scripts/cloud/connectors/claude (new and the host connector). Overlap compares paths segment by segment, and claim.ValidFootprintPath accepts spaces. So such an entry shares no path with the package it means, and the build does not hold that package against another build. Several open specs carry such entries, among them spc-2609221011151661, spc-2610111627213138 and spc-2610120941441282.
- iss-2610241549396753The remedy of iss-2610171626398856 (the v0.15.1 release review) asks for iss-2610161639025702 and iss-2610161756384596 to be resolved, as if the two-preflight work had delivered them. Neither ask has shipped. Deriving the preflight count from the machine's resources is still named a later step in internal/core/implement/load_slots.go:37-39 and in the brief (04-surfaces/27-implement.md:373-374). iss-2610161639025702 asks for more than the trial, including merge batching and test stages that run only the packages a change can affect. Following that remedy as written would close two open asks.
- iss-2610241549433260Five open records carry remedies that name verbs or pages itd-2610090831227812 retired with no alias on 2026-10-09: iss-25 and iss-52 name abcd source add (iss-52 also source ledger), and iss-92, iss-2608210934566220 and iss-2610040350491915 name prepare-this-repo, so a lane applying any of them targets a command that no longer exists; nothing checks a remedy against the retired names.
- iss-2610241549487283The identity package comment says the installed pre-commit hook calls Check to fail closed before a mis-attributed commit can land (internal/core/identity/identity.go:5-9), but no hook calls identity.Check: its only callers are ahoy's detection and the CLI's ahoy --identity, this repository's .githooks/pre-commit carries a self-contained shell twin, and the pre-commit ahoy scaffolds into a managed repository (internal/core/ahoy/defaults/pre-commit) has no identity gate at all, so a managed repository has no commit-time identity check.
- iss-2610241549531180abcd land pushes the branch (internal/core/landing/land.go:315) before it reads whether the branch's pull request is armed and in the merge queue (enqueue, land.go:1183), so re-running land after a new local commit pushes to a queued entry, the dropped-push hazard iss-2609181223354098 records, and the run then reports the arming as already in place.
- iss-2610241549584964The product thinker's 2026-10-12 ruling that a reading-window breach warns and never blocks a merge exists only in commit c738e111e and the comment at evals/coldreading_window_test.go:9; no decision record holds it, so a search of .abcd/work/decisions/ for prior rulings misses it, and iss-2609210748032488 still reads as waiting on the M33 margin interview for a check that no longer refuses anything.
- iss-2610241550026188record_schema resolves a cross-reference field's target in any record family (internal/core/lint/schema.go:764 checks only that the handle is in the corpus), so itd-2609221842494980 carries related_adrs: [iss-2609221820487644], an issue, and passes record-lint, although the ADR README documents related_adrs as adr-N only; because the link sits in the wrong field, the promote join between that shipped intent and its still-open originating issue is invisible to intent audit --issue-drift.
- iss-2610241550073708spc-57's acceptance-criteria mapping and Tests section name six tests that no longer exist: TestCaptureReaderAcceptsGroundsKey and TestRecordSchemaFlagsOutOfVocabularyGrounds, replaced by 8a97c281e the day before the spec closed, and TestPromoteRefusesWithoutGrounds, TestPromoteWithoutGroundsWritesNothing, TestResolveRefusesWithoutGrounds and TestCapturePromoteMissingGroundsExit2, removed by 667a57f4f when dcn-2609090000000001 parked the grounds refusals; the mapping still says promote refuses without grounds.
- iss-2610241550119108ahoy install's re-founding lineage question tells the person that No and decide-later write nothing and that the next install asks again, but declining registers this root as a new project in the session store's index, and no later install asks again, because the question is put only while the root is unregistered.
- iss-2610241550154898commands/ahoy.md lists the kinds of id an answers file may answer (a value question's key, adopt, approve.<category>, an offer's gap id) but not history.lineage, the id the re-founding lineage question is answered by, and does not name the lineage question among the questions checked only when they are asked.
- iss-2610241550202749AGENTS.md's Single repo, curated release boundary, .abcd/work/CONTEXT.md:44-47, .abcd/README.md:4 and .abcd/development/README.md:3-5 still say .abcd/** is present in marketplace installs and that the launch bundler's structural deny has yet to run on a cut release. Since adr-2609231048308186 the marketplace catalog pins each release's plugin archive (.claude-plugin/marketplace.json names abcd-plugin-v0.15.1.zip), and RenderPluginArchive renders that archive through RenderPayload and the bundle's structural deny of .abcd/** (internal/core/launch/archive.go:116-132, internal/core/launch/render.go RenderPayload, internal/core/launch/bundle.go:8-10), so a marketplace install now carries no .abcd/ tree and the deny runs on every cut.
- iss-2610241550257430When the site build inlines an SVG picture, the alt text the docs page gives it is dropped: the SVG branch of the asset renderer (internal/core/site/assets.go:425-432) returns the drawing wrapped in a span and never uses alt, so the picture's accessible name on the site is whatever the file itself declares (docs/explanation/artefacts.md:13 gives The brief while docs/assets/img/artefact-brief.svg declares brief), and nothing requires an inlined SVG to declare a name at all, so a drawing without one would reach the site unnamed while its page's alt is discarded.
- iss-2610241550303964The lint brief states the wrong exit codes for the two tree gates. .abcd/development/brief/05-internals/06-lint.md:48 says record-lint and abcd lint docs follow the tri-state grammar, blocker 2, warn 1, clean 0, and the severity table at line 34 says a warn finding raises the exit code to 1. The code does neither: cmd/record-lint/main.go:144 exits 1 on any blocker and 2 only when the lint could not run, internal/surface/cli/cli.go:955 makes abcd lint docs exit 1 on a blocker, and neither gate raises its exit code for warnings alone. The 2/1/0 tri-state belongs to bare abcd lint (internal/surface/cli/lint.go:76). A CI job written from the brief that keys on exit 2 for a blocker would pass a tree full of blockers.
- iss-2610241551259104The after-merge fidelity audit of itd-2610030720038073 judged a criterion unmet, so its check is still owed: ac-6 NOT_METrelated itd-2610030720038073
- iss-2610241604049754The after-merge fidelity audit of itd-2610030810350727 could not decide a criterion, so its check is still owed: ac-6 INCONCLUSIVErelated itd-2610030810350727
- iss-2610241606415232The marketplace catalogue's plugin description (.claude-plugin/marketplace.json: 'Host-agnostic configuration layer for development — a single Go binary, usable as a plugin in compatible agent harnesses.') tells a different story from the plugin manifest's (.claude-plugin/plugin.json: 'For people who know what they want to build and need help shipping it. A single Go binary that carries the why from idea to shipped reality, usable as a plugin in compatible agent harnesses.'), and the catalogue is not among the identity surfaces abcd identity checks, so the drift is invisible to it. Found while verifying the triage of iss-2608220150157505, whose registered surfaces all agree.
- iss-2610241613191748The after-merge fidelity audit of itd-2610111707085098 judged a criterion unmet, so its check is still owed: ac-13 NOT_METrelated itd-2610111707085098
- iss-2610241722201794The product thinker asked for every shell script in abcd to be reviewed for which should be built into the Go binary, so abcd can run on other systems, Windows among them. Today abcd's behaviour leans on POSIX shell in about fifty places: 37 tracked .sh files (14 under scripts/cloud, 13 gate and helper scripts under scripts/ such as check-attribution, check-issue-resolution, check-reviews, check-wip-source, check-vcs-stamp, preflight-receipt, pinned-toolchain, pr-keep-current and dependency-reauthor, and 10 plugin hooks under hooks/, bootstrap.sh among them); five git hooks in .githooks/ and their four templates in internal/core/ahoy/defaults/, all POSIX sh; the install script template under site-src/; and the Makefile that runs preflight. Each needs a POSIX shell, and many need GNU or BSD userland tools, so none of them runs on a stock Windows machine, and a Windows build of the binary alone would leave the gates, hooks and preflight behind.
- iss-2610241829569682TestReadOwedHonoursDeadline (internal/core/autonomy/owedread_test.go:1198) failed in a preflight on a loaded machine on 2026-10-24 (load near 20, other preflights running): the read it cut short came back with incomplete false while its notes said 'the local branches could not be listed | the pull requests were not read (the forge did not answer within 10s), so the check judged from disk', so either a read cut short under load does not mark itself incomplete, or the test's deadline races the machine. A test that fails under load blocks every preflight that meets it, whatever the branch changed.
- iss-2610241911001655Two tests fail under machine load rather than on a defect: TestReadOwedHonoursDeadline in internal/core/autonomy found the read marked complete when the forge timed out, and TestHookSessionEndRetriesATransientRootFailure in internal/surface/cli ran out of retry time and staged nothing, both during a gated preflight at load 17 on ten cores
- iss-2610241911052191The load gate opened a whole make preflight at load 17.8 on ten cores, under the 20 threshold, yet three packages (internal/core/claim, internal/core/implement/loop, internal/surface/cli) then hit the twenty-minute test timeout, because the other sessions' ungated stages kept the load near the threshold for the whole run
- iss-2610241920339387The load gate queues a seconds-long command behind whole preflights: on 2026-10-24 'abcd implement load --wait --timeout 1h -- go test ./internal/core/spec/ ./internal/reachaudit/', two packages that run in about five seconds, waited the full hour behind four to five waiters and timed out without running, because the gate admits one command at a time in start order whatever its size. With the rule that day of no go test outside the gate, a session had no gated way to check a small change before re-queuing a full preflight, so it either skips the check or breaks the rule.
- iss-2610242109545682After the setup redesign, several setup descriptions are incomplete rather than false: the brief's abcd home tree omits identity/, tools.json and shell-path.json and says backups/ holds only the assistant's settings; the uninstall summary omits that uninstall removes the shell PATH line and abcd's own tool copies; the tool paragraph omits the owned-copy upgrade offer; the --yes help text does not list the shell settings, the commit checks or tools among what it skips; and the public install how-to simplifies which bash startup file is edited.
- iss-2610242115122817The rule for downloading a verified release now exists twice: abcd's own update path (internal/core/update) and the new tool installer on the setup redesign branch each decide which hosts may be reached and how a download is bound to its release, so any fix to that rule must be made in both and can drift between them.
- iss-2610250007404944Every preflight on this 10-core Mac fails its unit stage at the 20-minute per-package budget: on 2026-10-24/25 six preflights in a row, from three sessions and through the gate's command form at a load of 5 to 7, ended with internal/core/claim, internal/core/implement/loop and internal/surface/cli each killed at 1200s with no test hung (each dump shows one test a few seconds in). The same packages take 260s, 633s and 535s on CI's Linux runner and implement/loop took 1830s in macOS CI's race pass, so the budget set on 2026-10-17 from one ten-minute run no longer fits macOS, and no preflight here can mint a receipt.
- iss-2610250013552001abcd reserve, run from a sibling worktree of the checkout that holds a person's live reservation, refuses with 'you are already building <id> on another computer', and the release merge hold reads 'being cut by your copy on another computer' the same way. The copy key lives in each worktree's own local tier, so every worktree is its own copy and the words are false for the commonest case, a second worktree on the same machine: on 2026-10-25 a renewal from the lane's worktree was refused that way, and only trying the main checkout found the copy that held it. The footprint refusal does not say that a renewal by hand, the same command again, names the footprint too.
- iss-2610250107576049The stop hook's wake tests read the real clock in the machine's local zone, so they fail during a daylight-saving fall-back's repeated hour. Cron.Next (internal/core/autonomy/cron.go) deliberately never matches a repeated wall-clock minute, so between 02:00 and 03:00 CET on 2026-10-25 a */10 or */30 task had no match until 03:00. TestHookStopOutput, TestHookStopWakeCountAcrossRuns and TestHookStopRecordsHandBack (internal/surface/cli/hook_stop_test.go) then failed in make preflight on every branch, at any load. They pass with TZ=UTC and again after the hour, while CI (UTC) stays green. The hook itself shares the behaviour: for that hour a session sees no qualifying wake for any recurring task.
- iss-2610251004378066internal/core/implement/loop outruns even the unit stage's new 40-minute package budget on this Mac: its 505 tests run one after another in one test binary, and on 2026-10-25 a preflight killed it at 40m00s with no test hung (the test running at the alarm was three seconds old), after a gated run of the package alone took 3590s at a load of about 13. The time is spread across the suite, not in a few tests: the ten slowest are 17% of it and the median test takes 4.4s, so no single fix shortens it. On CI's dedicated macOS runner the same package takes 1830s under -race, 76% of that budget. Almost every test sets HOME and git's environment through t.Setenv in the shared git fixture (gittest.NewRepo), and the production code reads them from the process, so the tests cannot run in parallel without threading the environment through about 30 to 40 files.
- iss-2610251201361740The session-end hook's retry of a transient repository-root failure has a 1.2-second budget, so on a loaded machine the first detection uses it all and the hook never retries: on 2026-10-25 TestHookSessionEndRetriesATransientRootFailure failed this way at a load near 20, and the same budget applies to real session ends, where the transcript store step is then skipped.
- iss-2610251203588744This session (abcd-58) captured and fixed three load-sensitive test failures as three new records on fix/unit-stage-budget, without first running abcd peers or checking the peer branches. A peer's chore/capture-holdups-3fee already held the same finding, iss-2610241911001655, reserved at 10:01 and fixed in the same three files. So the work was done twice, and the two branches would have conflicted. The duplicates were dropped before anything was pushed.
- iss-2610251555094324make preflight cannot land a one-record change on a busy machine: on 2026-10-24 a branch whose whole diff is one new issue record (iss-2610241228359748) ran preflight twice, every gate before the test stages passed both times, and both runs then waited the load gate's full two hours (abcd implement load --wait --timeout 2h) behind two to four running preflights and six to eight queued waiters, and failed with 'load gate still shut after 2h0m0s'. With no receipt the pre-push hook refuses the push, so a change that touches no Go code waits behind the full test and race stages of every other session and in practice cannot be pushed.
- iss-2610251557417359The user page's self-provisioning paragraph is held to nothing. TestSelfProvisionParagraphsMatchTheShippedSets and TestTheBriefNamesSessionEndAsTheBootstrapException read only the two brief chapters (internal/surface/cli/hooks_selfprovision_count_test.go:74-85, hooks_selfprovision_test.go:410-443), so 5d754f95b updated the brief when it wired Stop and StopFailure without a bootstrap rung, and docs/how-to/install.md:79-91 kept naming session end as the only hook that never downloads.
- iss-2610251557469666docs/how-to/install.md:82-85 gives the limits of the bootstrap attempts made when a message is sent and before a command or a compaction, and leaves out the attempt made after a question is answered: the PostToolUse hook on the question tool (hooks/hooks.json:39-50, hooks/post-tool-use.sh) also calls bootstrap.sh when the plugin root is empty, under the host's ten-minute default, since it declares no timeout.
- iss-2610251557502327docs/how-to/install.md:253-255 says that while ~/.abcd stands no tool runs at all in an agent session, because the safety check blocks every command, the rename included. That holds only while the plugin root is empty, the state a plugin update leaves, since hooks/pre-tool-use.sh exits 2 before any bootstrap. With a binary in the plugin root, abcd guard hook admits the exact rename command (internal/surface/cli/homestop.go:102-109, :143-160; internal/abcdhome/abcdhome.go:45-48), and the hook gates only the shell and question tools (hooks/hooks.json:29), so other tools still run.
- iss-2610251557562067docs/how-to/install.md:530-535 says the script served at /install.sh does what the one-liners do and one thing more, recording the release-mark. The script also takes --bin-dir DIR (site-src/install.sh.tmpl:53-55, :311-332) and prints the PATH line when the install directory is not on PATH (:300-308), neither of which the one-liners do (docs/how-to/install.md:484-485).
- iss-2610251558011105docs/how-to/upgrade-to-v0.12.0.md:25 and :38-41 state two v0.12.0 facts as if current. The run log is ~/.abcd.noindex/runs/<root-sha>/<date>.jsonl since v0.13.0 (internal/core/implement/run.go:41), and the next implement step or receipt writes the run state at the running binary's schema version, 13 in v0.15.1 and 14 on main, not 8 (internal/core/implement/loop/state.go:192-194). The page does not say either moved.
- iss-2610251558069765docs/how-to/upgrade-to-v0.13.0.md:45-47 says abcd ahoy names any worktree the repair left unlinked. The check is raised only inside a git repository (internal/core/ahoy/detect.go:111-119 gates detectStoreWorktrees on the folder kind, though its gap is scope machine, store_worktrees.go:128), so abcd ahoy run in the same plain Terminal window, typically the home folder, reports nothing about worktrees.
- iss-2610251558110452docs/how-to/upgrade-to-v0.14.0.md:103-108 gives the /abcd: menu and the agents-only pages as v0.14.0 had them, in the present tense. Since then the menu also lists embargo (v0.14.2), land (v0.15.0) and status (v0.15.1), and the agents-only pages include memory and reserve (v0.14.2) and announce (v0.15.1) (internal/surface/cli/helpgroups.go:120-155; commands/*.md block and user-invocable frontmatter).
- iss-2610251558166678docs/how-to/upgrade-to-v0.14.0.md:33-34 says /abcd:memory runs instead of refusing from the release that reuses the name. The page is agents-only (commands/memory.md:6, user-invocable: false), so a person who types /abcd:memory still gets the host's refusal; only an agent's invocation runs it, and it runs the memory-notes page. Same paragraph as open iss-2610151422157749 (release v0.14.2 unnamed; abcd memory ingest refusing without naming library).
- iss-2610251558207168docs/how-to/README.md:8-11 lists upgrade guides for v0.12.0, v0.13.0 and v0.14.0 only. v0.15.0 is also a breaking release (CHANGELOG.md:82-84): bare abcd decide records a decision and an ADR needs --adr, and ahoy install's --outbound-hook and --outbound-forge are refused at exit 2 in favour of --outbound (internal/surface/cli/ahoy_retired_flags.go:11-14). A script written for v0.14 has no guide.
- iss-2610251558250996docs/how-to/README.md:10 summarises the v0.13.0 guide as the folder rename, the worktree repair, the both-folders recovery and the block refresh. Its sections 'Route a role to a runner from your own settings' (upgrade-to-v0.13.0.md:90) and 'Keep your project's conventions in AGENTS.md' (:115) are not named, so a reader looking for the CLAUDE.md move cannot find it from the index.
- iss-2610251558295790docs/README.md:11 says reference/ holds config, schemas and the CLI reference. No page under docs/reference/ documents configuration keys or file schemas; it holds writing-style.md, terminology.md and cli/, as docs/reference/README.md:6-7 says.
- iss-2610251558325834docs/explanation/README.md:3-5 says the section covers the transport-agnostic core, the host-delegated design and the abstraction boundary; none of its four pages does. Line 10 summarises roles.md as the product thinker and the technical facilitator, while the page covers three roles.
- iss-2610251558360735docs/explanation/rationale.md:3 says abcd's bet is a small team of two roles; docs/explanation/roles.md:3 says abcd is built for three roles, per ADR-2609151528057260, whose Context retires the two-person-team description.
- iss-2610251558404922docs/explanation/artefacts.md:19 says an intent is filed as shipped once its acceptance criteria are verifiably met. That holds on the build loop's closing lane, where an unmet or undecided audit fails the round (internal/core/implement/loop/validate.go:129,186-205). A spec closed by hand ships the intent first and the audit follows; an unmet criterion then leaves the intent in shipped/ with an owed check and an issue (internal/core/intent/audit_owed.go:9-21, ruling DQ1c).
- iss-2610251558434724docs/reference/terminology.md: three crosswalk positions no longer fit their own label definitions once the stale facts are corrected, and need a ruling rather than an edit. Durable execution stays WATCHING although the pacing intent (itd-2609201925079472, shipped) checkpoints lanes to their branches and abcd build resumes a run from its state file (internal/core/implement/loop/ratelimit.go:3-20, loop.go:825; internal/surface/cli/build.go:103). Agent2Agent stays WATCHING although its tracking record itd-33 is superseded by itd-2609091034175565, so no live entry tracks it as the label requires (terminology.md:13-14). Orchestration says the orchestration-substrate role is declined while abcd's own implement loop sequences a run's agents and gates each stage on its receipt (internal/core/implement/loop/budget.go:11-13).
- iss-2610251558471369docs/reference/terminology.md:58 maps Memory onto the library's .abcd/memory/ store only and omits memory notes, the abcd feature closest to the established meaning: abcd memory add keeps a lesson with its recall words on the machine or, once promoted, in .abcd/memory.json (internal/core/memnote/layers.go:13), and the rules loader brings it back into a session when a prompt matches (internal/core/rules/inject.go:40-43). The glossary gives 'memory' as memory-note's alias (.abcd/development/brief/glossary/core/memory-note.md), so the row's use of the word disagrees with the canonical vocabulary. Its 'single writing curator' names no shipped component: the host session distils the pages and abcd library ingest writes them (commands/library.md:310-313), and principle-distiller, the curator the brief names, feeds disembark principles (agents/principle-distiller.md:3).
- iss-2610251558513511docs/reference/writing-style.md:53 and :55 tell a page to link a repo-specific term of art to its terminology.md entry, but terminology.md crosswalks established agentic-AI vocabulary and holds no entry for most of abcd's own terms (intent, spec, receipt, lifeboat); the one canonical glossary is .abcd/development/brief/glossary/ (its README:5-7), which is not user-facing. No docs page links terminology.md at a term's first use, so the rule cannot be followed as written.
- iss-2610251558557436docs/reference/writing-style.md describes its own standing in three ways the repository does not bear out: (a) lines 21-23 say a new rule enters as a warn and is promoted once the corpus is clean, but punctuation/em-dash-in-list-item (fb5ac85ea) and roles/retired-role-word (b4df4f25d) were armed at blocker in the change that cleaned the corpus, and only link_anchors entered warn-first (internal/core/lint/linkanchors.go:16-21); (b) lines 3-5 say other surfaces point at the guide rather than restate it, but the bundled DOCUMENTATION rules domain restates four of its rules (internal/core/rules/defaults/rules.json); (c) lines 87-90 list the rules without a line escape and omit persona_registry, which reads none (internal/core/lint/persona.go:65-85).
- iss-2610251558595210docs/reference/README.md:3-4 presents the reference folder as describing configuration keys, environment variables and file schemas, and no page ever has: the folder holds the generated command reference, the writing style guide and the terminology crosswalk (the wording dates from 157e3ac1f). The proposed fix narrows the line, but the gap stays: keys a person sets by hand, such as load.preflights and reservation.github_username in ~/.abcd.noindex/config.json or rules.force_refresh_every_n in .abcd/config.json (internal/core/rules/inject.go:339-343), are documented only inside command help.
- iss-2610251559033353abcd capture --help and docs/reference/cli/commands.md:492 render the remedy flag as --remedy abcd capture remedy the proposed fix, one line (required); abcd capture remedy rewrites it later. The usage string at internal/surface/cli/cli.go:5322 backquotes abcd capture remedy. pflag's UnquoteUsage takes the first backquoted span as the flag's value placeholder, so the placeholder reads as a command instead of string. This is the class iss-2608301212428844 resolved for --grounds. TestGroundsFlagUsageRendersAStringPlaceholder (internal/surface/cli/capture_surface_test.go:1220) pins only the three --grounds flags, so --remedy slipped through. It is the only such placeholder on the page.
- iss-2610251559060083The ahoy install --yes help at internal/surface/cli/cli.go:4261 (docs/reference/cli/commands.md:135) says --yes excludes 'the optional git-identity pin, the status line and the model-tier routing tables, which need an answered prompt (run without --yes, or answer every prompt with: yes | abcd ahoy install)'. Under --yes the install also leaves the README question, the drain eligibility record and the removal of a conventions file that only repeats AGENTS.md: optionalGapIDs (internal/core/ahoy/apply.go:2359) lists them, and optionalSkipped returns every pending one under Yes (apply.go:2378-2381). Those three are asked only at a terminal (terminalOnlyGapIDs, apply.go:2366), and piped stdin is not a terminal (stdinPrompter.AtTerminal, cli.go:4766), so the advised yes | abcd ahoy install never answers them. The install's own result already says so (optionalSkipReason, cli.go:4597-4614). The drain-rule (a101c59d1) and conventions-file (c97f6807b) offers joined the list after the help was worded (db74fb520), and so did the README parts (13615ee16).
- iss-2610251559107915abcd build next --help (internal/surface/cli/build.go:303-310; docs/reference/cli/commands.md:417-425) defines the candidates as the planned intents that pass every abcd build <itd-N> check, 'less one this checkout already has a run in progress for'. It also says a part whose section is absent reads zero, with the reason saying the spec carries no footprint. In a checkout with a remote named origin, candidatesAt excludes, before any scoring, an intent whose spec's ## Footprint names no packages, at the check footprint (internal/core/implement/loop/next.go:149-186), so such an intent is never scored. Commit 6eb4ac9c0 added the exclusion and documented it in commands/build.md:193 and the brief, but left the CLI help unchanged.
- iss-2610251559136898Five sentences in internal/core/surface/sentences.go name less than the verb writes; each renders on the verb's help and on docs/reference/cli/commands.md. (1) ahoy uninstall (sentences.go:47; page 158) says 'Writes the removal of the marker block, PATH copy, and provenance record'. Uninstall also removes the README parts (internal/core/ahoy/apply.go:2196, readme_apply.go:454) and restores the harness's status-line command (apply.go:2201, statusline_apply.go:280-310). (2) capture resolve and (3) capture wontfix (sentences.go:88, 92; page 672, 714) say 'Writes the moved record'. The transition also repoints every relative markdown link in the working tree that named the old path (internal/core/capture/workflow.go:715; internal/core/relink/relink.go:1-4). (4) build next (sentences.go:63; page 411) leaves out the reservation its start pushes to origin (internal/core/implement/loop/loop.go:412), which build's own sentence names. (5) docs fidelity (sentences.go:125; page 1141) says 'Writes drafted edits only with --apply', yet --autonomous applies them too (internal/surface/cli/docfidelity.go:128). Same class as iss-2610160608444348, which holds the drain sentence.
- iss-2610251559163141The shared --route help (internal/surface/cli/route.go:86-91) says 'each invocation dispatches one', and it renders for disembark principles, press-release and review (docs/reference/cli/commands.md:1033, 1052, 1083). Run without its payload flag, each of those verbs runs its deterministic mode and dispatches no agent (delegatedAgent, route.go:73-78). It then refuses --route with exit 2 (route.go:115-120). Only graveyard, whose --lessons-json is required, always dispatches one.
- iss-2610251559204442disembark probe, plan and pack share one --include-ignored help (internal/surface/cli/cli.go:1332; docs/reference/cli/commands.md:1002, 1020, 1070), and it promises '(widens the scan; the report says so)'. probe's coverage report prints 'scope: WIDE' (internal/core/lifeboat/coverage.go:114-116), and pack writes that report into the lifeboat (plan.go:226-230). plan's output, text and --json alike, is the PlanManifest (plan.go:402-410; RenderManifest 434-450), which carries no scope, so abcd disembark plan --include-ignored says nothing of the wider scan.
- iss-2610251559234988abcd drain --help (internal/surface/cli/drain.go:54-55, generated into docs/reference/cli/commands.md:1190-1191) says of a promoted issue that 'a person's own abcd build <iss-N> still takes it'. Since 6d4307058 a person's build takes a promoted issue only when no other rule would hand it back; one that another rule holds (security, category, severity, 'Waits on', a deferral, no remedy) is refused with that rule's reason (internal/core/implement/loop/check.go:219-230, 251-286). That commit updated commands/drain.md:155 but not the help string, so the reference tells a person that build takes a promoted security or major issue it refuses.
- iss-2610251559275506abcd drain --help (internal/surface/cli/drain.go:141-142; commands.md:1281-1283) lists the waits a lane's refusal count never includes as 'the wait for a preflight receipt, an outage's wait, and a land fence that cannot read origin'. Since b15e2e48a a land fence held by another person's release cut is a wait by design too and is never counted toward stuck (internal/core/implement/loop/stuck.go:118-120; refusal.go:57-60; reservation.go:331-339). The commit did not touch the help, so a person reading the list expects a lane held by a release cut to be handed back as stuck after three refusals or sixty minutes, and it never is. The header comment of stuck.go:15-17 lists the same three.
- iss-2610251559309480abcd drain --help (internal/surface/cli/drain.go:42-195) never mentions two things every move does. (1) On origin, an eligible issue whose found_at names no path is handed back before any judgement is asked, flagged from 'reservation' as no-found-at with the home 'give it a found_at naming the file the fix changes' (internal/core/implement/loop/drain.go:911-921; reservation.go:963-981). (2) Before its window clock, every move takes the landing's last step for each issue lane in the checkout parked at land whose pushed head is on the default branch, removing that lane's worktree and branch, and names a pull request merged by squash or rebase so the person can confirm it and clean up (internal/core/implement/loop/drain_finish.go:3-11, 154-157, 184-339; drain.go:671-686). The help's account of parked lanes (drain.go:152-156) stops at closed, conflicting and open.
- iss-2610251559345278Minor imprecisions in abcd drain --help (internal/surface/cli/drain.go): (a) 60-61, the dispositions omit unreadable (internal/core/capture/eligible.go:61-62, 500-510); (b) 78-79, the dry run 'plans from origin's default branch as last fetched', but when that cannot be read it plans from the checkout's own ledger and says so (internal/core/implement/loop/drain_origin.go:151-154), which 62-63 'never from the checkout' does not allow for; (c) 122-123, a lapsed judgement request is also not asked again before a five-minute cool-down, the take-over margin (drain_hold.go:185-202; internal/core/claim/claim.go:61; internal/core/lease/lease.go:33); (d) 143-144, abcd implement step --discard needs its lane id (the hand-back names abcd implement step --run <run-id> --discard <lane-id>, stuck.go:251-252), and the discard also closes the pull request (internal/surface/cli/build.go:1072); (e) 144-146, 'Every move renews ... waiting or not', but a move that waits on origin or stops on a given-up outage returns before the renewal (loop/drain.go:545-551, 660-669, ahead of 676-678); (f) 176-177, 'ten unless reservation.max_live ... raises it', but the key takes any whole number from 1 to 100 (internal/core/claim/maxlive.go:31-63), so it can lower the cap too; (g) 194-195, exit 3 is reliable only for the drain's own lock: a run lock held while a lane starts passes the issue over as held (internal/core/implement/loop/loop.go:1107-1121; drain.go:1079-1115).
- iss-2610251559378983The --public flag of abcd ideate record (internal/surface/cli/ideate.go:92-93; commands.md:2096) reads 'the idea is public: commit the verdict under .abcd/development/research/ideas/<root-sha>/ and record a decision pointing at it'. The verb writes the record and a decision record (internal/core/ideate/record.go:176-225) and makes no git commit: neither internal/core/ideate nor internal/core/decisions runs git beyond resolving the checkout root. Read literally, the help promises a commit the verb never makes, and the person is left with uncommitted files.
- iss-2610251853204621TestNothingIsMarkedPastTheHooksDeadline (internal/core/claim) fails under -race on a loaded machine. It gives the whole status read a real 400ms deadline, but it tests only that a block marked after the hook's deadline keeps nothing. The read itself (git through the status state, then render) outran 400ms in the joint preflight's race stage on 2026-10-25, so PromptNotes returned 'status unavailable' and the test failed before it reached the marking. It is the same class as iss-2610241911001655: a load-dependent budget standing in front of the behaviour under test.
- iss-2610251952042547The published abcd v0.15.1's prompt-router hook ran for 7 to 10 seconds at about 99% CPU per prompt in a busy session on 2026-10-25 (one sample: pid 98266, 9 s; another: pid 370, still running at 7 s), on a 10-core machine at load 25 where an endpoint scanner already takes about four cores. The hook has a one-second contract (TestThePromptHookReturnsInsideItsSecond), but on a loaded machine nothing holds it to that: a session that receives many messages pays a full core for most of every ten seconds, which slows every preflight on the machine and delays each reply.
- iss-2610252211452294The implement step sentence at internal/core/surface/sentences.go:221-222, rendered as the verb's one-line help and at docs/reference/cli/commands.md:2788, says the step 'refuses a push with no preflight receipt'. Since 13b7bd1aa (ruling DR6d-2) a landing whose head no preflight receipt names waits instead: a contention that holds only that lane, the call moving the others and exiting 3 only when nothing else moves (internal/core/implement/loop/land.go:439-452). The step's own Long help says so (internal/surface/cli/build.go:834-837), so the sentence and the paragraph under it disagree; an agent reading only the sentence treats a waiting lane as refused.
- iss-2610252211466719The implement receipt Long help at internal/surface/cli/build.go:1112-1114 calls the implementer receipt's resolves list optional. On an issue run (build of an issue, or a drain lane) the receipt is refused unless resolves names the lane's issue (internal/core/implement/loop/receipt.go:405-407, added in 2cec1e367), and an implementer may hand the lane back with a handback object instead of commits, which ends the lane (receipt.go:69-73,398-400). The help mentions neither; it renders at docs/reference/cli/commands.md:2659-2661.
- iss-2610252211476480Two intent sentences name less than the verb writes. intent audit (internal/core/surface/sentences.go:242-243; page line 3061) says 'Writes an OWED stub only for --owed or an id', but --issue-drift leaves a report under .abcd/.work.local/logs/audit/issue-drift-<ts>/ (internal/core/capture/drift.go:68-73,179), and on a provider route audit <itd-N> sends the request and ingests the verdict into the shipped intent's Audit Notes (internal/surface/cli/cli.go:3446-3448, dispatch.go:179-211). intent consistency (sentences.go:248-249; page line 3123) says 'Writes the request locally', but on a provider route it sends each request and ingests the answers, writing the dated review and one capture per finding (internal/surface/cli/intent_consistency.go:105-121). Both sentences predate provider dispatch (51c7a9744). Same class as iss-2610251559136898, which holds five other sentences.
- iss-2610252211480171abcd implement load's help says less than the verb does, in three places. (1) Its sentence (internal/core/surface/sentences.go:195-196; page line 2286) says 'Writes a run-log event or the wait's hold', but --wait also renews the caller's reservations, each renewal a commit pushed to origin (internal/surface/cli/implement_load.go:283,334-392; internal/core/claim/renewdue.go:45-64; claim/remote.go:155-159), added in 6931d4ac4. (2) The Long help says 'Without --wait it never refuses, never waits and never stops anything' (implement_load.go:65-66; page line 2298), yet --race-gate without --wait waits (implement_load.go:221-232), and an unknown --site or a stray --timeout is refused at exit 2 (implement_load.go:234-240). (3) The Long help names a symlinked ~/.abcd.noindex as a refusal (implement_load.go:186-187) but not the refusal under a HOME inside a git working tree that is not the account's own (internal/core/implement/load_wait.go:473-478, cd798880f), which commands/implement.md states; and it says the waiter renews 'each of your live reservations' (implement_load.go:189-191) while release reservations are never renewed (renewdue.go:53). The --wait flag line is already held by iss-2610141706070227.
- iss-2610252211483734abcd implement log's Long help at internal/surface/cli/implement.go:503-508 (page lines 2468-2474) overstates and understates its checks. It says the claim, window and session events are refused, but the load event and the four outage events are refused too (internal/core/implement/log.go:84-89,405-407). It says 'an at or last_productive is an RFC 3339 time, and a *_min or minutes field a number', but those fields are checked only on the events whose rules name them (intervention, decision, stop, agent_end, ceiling_overrun and backoff: log.go:126-141,168-200,457-466); lane_close --field minutes=abc or gate_run --field at=yesterday is written as given.
- iss-2610252211498831The reserve --sweep help says 'A hand-back on a record still open, a commit of a kind the sweep cannot classify, a history it cannot read to its root, and an unreadable tip keep the branch' (internal/surface/cli/reserve.go:174-176, reflected at docs/reference/cli/commands.md:4532-4534). Only the hand-back carries the 'record still open' limit. The judge marks a branch whose record is terminal on origin's default branch as spent once its tip is classifiable, before it walks the chain (internal/core/reservesweep/judge.go:94-97), and TestATerminalRecordIsSpentWhateverItsTipOnceOlderThanTheAge (judge_test.go:96) pins that. So on a resolved, won't-fixed, shipped or superseded record, an unclassifiable non-tip commit or a history unread to its root does not keep the branch, and --apply deletes it. The help states the fail-closed rule more widely than the code applies it.
- iss-2610252211502540The statusline sentence 'Writes nothing; never refuses.' (internal/core/surface/sentences.go:416-417, shown at docs/reference/cli/commands.md:4829) is false for an operand. The command declares Args: cobra.NoArgs (internal/surface/cli/statusline.go:137), so abcd statusline x is refused with a usage error, and decideStatus returns an error when the working directory cannot be read (statusline.go:221).
- iss-2610252211512331The library long help says 'Every corpus verb but init exits 3 when there is no corpus.' (internal/surface/cli/source.go:98-99, docs/reference/cli/commands.md:3708-3709). But library sync-banlist --refresh with no corpus prints a one-line notice and exits 0 (source.go:557-561), as its own help and flag text say (commands.md:3906-3914).
- iss-2610252211514146The library add --text flag help reads 'the extracted text of a non-text document' (internal/surface/cli/source.go:320, docs/reference/cli/commands.md:3756), which reads as if the value is the text itself. source.Add reads the value as a path and refuses anything that is not a readable regular file with 'the extracted text is not a readable regular file' (internal/core/source/add.go:301-306).
- iss-2610252211524459spec close --production-mode carries the shared productionModeFlagHelp, 'how this record's text was produced ... (default: the repo's declared mode, else hand-written)' (internal/surface/cli/cli.go:3350, wired at cli.go:3930, docs/reference/cli/commands.md:4773). On spec close the flag only stamps the follow-on spec that --remainder mints, and without --remainder it is refused with exit 2 (cli.go:3813-3815). The flag help says neither.
- iss-2610252211536978Two flag pairs are mutually exclusive, but neither flag's help says so. site build --preview and --version (internal/surface/cli/site.go:88; help at site.go:83-87; docs/reference/cli/commands.md:4732-4733). update --check and --yes (internal/surface/cli/update.go:156; help at update.go:154-155; commands.md:4898-4899). A reader of the reference learns of either pairing only from cobra's error.
- iss-2610252211547430scribe.go declares a Short on the visible commands scribe, scribe assemble and scribe ingest (internal/surface/cli/scribe.go:37, 52, 115). applySentences overwrites each one with the manifest sentence (internal/surface/cli/sentences.go:51-63; manifest at internal/core/surface/sentences.go:397-402), so these strings are dead and already differ from the sentences users see. The comment at sentences.go:24-25 says 'No constructor declares a Short for a visible command, so there is no second copy to drift.' Several capture sub-verbs in cli.go (5691, 5731, 5768) do the same.
- iss-2610252211549081README.md:130 says: 'abcd --view facilitator shows the full board: the repository, the record, the work tiers, the presence line and every intent with its spec.' The full board lists only the Now and Next rows, each with its spec id (internal/core/board/board.go:295, statusRow at :348). The Later group, every planned intent the readiness gate reports not READY plus every draft (internal/core/statusblock/statusblock.go:20-22), is drawn as one count line, 'Later: N intents' (board.go:308). Shipped intents are not on the board at all. A reader looking for a not-ready or draft intent on the full board will not find it there.
- iss-2610252211559933README.md:26 says of the shipped-intent audit: 'That verdict is recorded, not enforced.' When a verdict judges a criterion NOT_MET, the ingest files a major bug in the ledger's open/ folder (internal/core/capture/auditowed.go:25-37; commands/intent.md:1009-1015). The release cut refuses to go ahead while a major record captured since the anchor tag is still open (internal/core/changelog/findings.go:62, GuardFindings at :193, called from internal/core/release/emit.go:267). So the verdict does not unship the intent, but a failed one stops the next release until it is fixed, declined with a reason or deferred, and the sentence leaves that out. Judgement call: the sentence may be meant only as the verifier-selects principle, that no model verdict decides admission.
- iss-2610252211560027README.md:40 introduces the principles with a link to the record site's foundations page ('abcd is founded on several [principles](https://abcdev.app/record/foundations/), ...'). README.md:47, :57 and :60 then name three principles that page cannot carry: '**abcd builds abcd**', '**Work starts from an intent**' and '**The record is part of the product**'. The foundations page is built from the principle store alone (internal/core/site/foundations.go:16-18, explorer.go:721-746). .abcd/development/principles/ has no record for any of the three, and git grep finds those names only in README.md. The other five are in the store: prefer-the-experiment-to-the-inference.md, verifier-selects-gates-decide.md, less-but-better.md, the-record-lands-with-the-act.md and enforcement-claims-are-facts.md. So a reader who follows the link finds five of the eight principles the README names.
- iss-2610252211573105README.md:142-144 says the BibTeX block 'is rendered from `[CITATION.cff](CITATION.cff)`, which is the record GitHub's own *Cite this repository* button reads'. But README.md:149 reads ' title = {{abcd}: {Agent-Based} {Configuration} for {Development}},' while CITATION.cff:4 declares title: 'abcd' (the long name is in abstract:, CITATION.cff:5). The cite button therefore hands out a different title from the README's. TestReadmeCitationAgreesWithCitationCFF pins only the author, the repository URL and the licence (internal/core/launch/citation_test.go:33-43), so nothing catches the title.
- iss-2610252211582415README.md:127, the last line of the sample board under the bare abcd prompt, reads 'abcd v0.13.4'. That line is the installed version (internal/core/board/board.go:138). The release a user installs today is v0.15.1: .claude-plugin/marketplace.json:15 names abcd-plugin-v0.15.1.zip, and v0.15.1 is the newest tag. So the sample shows a version two minor releases old. commands/abcd.md:24 uses the same version, as a labelled example.
- iss-2610252214104892The ahoy chapter states the uninstall leaves 'the entire .abcd/ namespace and the history store intact' and omits the README parts and status-line hand-back, while internal/core/ahoy/apply.go:2163-2169, the chapter's own line 65-70 and commands/ahoy.md:1014-1036 say it removes README parts, hands the status line back and clears readme.created.
- iss-2610252214116260The ahoy chapter (lines 1145-1148, and Acceptance 1228-1230) says zero actionable gaps means 'already up to date' with no write, but Install also proceeds for an askable optional offer or a flag that would change a setting, and returns partial for an unverified owned copy (internal/core/ahoy/apply.go:183-229; commands/ahoy.md:489-492).
- iss-2610252214123453The ahoy chapter's 'Not built yet: destroy … (itd-10)' presents a draft intent (intents/drafts/itd-10-purge-uninstall.md, spec_id null) as a staged design, against the 00-meta truth rule that the brief records no undecided option.
- iss-2610252214130450The folder-kind table and text say a '.git/ directory' marks a repository, but gitPresent accepts a .git file too (linked worktree, submodule; internal/core/ahoy/detect.go:220-229).
- iss-2610252214149191The ahoy chapter (14,737 words) and commands/ahoy.md (13,237 words) are parallel full statements of the same behaviour; the declared rule (04-surfaces/README.md:3-7, adr-2609231028044006:102) makes the chapter the home for behaviour, yet the commands page is the more complete copy and the more current one in the two stale spots above.
- iss-261025221415216005-intent.md:318 says 'A leading quote always creates — never falls through to bare render'; a quoted lone word is refused at exit 2 (internal/surface/cli/cli.go:2772, commands/intent.md:119). Found by the 2026-08-23 crosscheck and never fixed.
- iss-2610252214152975commands/intent.md:232 says the grounds check is 'the eighth and last row of the report', but abcd intent ready appends a ninth, gating open_questions row last (internal/core/intent/ready.go:153).
- iss-261025221416190005-intent.md:333 says consistency ingest files a finding unless an open record quotes an end; the code checks the finding_ref key first and marks a finding held by a resolved or wontfix record 'addressed', filing nothing (internal/core/intent/consistency.go:891-896, commands/intent.md:1277). 05-internals/01-agents.md:168 has the same gap.
- iss-261025221417428105-intent.md:553 says the honoured/diverged/missing prose review is deferred; the ingest already renders it into Audit Notes (internal/core/intent/audit.go:1944-1947; agents/intent-auditor.md:105).
- iss-261025221418962105-intent.md:434-440 says scope conditions are 'mandatory with an explicit nullity — enforced'; the readiness gate reports them on an advisory row that never withholds readiness (internal/core/intent/ready.go:32-37, commands/intent.md:276, and the page's own :413).
- iss-261025221419948805-intent.md:526 says the related_issues/related_intents join is checked 'not by the record-lint'; related_issues_backlink is a record-lint rule armed at warn (internal/core/lint/reciprocal.go:225, .abcd/record-lint.json:497), as :511 of the same page states.
- iss-261025221420007005-intent.md:523 says every record in superseded/ carries kind_at_supersession; itd-17, itd-27 and itd-58 do not, and itd-20 keeps a non-null bundle with no bundle_at_supersession, against :509.
- iss-261025221421111205-intent.md:304-310, :334, :624-648 and :657 still stage an on-demand shape verb with a flock contract; itd-48:147 gave the shape role to itd-34's kinds lint, itd-34:241 leaves it out of delivery, and :639 cites the superseded itd-33. 05-internals/01-agents.md:175 and 04-universal-patterns.md:124 repeat it.
- iss-261025221421783305-intent.md:448-499 (§ 5), the grill row (:319) and the PRD-freeze block (:221-226) keep the predecessor's grill/PRD design: itd-27 is superseded by itd-94, which carries none of it, and no GL003/GL005/GR002 code exists. intents/README.md:177-185 and :239-251 keep the same fields in its template.
- iss-261025221422085405-intent.md:179-180 is a verbatim copy of :74-75 (low ids, target_release) on the same page.
- iss-2610252214232497Three press-release templates disagree: the brief's body (05-intent.md:397-431) has Mechanism, Scope Conditions and Grounds but no Prior Art or SOTA; intents/README.md:188-234 is the reverse; create.go:503-530 seeds a third set. 05-intent.md:507 requires ## SOTA on a planned intent.
- iss-2610252214242532intents/README.md lags the code and the record. :38 and :277 list the spc-83-operator-surfaces members as planned (itd-24, 63 and 69 shipped; itd-20 superseded). :100 and :132 mark bundle and reclassify as design targets, though bundle.go and reclassify.go ship. :159 says an intent is 'implemented by exactly one spec', against invariant 17 (02-constraints/03-invariants.md:171). Its own :33 names the brief canonical.
- iss-261025221425218501-product/05-personas.md:7 says '/abcd:intent '<text>' picks a persona for the customer quote'; the create has no persona logic (internal/core/intent/create.go), and 05-intent.md § 4 claims nothing of the kind.
- iss-261025221426017904-launch.md:64, 179-187, 704-707 and 814-821 call commit/tag/publish and the release commit-message format a design target of itd-72, but itd-72 is superseded by adr-37 (.abcd/development/intents/superseded/itd-72-launch-ship-tier-b-publishing.md:20,28), so no decided target stands behind them
- iss-2610252214267121The doc-fidelity gate checks only the brief chapter (04-surfaces/10-docs.md:66-82, commands/docs.md:92). So 05-intent.md is the gated copy of intent-verb behaviour. commands/intent.md, the page the host runs and the more current one (chunking, finding keys), is ungated and carries a false line (:232).
- iss-261025221427125004-launch.md:664-666 and commands/launch.md:1062-1064 say auto-release.yml renders the plugin archive on the pushed commit (the command page: 'in detect') before the tag; auto-release.yml runs no launch archive, and the CI renders are release.yml's verify (.github/workflows/release.yml:205) and release job (:545), as adr-2609231048308186:71-73 and 04-launch.md:139-142 say. Resolved iss-2609260552247395 fixed the same claim at commands/launch.md:152-153 only
- iss-2610252214288494commands/launch.md:533-535 says the receipts commit makes 'the branch ... exactly two commits', but internal/core/release/protocol.go:69-71 composes a captures commit after the receipts, as commands/launch.md:943-949 and 04-launch.md:151-153 also say
- iss-2610252214292202commands/launch.md:647-648 says deleting a record to clear the gate is refused under deleted-finding, but deletedRecords (internal/core/changelog/findings.go:353-385) judges only records the anchor held in open/; a record captured this cycle and deleted in a commit is caught by neither half (residual named in resolved iss-2609091143455568; 04-launch.md:616-618 states it)
- iss-261025221430676817-guard.md:818-820 calls the check's help text 'the fuller statement of the same list ... with a worked example for each'. The help (internal/surface/cli/guard.go:111-139) is the shorter list: it omits items the brief names (a .. after a symlink or a ~user home, a target spelled another way, another interpreter's file, a script changed between check and run) and gives no example for several. The fuller statement is commands/guard.md:920-955.
- iss-261025221431467616-lint.md:70-81 justifies the gate bucket for the outbound and site targets by CI consumption ('wired into CI to make a binary pass/fail decision'; 'its exit is the release job's publish decision') and says 'the distinction is the one adr-40 draws'. adr-40:136-137 says 'A lint's exit code being consumed by CI does not make it a gate; producing findings is what names it', and :113-114 says a surface that produces findings is lint, review or audit.
- iss-261025221432300116-lint.md:130-132 (and :4-5, 'each finding naming the file') says every finding carries a file. internal/core/repolint/repolint.go:70 marks it omitempty, and rule_site.go:76 leaves it empty for a gate failure with no source span, as commands/lint.md:39 already states.
- iss-2610252214325849Found in a counterpart: internal/surface/cli/guard.go:31-34 says the hook treats a guard that cannot answer as 'fail-OPEN (loud, exit 0 ...)'. failOpen returns exit 1 (guard.go:332-335), as 17-guard.md:71-73 and docs/how-to/install.md:152-157 state, because the host discards stderr on exit 0.
- iss-261025221433846734-build.md:191-193 says the pick's record commit is made 'with hooks off'. pickcommit.go:18-21 and commands/build.md:216-219 say the repository's hooks and signing run (iss-2610111729399920, resolved without updating the brief).
- iss-261025221434293734-build.md:210-212 lists the series refusals without --max 0, which iss-2610121210280182 made a refusal at the pick stage (commands/build.md:274-277).
- iss-261025221435870634-build.md:679-680 says the validate stage hands the head to validators 'one fresh agent at a time'. validate.go:4-5 and commands/implement.md:402 run them side by side up to the ceiling (ruling DR6, state v9), as does the brief's own 406-414.
- iss-261025221436621834-build.md:850-851 says exit 2 is refused 'with nothing written'. stuck.go:7-9 and commands/implement.md:436-438 log each refused step of an issue run on its lane (refused, state v13).
- iss-261025221437679501-product/03-mental-model.md:85 says 'The brief's press release and surface chapters carry an ## Acceptance block'. Neither 34-build.md nor 38-land.md carries one, and only 3 of the 36 chapters under 04-surfaces/ do.
- iss-261025221438258835-drain.md:252-253 says a pull request that turns conflicting after arming is refused by the run's own step 'since the drain's part ends at the open pull request', but the drain's move re-enters the sync for a parked lane whose conflict is confined to declared generated files or not reproducible here (internal/core/implement/loop/drain_finish.go:274-283), as commands/drain.md:407-412 and the chapter's own :413-416 say; :413-415 also omits the not-reproducible case commands/implement.md:471-472 names.
- iss-261025221438449035-drain.md:678-679 states a spec's delivery state ('spc-2609212015054359, which stays open for the decision-record marker and the issues its plan names'), which .abcd/development/brief/README.md:13 says lives in the roadmap and never in brief prose.
- iss-2610252214390939.abcd/work/issues/README.md:159 says resolving without --impact 'exits 1'; it exits 2 (internal/core/capture/workflow.go:373-376 refuses with ErrRequestRefused, mapped to code 2 at internal/surface/cli/cli.go:5989), as 06-capture.md:296-302 and commands/capture.md:408-411 say.
- iss-2610252214407620.abcd/work/issues/README.md:64-66 says of the admission and surprise stores that 'no verb writes either family yet'; capture admit and capture surprise ship (internal/core/capture/admit.go, surprise.go; commands/capture.md:573-611).
- iss-2610252214410618.abcd/work/issues/README.md:70-140 lists the schema as validated strictly with unknown keys rejected (:72), but leaves out remedy, origin, production_mode, duplicates, refines, deferred_after and deferral_reason, all of which internal/core/issueschema/issueschema.go:59-129 accepts.
- iss-261025221442915506-capture.md:519-527 (§4) keeps the legacy scratch migration as a staged design ('Not built yet ... on first run after install, the command parses a free-form scratch buffer'), while dcn-2607170000000002:14-15 ruled it 'satisfied-by-history ... no dead migration code built' and 05-internals/03-configuration.md:1198-1200 says it 'has nothing left to migrate'.
- iss-2610252214431775.abcd/development/decisions/adrs/README.md:33 says every ADR-id reader admits both vintages 'through one derivation', naming the record_schema and citation-currency gates, the site index and the lifeboat; 24-decide.md:142-154 and the code show four derivations (internal/core/lint/schema.go:86, internal/core/site with no recordid import, internal/core/lifeboat/graveyard_abandoned.go:435-441). The brief calls consolidating them 'open work', and no ledger record holds it.
- iss-2610252214448479commands/ideate.md:200 says exit 2 means 'nothing was written', and 18-ideate.md:178-180 says 'a run never leaves a verdict nothing points at'; when the pointer write fails and the rollback also fails, internal/core/ideate/record.go:219-221 returns 'THE ROLLBACK FAILED — remove ... by hand', which internal/surface/cli/ideate.go:76-83 exits 2 with the verdict still on disk.
- iss-2610252214455357decide sends every record and mint error, a mint-lock timeout or a write failure included, to exit 2 (internal/surface/cli/decide.go:94,110). commands/decide.md:129-133 and 24-decide.md:95-97 describe exit 2 as an operand refusal only, and capture keeps exit 1 for faults (06-capture.md:310).
- iss-261025221445887437-reserve.md:29-33 says the verb 'does one of two things' (reserve or release) plus 'a third form, the holder query'; the sweep form shipped on 2026-10-16 (internal/surface/cli/reserve_sweep.go:30; commands/reserve.md:293-329; adr-2610161940004937) and is absent from the chapter's prose and its Exits (:364-390), though its own appendix lists the three flags (:415-421).
- iss-261025221446387308-abcd.md:517-599 keeps the six-section board of itd-20 as a 'Design target', with two open questions and an alias rationale, though itd-20 was superseded by itd-121 on 2026-09-20 (intents/superseded/itd-20-top-level-abcd-dispatcher.md:24,32) and the truth rule (00-meta.md:7-16) admits only decided shipped or staged machinery and sends open questions to 03-open-questions.md; 01-product/04-scope.md:16 still cites the board as 'per itd-20', 08-abcd.md:604 names only itd-20, and 06-capture.md:520-522 links its dev-sync dependency to this section.
- iss-2610252214479123The chapter-number collision iss-2610151050383937 records (37-embargo.md and 37-reserve.md) has grown: 37-memory.md is a third 37, and 38-announce.md and 38-land.md share 38 (04-surfaces/README.md:47-51).
- iss-261025221448839920-banlist.md:38-42 records as a 'rough edge' that a private add accepts and silently drops the severity and successor flags (internal/surface/cli/banlist.go:170-171 passes neither to AddPrivate); no ledger record holds it.
- iss-261025221449314319-identity.md:112-118 records as a 'rough edge' that identity init on an adopted repo silently drops a new block location (internal/core/positioning/init.go:86 counts only title, tagline and pitch as answers); no ledger record holds it.
- iss-261025221450583137-memory.md:84-88 says memory list is the unfiltered list the naming rule forbids; iss-2610171626344967 was resolved by writing that into the brief, so no open record holds the defect, while the same shape for banlist list is open as iss-2609282105240081.
- iss-261025221451721011-history.md:52-54 says show matches 'by session id (newest when a session has several records) or by record filename'; history.Read matches the filename, then an exact agent id, then a session's main-thread record even when a sub-agent record is newer (internal/core/history/history.go:471-497), as commands/history.md:144-147 says.
- iss-2610252214522207The generated CLI reference's library ingest example is https://example.com/paper.pdf (internal/core/surface/examples.go:111), a PDF the binary rejects with no extractor wired (internal/core/memory/ingest.go:985-987; 07-library.md:355-356, commands/library.md:297-299).
- iss-261025221452602707-library.md:435-438 says itd-36 is non-decomposable and 'a partial ship is not meaningful'; itd-36 shipped with ac-3 and ac-12 NOT_MET (itd-36-memory-unification.md:140, :175) and without the curator role the paragraph says the sub-verbs need (07-library.md:413).
- iss-261025221453583719-identity.md:41-48 reproduces abcd's canonical identity block verbatim, a second copy of the tagline that no registered surface check covers, in the chapter about keeping one copy.
- iss-2610252214545793The routing paragraphs at 02-disembark.md:296-300 and 23-reading.md:352-356 list seven route-receipt fields; internal/core/oracle/receipt.go:79-84, commands/disembark.md:266-269 and commands/reading.md:291-294 also carry provider_call and unpinned.
- iss-2610252214553884Staged claims rest on draft intents, against the 00-meta.md:7 truth rule ('never an undecided option'): 02-disembark.md:70-71 and 03-embark.md:254-255 (itd-23, intents/drafts/) and 02-disembark.md:114-117 (itd-11, intents/drafts/); the force, archive, refresh-audit and workspace-registration modifiers at 03-embark.md:240-258 have no intent at all.
- iss-261025221456644802-constraints/01-platform.md:21 says 'a test hashes its tree before and after' and :23 says past disembarks are recorded as 'hash + file list + label'; the test is a path/size/mode fingerprint (internal/surface/cli/disembark_test.go:240-258; 02-disembark.md:234-235 'a fingerprint, not a content hash') and the voyage entry carries no file list and no label (internal/core/lifeboat/voyage.go:27-43; 03-embark.md:300-303).
- iss-2610252214576430README.md:248-249 declares the bare-invocation paragraph the one enumeration of exceptions and says chapters point there rather than restating it, but 02-disembark.md:44 and :227-232, 03-embark.md:45 and :197-199, 09-reflect.md:38-39 and 10-docs.md:119-121 restate the bare behaviour.
- iss-2610252214584503commands/embark.md:95-97 says the plan is judged again 'under the target's ledger and intent locks', but the write also takes the spec store's lock (internal/core/lifeboat/embark.go:102-114; 03-embark.md:86-89), so the counterpart a pointer would lean on is the less complete copy.
- iss-261025221459459204-surfaces/README.md:152's agents-block row omits guard approve, which helpgroups.go:143 annotates into the agents block and the snapshot records with block agents.
- iss-261025221459591804-surfaces/README.md:276 says the hidden hook has 'six host hook entrypoints'; the binary registers eight (stop, stop-failure added: internal/surface/cli/hook_stop.go:90, :259; hooks/hooks.json).
- iss-261025221500095704-surfaces/README.md:483-495 restates the glossary's library and memory-note definitions (glossary/core/library.md:4, core/memory-note.md:4) though the glossary is declared the only home for term definitions.
- iss-2610252215019685glossary/README.md:172-209 describes /abcd:intent grill as 'a design target (itd-27)', but itd-27 is superseded by itd-94 (intents/superseded/itd-27-grill-skill-and-glossary.md:3); interview/embark.md and interview/session.md define stable terms for the same superseded design, and only planned itd-50:91 still leans on it.
- iss-2610252215020066glossary/core/reading-position.md:60's example says 'comparative does not assemble and refuses: its object has no channel'; the comparative position now derives its candidate run and assembles (internal/core/reading/assemble.go:403; 04-surfaces/23-reading.md:61-83).
- iss-2610252215032235glossary/core/spec.md says a spec lives 'as a directory ... decomposed into numbered tasks' and its definition says 'broken into ordered tasks', with example 'Task spc-3.1'; specs are single files open/spc-N-<slug>.md (specs/README.md:17-18) with ## Steps, and step.md:6 forbids 'task' as a synonym.
- iss-2610252215042936glossary/core/record.md:32, :42-43 and :66 say embark writes 'the four record families (ADRs, issues, intents, specs)'; embark writes five, release retrospectives included (04-surfaces/03-embark.md:104; internal/core/lifeboat/embark_types.go:330).
- iss-2610252215053156glossary/core/voyage.md:4 and :28-30 present embark/provenance.json and embark/from/<timestamp>/ as part of what the voyage records ('every disembark and embark run'); 05-internals/03-configuration.md:497-500 says only the disembark log ships and the embark side is staged (03-embark.md:272 'not built yet'). Its Open question (:43-48) is also stale: oracle.md no longer says 'during a voyage', and phase.md:83 calls the sense retired.
- iss-2610252215061740glossary/core/loop.md:35-40 says 'abcd never owns the run loop ... a pluggable adapter supplies the loop itself'; the run seam's native default is a 'thin native Go loop (adr-27)' (05-internals/02-adapters.md:25) and the implement loop is abcd's own loop over a state file (04-surfaces/34-build.md:5-7). The Senses table also lacks the implement/build-loop sense step.md:18 and oracle.md:25 use. docs/reference/terminology.md:45 repeats 'never owns the loop'.
- iss-2610252215074926glossary/core/transport.md defines transport only as delivery to an oracle, while AGENTS.md Boundaries ('knows a transport'; front doors under internal/surface/*) and glossary/core/surface.md:4,20 ('the transport package') use the word for the CLI front door.
- iss-2610252215079172glossary/core/README.md:6-9 says each multi-sense core word carries a ## Senses table; construal.md:23 says the word carries one sense and has none, and reading-position.md:32 uses '## The spelling'.
- iss-2610252215082536glossary/core/ledger.md:37 says 'The fifth sense is a side'; the local ledger side is the sixth row of the Senses table (:33, after the warm row at :32).
- iss-2610252215090992glossary/core/technical-facilitator.md:4 and :25 attribute 'the facilitator is a mode, not a person' to draft itd-97; adr-2609151528057260:52 accepted it, and adr-2610150603484802:34-42 set a fresh repository's facilitator to a person. docs/explanation/roles.md:3 and :23 still say the facilitator 'is an AI by default', against that amendment.
- iss-2610252215106673glossary/core/product-thinker.md:26 says the product thinker owns the brief and the intents; docs/explanation/artefacts.md:15 says the brief is 'owned jointly by the product thinker and the facilitator'. The user doc restates the glossary role terms and contradicts it.
- iss-2610252215115075docs/reference/terminology.md:58 maps 'Memory' onto the library's distilled pages, but the glossary makes 'memory' an alias of memory-note (glossary/core/memory-note.md:5) and sends agent-learned lessons there (core/library.md:26); the shipped memory notes (commands/memory.md) are not mentioned. Line 59 also says 'No MCP server ships today', while abcd guard approve speaks MCP on stdio (internal/surface/cli/guard_approve.go:48-50).
- iss-261025221512820602-constraints/04-naming.md:19-20 restates the glossary's lifeboat and voyage definitions in the maritime table, and docs/explanation/artefacts.md:15,19 and roles.md restate the brief, intent and role definitions without pointing at the glossary.
- iss-2610252215131319The press release lists /abcd:run (itd-29) as shipped operator-internal wiring, while 04-scope.md:19 says it is not built and itd-29 is superseded.
- iss-2610252215141901Four pages (press release, context, naming, mental model) still carry /abcd:intent grill (itd-27) as designed or staged and Role 3 intent shape as a third auditor role. itd-27 is superseded by itd-94 (01-build-sequence.md:99-102: 'There is no grill sub-verb'), and itd-48:19 moved the shape role to the kinds lint.
- iss-2610252215152058The context page's lifeboat tree (root README.md, press-release.md, principles.md, research/, audit/ from 'passes B/C') and the press release's 'three passes ... targeted chat retrieval' contradict the output shape at 04-surfaces/02-disembark.md:135-152 and the 'Not built yet' transcript distiller at :114. The press release's open question names a chat-distiller agent that agents/ does not hold.
- iss-261025221516430702-context.md:47 calls .abcd/corpus.json the 'user-maintained' validation-corpus list, and 01-platform.md:41 makes that page its SSOT. The file is absent, and 04-naming.md:80 says the name is reserved and 'not yet in the tree'.
- iss-261025221517445803-mental-model.md labels itd-2609212103568351, itd-2609212103565953 and itd-34 as 'planned', but all three are in intents/shipped/, and abcd intent plan <itd-N> [<itd-N>…] --bundle ships.
- iss-2610252215183541The press release's out-of-scope line hand-counts '13 more items' against a generated list of 119 drafts whose own page says it is not hand-counted.
- iss-261025221518995403-mental-model.md:72-81 describes in the present tense an LLM suggested_kind classifier, an intent classify-capture-kind verdict (itd-44, a draft) and a discipline_kind field with a gate registry under .abcd/disciplines/. The create path writes suggested_kind: null (internal/core/intent/create.go:471), no code reads discipline_kind, and .abcd/disciplines/ does not exist.
- iss-261025221519323301-platform.md:17 calls the markdown plugin surface a 'later front door', but the surface ships, as AGENTS.md:135 and 01-build-sequence.md:28 both say.
- iss-261025221520779202-constraints/README.md:12 describes 03-invariants.md as a 'Navigational pointer ... (placeholder)'. The page itself (:3) declares 'Status: LIVE' and the canonical home of the invariants.
- iss-261025221521755906-delivery/README.md:10 gives the build sequence as 'MVP → the companion harness → Claude Code'. 01-build-sequence.md has milestones 0-6 and no such order.
- iss-2610252215220345Six reserved-vocabulary rows at 04-naming.md:197-202 cite itd-33 as 'a later phase', and itd-33 is superseded. claim.status 'interlocks with itd-29', which is also superseded. The shipped reservation vocabulary differs.
- iss-261025221523227603-evidence/04-tradeoffs.md:41,49,57 cite .abcd/work/idea-assessments/*.md as sources. The directory does not exist (itd-37:109 calls them unmigrated local notes).
- iss-261025221524310303-configuration.md:163-165 says the repository's own config carries five blocks; .abcd/config.json carries six, the sixth being release.digest (read by internal/core/release/digest.go:26), which is missing from the page's 'sixteen keys' (line 33) and its opt-in list (lines 7-21)
- iss-261025221525217803-configuration.md:409 says 'No run seam ships, so nothing drains today', but commands/intent.md:1028 documents intent audit --owed draining the owed reviews, and 01-agents.md:153 says the same
- iss-261025221526805003-configuration.md:474-477 calls the one-owner rule for the transcript store 'a convention with nothing behind it', but TestOnlyTheHistoryPackageNamesTheStorePath (internal/core/history/store_boundary_test.go:162) enforces it, with the assembler's exclusion row as its declared exception
- iss-261025221527684602-adapters.md:28-33 and 04-universal-patterns.md:177-182 say '.abcd/config.json -> <seam>.backend selects the backend' and that a failing backend degrades to the native default; 03-configuration.md:382-390 says no shipped code reads spec/run/history.backend, and 01-agents.md:203-205 says oracle.backend routes nothing
- iss-261025221528105102-adapters.md:338-359 describes lifeboat source readers with a 'probe() → extract() → copy()' contract and an adr.path config key; internal/core/lifeboat/probe.go:120-130 defines Source as a per-section, per-tier adapter (Section/Tier/Probe), and ADRs come from a fixed conventional-directory list (sources_conventions.go:149) with no adr.path key
- iss-261025221528633504-universal-patterns.md:81-82 names internal/core/schema and internal/core/render as the owners of JSON schemas and renderers; neither package exists
- iss-261025221529948704-universal-patterns.md:144-154 calls doc-fidelity 'planned under draft intent itd-60 … not yet built', keyed `logs/doc-fidelity/<input_fingerprint>/`; itd-60 is in intents/shipped/, and the gate saves `.abcd/.work.local/doc-fidelity/<commit>/doc-fidelity.json` (internal/core/docfidelity/store.go:32-35)
- iss-261025221530031304-universal-patterns.md §6 keeps superseded designs as design targets: grill/ (itd-27, superseded) at line 116, and .abcd/coordination/ (itd-33, superseded; the directory does not exist) at lines 139 and 157. Line 161 says voyage is 'tracked under the visibility rule', against 03-configuration.md:509-513 ('never committed', with nothing in-tree to ignore)
- iss-261025221531881704-universal-patterns.md:188 says lint blocks a namespace whose curation disagrees with its declared lifecycle class '(lint code reserved at 06-lint.md)'; 06-lint.md:14 says the engine has no numbered code catalogue, and no lint or README declares or reads a lifecycle class
- iss-261025221532879905-prompt-quality.md:128 keeps the 'more than 10% shorter' acceptance rule for the self-improvement pre-flight, which itd-5:38 records as struck on 2026-07-12 by itd-81 ('The gate is the corpus score')
- iss-261025221534688406-lint.md:60 says each gate emits JSON on --json; record-lint has no --json flag (cmd/record-lint/main.go:37-44) and prints file:line text only
- iss-261025221535810806-lint.md:70 and :74, and README.md:20, rely on a documentation-auditor that audits the lint contract at every disembark; 01-agents.md:95 lists it as unbuilt, and agents/ has no such prompt
- iss-261025221536995405-internals/README.md:22-27 lists 'Future enforcement candidates (deferred, not yet tracked in the ledger)', the kind of proposal the truth rule at 00-meta.md:9 bars
- iss-261025221537615605-internals/README.md index rows are stale: row 3 claims 'adapter-registry config' (03-configuration.md:404 says there is none), row 1 says every agent declares JSON I/O (01-agents.md:55-59 says four do not), row 7 credits principle-distiller with curating memory, and row 10 names 'The check gates', now lint site (7b579ca5e)
- iss-261025221537913607-memory.md:16,42,148-158 give principle-distiller the memory curator role and say 'The agent count stays at 15'; 01-agents.md:18 says eighteen ship, agents/principle-distiller.md:3 only distils a packed lifeboat, and commands/library.md:310 makes the host the distiller
- iss-261025221538611907-memory.md:50,153,206 and 09-provenance-substrate.md:107 say the internal/core/memory adapter distils vendor session memory ('existing behaviour'); no harvest code exists in internal/core/memory, and memory.harvest is a staged key no code reads (03-configuration.md:393)
- iss-261025221539538207-memory.md:42 says source.class is backfilled 'on first /abcd:ahoy after itd-36 ships'; itd-36:163 records that ahoy has no memory step and that the backfill runs when a memory verb touches the store
- iss-261025221540886707-memory.md:181-195 describes memory-page recall with FRESH/MODERATE/DEPLETED brackets as shipped behaviour; itd-39 is in intents/planned/, the shipped router recalls memory.json notes (03-configuration.md:976; internal/core/rules/rules.go:394-395), and no bracket exists in the code
- iss-261025221541512809-provenance-substrate.md:18-21 says licence detection is 'implemented by internal/core/provenance detect_licence' and reads Cargo.toml and pyproject.toml; the detector is memory.detectLicence (internal/core/memory/provenance.go:308), internal/core/provenance is the disclosure vocabulary, and the code says TOML manifests are not parsed (provenance.go:305)
- iss-261025221542934309-provenance-substrate.md:124 calls the source-hash registry 'regenerable per the lifecycle taxonomy'; line 52 says it is only partially regenerable and overrides that classification
- iss-261025221543569710-site.md:3-12 and 05-internals/README.md:16 still mark the abcdev.app root as a design target that 'still serves the MkDocs rendering' until the first tagged deploy; the release chain has called site.yml since 2026-08-22 (auto-release.yml:148), and 26 tags have been cut since. This describes outside state and is probably stale
- iss-2610252224170402.abcd/work/rulesets/README.md:10 says main-protection.json carries the nine required status checks, but main-protection.json lists ten.
- iss-2610252224180535The header comment of .github/workflows/ci.yml (line 19) says the issue-resolution gates are RS001-RS003, while the job it describes runs RS001 to RS006 (ci.yml:711-751).
- iss-2610252224197576.github/CONTRIBUTING.md:134 and :169, AGENTS.md and the bundled COMMITTING rule (internal/core/rules/defaults/rules.json) say the Assisted-by trailer follows the Linux kernel's format, Agent:model-version. The kernel's coding-assistants page (docs.kernel.org/process/coding-assistants.html, read 2026-10-25) no longer carries a vendor or model field, so the claim that abcd's trailer is the kernel format is out of date, whatever form abcd keeps.
- iss-2610252224202553.abcd/development/research/notes/2026-07-30-session-recording-sota.md:79 says, from facts verified 2026-08-15, that opencode is not among SpecStory's documented providers. SpecStory now lists 15 providers, OpenCode among them (read 2026-10-24 in the state-of-the-art pass on iss-217), so the statement is out of date.
- iss-2610252224215664No gate checks that the /docs/ links on the composed site pages and the site-src/redirects targets resolve in the built output. abcd lint site drops docs/ from its page walk (internal/core/site/check.go), no workflow runs a link checker, and siteHref (internal/core/site/compose.go) hard-codes the docs generator's URL shape, so a generator change that moved those URLs would break the links with every gate passing.
- iss-2610252224221774scripts/cloud/connectors/claude/launch.sh:19-22 says the self-hosted dispatch answer's exact JSON fields are not documented, but the host's CLI reference now documents them: ok true with session_id, title, url and pool_id, or ok false with error and exit 1 (read 2026-10-24). internal/cloudscripts/cloud_send_test.go:48 still pins the generic -p result shape rather than that documented line. Separately, the C12 test's marker list names no host id forms, so the ccpool_ id form send.sh:80 names outside the connector passes the check.
- iss-2610252224232577itd-201 promises GRILL's asking rules whenever an agent needs a human decision, at any stop for a verdict, but its own open question 1 (whether the recall words fire on every stop for a verdict, or the mode verb should inject the domain when a stop is parked) is unanswered, and nothing injects GRILL at a parked stop: neither the mode verb nor the mode store references the domain.
- iss-2610252224248804For a release cut by launch ship, reflect's warning about intents targeted at the release that did not ship can never fire. The cut moves those targets to next before a tag exists (internal/core/release/ingest.go:455, PlanTargetMoves), and the reflect seed (internal/core/reflect/seed.go:173) reads only the intents' current target_release, not the cut's record of the moves (fidelity review of itd-24).
- iss-2610252224253701itd-24 promises that future intents reference past lessons, but nothing on the intent side reads the retrospective store: lessons are read only by embark's lifeboat view (ReadLessons at internal/core/reflect/lessons.go:28, used from internal/core/lifeboat/retrospectives.go:54).
- iss-2610252224253742itd-2609151138388536 promised that a managed repository's owner could convert an existing decision log with the same one-off script used here, but nothing an owner could run exists: the script stayed in a gitignored local tier and was never committed, PR #1026 does not carry its source as the spec required, and no user doc names a way to convert.
- iss-2610252224260920itd-2610030720038073's check D6, that no run log carries a stop naming indexing, was never taken: the receipt (.abcd/development/research/notes/2026-10-04-noindex-scan-receipt.md:28) defers it to the next run's log, and no later receipt records it.
- iss-2610252224273366itd-2610030810350727's host evidence is incomplete. The dated screenshots meant to prove the 80-column reading (A4, and A5's host half) are described in the calibration note but not committed, and the local tier it names has no such directory. Every screenshot it describes is a single-question call, so nothing shows a longer question split into tabs within 24 rows per tab, and nothing records a question without previews wider than 80 columns, though abcd's questions now never carry previews.
- iss-2610252224285242intent audit judges struck acceptance criteria. countAcceptanceCriteria (internal/core/intent/audit.go:2029) counts every top-level bullet of the Acceptance Criteria section, so a bullet struck by a later decision, such as itd-2610030810350727's A6 struck by decision 11, keeps its slot and must get a verdict. Nothing delivered can decide a struck outcome, so its INCONCLUSIVE files an owed check that no re-run can clear (iss-2610241604049754).
- iss-2610252224295213itd-2610090831227812's spec planned an after capture of what the bare abcd listing shows (the fifteen, step 8), with the screenshots attached to the spec. The closed spec records three partial-match probes in prose and keeps the screenshots in another checkout's local tier.
- iss-2610252224309038itd-2610111707085098's criterion C13 asked for a live receipt, C1 to C8 each captured before and after, attached to the pull request. PR #1033 says the receipt is in the local tier, and the pull request carries no comment, review or file holding it.
- iss-2610252224311175No test carries a generated-file conflict through the implementer's regeneration to a pushed, mergeable pull request: the sync tests stop at the sync brief (internal/core/implement/loop/sync_default_test.go:140), and re-landing is pinned only for a conflict-free resync (:241). This is the half of itd-2610161016391855 its fidelity review found unproven.
- iss-2610252224317335spc-2610161044461448 required the 2026-10-16 three-account lab to be rerun on the built binary, every account on one build, before it closed. No rerun is recorded in the close commit (80764362b), the history or the lab store, so three shipped intents rest on per-step tests with two or three clones of one local bare origin: itd-2610161016391855 (evidence from drains on several accounts), itd-2610161016394967 (drains share the work, end to end) and itd-2610161016401115 (a drain runs unattended for a day).
- iss-2610252224325919itd-2610161616086564's offer for a setting whose default changed in an update is exercised only by tests that stand in a table: the embedded default-change table carries no entry (internal/core/ahoy/defaults/default-changes.json:3), so no shipped binary has ever reached that offer.
- iss-2610252224332293itd-2610161617096084 has no durable proof that a live host agent's first reply begins with the printed lines word for word. The spec's live run cites transcripts only in a session scratchpad (live-run/transcripts/ and live-run/transcripts2/), none in the repository or a durable local tier, and the first run's reply restated the lines rather than repeating them.
- iss-2610252224345288itd-3's criterion 6 asks for every broadly applicable rule of the legacy methodology file to be preserved in the bundled defaults, by a recorded completeness review. No such review is recorded: legacy-harvest.md marks rows Keep (Singular vs Plural Naming, Documentation Footer Standards and others) without saying which bundled rule carries each, and dcn-2607110000000005 records only that itd-3 shipped ahead of it.
- iss-2610252224353794Ruling H1b says itd-6 is finished only after one live run against the real RepoPrompt app, a check owed to a person. itd-6 moved to shipped/ with every test on a test-owned MCP server (internal/adapter/repoprompt/mcptest/mcptest.go) and no record of the run, and no ledger record tracks it; the command-line runner's equivalent is tracked as iss-2609301519558538.
- iss-2610260445269853A branch that edits .github/workflows cannot be pushed with the session's gh token: GitHub refuses the https push (refusing to allow an OAuth App to create or update workflow without workflow scope), and abcd land relays the raw git refusal with no route past it. A preflight that took hours was only pushed by hand over SSH.
- iss-2610260459250412abcd build, run in a fresh store worktree of a checkout abcd manages, refuses at the state stage because .abcd/.work.local/ is not a directory there, and its remedy names abcd ahoy, which installs abcd rather than making the tier. AGENTS.md sends every concurrent session to its own store worktree made with a plain git worktree add, which never carries the gitignored tier, so every build or drain started that way is refused until the tier is made by hand with mkdir. Seen on 2026-10-26 restarting build itd-82 from ~/.abcd.noindex/worktrees/<root-sha>/itd-82-build.
- iss-2610260845422800The load gate queues a targeted go test (one package, a few minutes) behind whole preflights in one FIFO line, so a short job starves: on 2026-10-26 an implementer's package test for the review-set lane timed out at the gate twice at the 2h limit, behind 19 waiters and 17 make preflight processes (load averages 31.5, 20.7, 40.5 at 09:44). Neither the fixed admission count (iss-2610161756384596) nor the ungated stages (iss-2610241214065079) covers the ordering: even a measured admission count keeps a short job behind every long one already queued.
- iss-2610261151381604make preflight does not run the two hosted scans CI runs on every pull request, gitleaks over the commits the pull request would land and govulncheck over the module, so a finding either of them makes is found only after the push, in a hosted run. Between 2026-10-18 and 2026-10-26 they failed 12 of 32 failed CI runs: govulncheck 10 (one newly published standard-library vulnerability, on every pull request and queue entry from 2026-10-21 until the toolchain moved to go1.26.10 on 2026-10-22) and gitleaks 2.blocks iss-2610261151481013
- iss-2610261151481013When the default branch itself fails a hosted check, every branch pushed meanwhile pays a hosted run that is certain to fail, and nothing local says so before the push. From 2026-10-21 to 2026-10-22 a newly published Go standard-library vulnerability failed govulncheck on the nightly run and then on every pull request and queue entry, 10 runs, for about a day and a half, until the toolchain bump landed. A branch that changed neither go.mod nor go.sum could not have introduced it, and its author could have been told to land the bump first.blocked by iss-2610261151381604
- iss-2610261152125261RS004 on the pull-request form, every issue id the title and body name declared on a Refs: or Resolves: line, is checked only by the hosted attribution workflow, although the title and body exist before gh pr create runs and the shell guard already reads them for the outbound policy. Between 2026-10-18 and 2026-10-26 it failed 4 pull-request runs, each fixed by adding one line to the body.
- iss-2610261339023831Re-running a failed attribution run after fixing the pull-request body (gh run rerun on the old run) replays the event the run was started with, so it checks the old body again and fails. The re-run joins the attribution-<pr> concurrency group and cancels the newer run that the body edit started, which would have passed. On 2026-10-26, PRs #1129 and #1133 each sat red for about four hours: the edited runs 40325771175 and 40325732363 were cancelled, and runs 40298736534 and 40298846131 failed again on the bodies they started with.
- iss-2610261616580903abcd capture writes an issue body the site renderer refuses, and nothing says so until the next record-lint run. The text is written as given: the capture path runs neither the prose cleaner the consistency ingest uses nor the body-render check record_schema applies at the gate. So a placeholder named after a void HTML element (input, link, source), or a link to a path the site cannot resolve, lands in the record and is refused only later. On 2026-10-26 two such records stopped a landing preflight after six hours in the load gate's queue.
- iss-2610261617079475TestAStepWithNoRunNamedAddressesTheNewerRunOfAReadmittedIssue failed once in CI's check (ubuntu-latest) job on PR 1134 and passed when the same tree was run again. Resolve reported two runs in progress, run-2610261029093535 and run-2610261029099737, so the handed-back run was not treated as superseded by the newer one. Both run ids were minted in the same wall-clock second, although the test's injected clock moves a minute between the two runs. So the ids come from the real clock, and the newer run is likely told apart by id order, which within one second is the random suffix.
- iss-2610261617171196The reviews-charter self-test once reported its case 'RD001 a symlinked review folder' as failing although the output it printed contained RD001, and the case passed on a rerun. scripts/check-reviews-cases.sh checks a case's needle by piping printf into grep -q under set -o pipefail, so the pipeline's status is the writer's too. When grep has matched, a writer that exits non-zero still makes the check report the needle missing.
- iss-2610261622501094The implement loop lists a checkout's runs oldest first by sorting their ids, but a run id is the second it was minted in plus four random digits, so two runs started within one second come back in random order. superseded() then reads a handed-back run as the newer of the pair, both count as in progress, and a bare record read or step refuses with '2 runs are in progress'. TestARecordReadWithNoRunNamedAddressesTheNewerRunOfAReadmittedIssue failed this way in CI on 2026-10-26 on a records-only pull request (#1136).
- iss-2610261651489204abcd intent consistency ingest writes a 00-summary.md that the reviews-charter gate refuses once a pass files enough findings. renderConsistencyReport puts the table of every finding and every finding's full text into the one summary, and RD004 (scripts/check-reviews.sh) refuses a summary past the 1 MiB the board reads. The 2026-10-26 whole-corpus pass, with 1307 findings, wrote 1.64 MB, and nothing said so until lint-reviews ran on the branch. The summary was split by hand: its table stayed in 00-summary.md and the full findings moved to 01-findings.md.
- iss-2610261739363732A drain lane finished outside the implement loop leaves the drain stuck: lane 1 of run-2610240852593097 (iss-2610142134353345) was refused at its implementer receipt on 2026-10-24, then finished by hand on 2026-10-26 (main merged in, record resolved, an Opus and a Sonnet review, a gated preflight, PR 1138 opened with Resolves). The run still says 'awaiting the implementer's receipt', and every abcd drain move answers 'drive the lane with implement step' and opens nothing more. No verb adopts a pull request opened by hand for a lane, or retires a lane whose work landed elsewhere; handing a receipt back would re-run the validators and open a second pull request, and a hand-back would discard the branch the open pull request is built on.
- iss-2610261837062463A build's reservation lapses while the host waits on an agent, because only implement step renews it (renewReservation in internal/core/implement/loop/reservation.go): build itd-82's run-2610260500113538 reserved itd-82 until 07:00Z, its implementer then held the implement stage for about thirteen hours under the shared machine's load gate, and no step ran to renew it. Revived after the lapse, the reservation is judged like a new one (crowd.go), and a build's automated act backs off on any overlap with the same person's other copy, so the renewal was refused for loop.go, in the footprint of iss-2610142134353345, live from the main checkout. The run goes on to validation holding no reservation, and the land fence will stop it, though nothing of the other record's work touches the lane's files.
- iss-2610261846399326TestARecordReadWithNoRunNamedAddressesTheNewerRunOfAReadmittedIssue (and its two siblings in drain_repace_test.go) fail about half the time: superseded() in drain_readmit.go treats a later entry of Runs as the newer run, and Runs is ordered by run id, but the readmittedRuns fixture opens both runs within one wall-clock second (its clock advances o.Now by minutes, which the run id does not read), so the two ids share their timestamp and order by the random suffix. CI failed PR 1137 on it on 2026-10-26 with run-2610261539014434 (newer) sorting before run-2610261539014869 (handed back): '2 runs are in progress'. In production two runs of one issue in one second are rare, so the defect is the ordering assumption more than the fixture.
- iss-2610261852072295The shell guard's tokenizer has no notion of [[ … ]]: it cuts [[ $n -gt 1 && $a == *x* && $d == "$c" ]] at each && into separate segments, so $d == "$c" ]] reads as a command whose program the line does not fix. The guard then guesses $d may be a shell (a guessed sh -c payload) and re-reads its words as a shell string with the variables' values written in, so a quoted value such as c=" >8 " becomes a redirect to a file 8. A shell run of any script later in the same script then warns script-written-then-run (a write the guard cannot place). Found on .githooks/commit-msg's is_scissors test (cut_line holds ' ------------------------ >8 ------------------------') once the hook ran check-issue-resolution.sh through bash after it; minimal repro: a script of c=" >8 ", that [[ ]] line, then bash /abs/script.sh. Traced in a debug build: payload.go's kindShell ref with guessed:true, payload '== >8 ]]', from a segment whose tokens are [<unknown> == ' >8 ' ]].
- iss-2610262030262031The press release says disembark pack runs three agent passes; the disembark chapter says pack is one deterministic run with no model passes
- iss-2610262030273891Meta says embark writes the new repo's brief by reversing the mapping; the embark chapter says only the record families land and everything else is never written
- iss-2610262030276998The press release's embark criterion promises an interview, a brief README and memory/docs/terminology; the embark chapter has no interview and writes only record families and the marker block
- iss-2610262030285264Meta says lifeboat-composer agents produce the skeleton's shape; the disembark chapter says pack dispatches no agents
- iss-2610262030288703Platform says past disembarks are recorded with a label; the voyage-log chapter says the entry carries no label
- iss-2610262030290887Platform says the markdown plugin surface is a later front door; the ahoy chapter describes the slash command already dispatching every sub-verb
- iss-2610262030294754The press release says install writes a marker block in AGENTS.md and the prompt-router hook; the ahoy chapter says a default install writes the block nowhere
- iss-2610262030301422The press release calls bare-shows-status a universal convention; the naming page says conformance is partial and several verbs refuse or act instead
- iss-2610262030301816The press release lists `/abcd:run` as in-scope operator wiring; the scope page says it is not built and its intent is superseded
- iss-2610262030315186Context presents `.abcd/corpus.json` as an existing, seeded validation-corpus list; the naming page says the name is reserved and not yet in the tree
- iss-2610262030315625Context's lifeboat diagram shows research/ and audit/ as pass B/C outputs; the disembark chapter says pack runs no model passes and its output shape has no such directories
- iss-2610262030322001Context keeps `intent ship` as a design target that drives a spec to completion; the scope page says closing the spec ships the intent and there is no separate ship command
- iss-2610262030324496The mental model describes the capture-kind classifier as operating; the naming register marks it staged with no classifier sub-verb registered
- iss-2610262030331903The mental model gives Modification Grammar three sub-headings; the tradeoffs page records a four-axis section that includes Ripple
- iss-2610262030338994The mental model defines a standalone intent as shipping as one spec; invariant 17 makes an intent own one or more specs as the normal state
- iss-2610262030341371Invariant 8 puts an Acceptance block on every 'brief phase'; the mental model puts it on the press release and surface chapters, with phases retired
- iss-2610262030345408The launch chapter says the repo organises work by phase per adr-9; the mental model says the phase is retired and adr-9 superseded
- iss-2610262030354678The naming register still files commands under 'later phases'; the scope page says the phase is retired as a unit of the record
- iss-2610262030354870The constraints index calls the invariants page a placeholder pointer; the page calls itself the canonical register
- iss-2610262030357877The evidence index says every file in the chapter is live; the tradeoffs page is marked PARTIAL
- iss-2610262030363874The naming register defines `managed-repo` as needing `.git/` and accepting an in-tree `.abcd/`; the ahoy chapter rejects both
- iss-2610262030364518Dependencies says abcd stamps `schema_version: 1` everywhere; the voyage log's documented entry carries `schema_version` 2
- iss-2610262030374385The scope page says closing the spec ships the intent; invariant 17 says closing a spec never ships an intent that still has an open spec
- iss-2610262030375215Invariant 3 says every capability is reachable with no plugin host; ahoy says preparing a repository runs only as a host-agent workflow the CLI cannot yet do
- iss-2610262030385476The mental model calls the Now / Next / Later status block a planned intent; the scope page says the bare `/abcd` board renders it
- iss-2610262030388384Dependencies names RepoPrompt and codex as oracle adapters; ahoy says host-delegated is the only oracle answer with an adapter
- iss-2610262030391056Meta's truth rule bans aspirational maybes from the brief; the press release's open questions carry one outside the registered question homes
- iss-2610262030398252Invariant 18 says surface-chapter prose states no flag the tree registers; the launch chapter's prose names its `dry-run` flag outright
- iss-2610262030401652Phases are history on the scope page, yet the intent chapter defines planned/ as scoped into a roadmap phase
- iss-2610262030409180The scope page derives build order from dependencies and shelves; the intent chapter names the phase plan as the canonical build order
- iss-2610262030410509Invariant 17 makes the intent-to-spec relation 1:n; the intent chapter's kinds table maps a standalone intent to one spec (1:1)
- iss-2610262030417187Invariant 8 requires every intent's press release to carry Acceptance Criteria; the intent chapter says a bench draft may carry none
- iss-2610262030422370The mental model's default discipline route is plan or reclassify from drafts/; the intent chapter's reclassify refuses any move into disciplines/
- iss-2610262030424329The mental model presents a capture-time classifier that emits the decision verdict; the intent chapter says nothing of it exists or reads the field
- iss-2610262030434632A bundle's shared spec is intent: [itd-A, itd-B] in the mental model but a scalar intent: beside an intents: list in the intent chapter
- iss-2610262030435247The mental model describes Role 3 as a continuous audit role; the intent chapter makes it on-demand only and defers continuous invocation
- iss-2610262030439309The mental model gives intent-auditor a discipline role that checks every spec; the intent chapter gives it three roles, none of which does
- iss-2610262030443173The mental model says disciplines use Given-When-Then under ## Rule; the intent chapter says nine of sixteen use a different idiom with no acceptance section
- iss-2610262030446141The ADR store's filename shape is adr-N-< slug>.md in the mental model and zero-padded NNNN-< slug>.md in the intent chapter
- iss-2610262030459672The mental model says principle-distiller extracts each spec's Modification Grammar into memory at spec completion; the library chapter says that extraction is not built
- iss-2610262030459678The press release lists intent grill as a designed companion per itd-27; the intent chapter says itd-27 is superseded by itd-94
- iss-2610262030467492The context page carries intent grill as designed-not-built per itd-27; the intent chapter says its intent is superseded
- iss-2610262030468053The naming register marks /abcd:intent grill staged under itd-27; the intent chapter says itd-27 is superseded
- iss-2610262030472547The press release says the library curates its knowledge substrate from the documents you consult; the library chapter says nothing connects the corpus to the memory store
- iss-2610262030475870The context page says disciplines move drafts/ to disciplines/ on plan; the intent chapter says plan's discipline branch does not ship
- iss-2610262030481186The naming register says Role 2 verifies registration on every plan-review; the intent chapter runs Role 2 on demand only
- iss-2610262030485894The press release's acceptance criterion expects an interview yielding a persona quote and Given-When-Then criteria; the intent chapter's create seeds the criteria as prompts
- iss-2610262030486866The personas page says the quoted create picks a persona for the customer quote; the intent chapter says the create writes the quoted text as the press release
- iss-2610262030494155The register defines the audit bucket as reality against a recorded commitment; the intent chapter files the document-against-document consistency pass under audit
- iss-2610262030497817The naming register attributes /abcd:audit lifeboat to itd-16; the intent chapter attributes it to itd-35
- iss-2610262030507151The naming register lists memory as a live exempt surface; the library chapter says the memory command merged into library with no surviving alias
- iss-2610262030509054The naming register makes glossary/ the only glossary; the intent chapter waits on a terminology/ directory for the same role
- iss-2610262030511283The board's design target reads a recent-logbook section; the naming register retires the logbook and forbids re-minting it
- iss-2610262030516940The register defines voyage as the operator-level record of operations; the reflect chapter uses voyage for a project and its store
- iss-2610262030520052The press release says state-mutating actions require an explicit sub-verb; the capture fast path writes a record from a bare quoted argument
- iss-2610262030522067The press release calls bare-shows-status-and-next-actions universal; the intent chapter says it is common, not universal
- iss-2610262030530560The press release's criterion files an issue from text alone; the capture chapter refuses any new filing without a remedy
- iss-2610262030536960The truth rule admits only shipped or decided staged machinery; the intent chapter keeps a staged audit-loop design it says was re-scoped away
- iss-2610262030547620The truth rule says everything in the brief is decided; the board chapter's design target rests on a superseded intent with no spec
- iss-2610262030547982The naming register marks the PRD-freeze vocabulary as machinery abcd neither ships nor plans; the intent chapter specifies it as a later-phase plan front end
- iss-2610262030556470The mental model says the intent for the Now / Next / Later status block is still planned; the site chapter describes the status page and the bare board rendering that block as shipped behaviour.
- iss-2610262030559592The mental model calls the itd-60 doc-fidelity loop planned and not yet exercised; the docs chapter describes the itd-60 doc-fidelity gate as a working gate in the present tense.
- iss-2610262030561707The naming register calls `~/.abcd.noindex/history/` the history store's registry; the history chapter says that directory is ahoy's registry, holds no transcripts, and that the history store lives under `~/.abcd.noindex/transcripts/`.
- iss-2610262030564496Invariant 2 says a missing or misbehaving adapter falls back to the native path and abcd never blocks; the reading chapter says a cold-reading dispatch whose provider cannot be reached exits 2 with nothing ingested.
- iss-2610262030567363The mental model says the brief's surface chapters carry an `## Acceptance` block in Given-When-Then format; the identity chapter has no such block and names an issue as its acceptance corpus instead.
- iss-2610262030576576Invariant 4 says all inter-agent data is JSON and markdown is only a render step; the history chapter's reconstruct artefact is Markdown precisely because a model reads it.
- iss-2610262030578776The mental model gives ADR files the shape `adr-N-<slug>.md`; the decide chapter says an ADR's filename is its stamp followed by its slug.
- iss-2610262030580466The reserved-vocabulary register fixes review verdicts as SHIP / NEEDS_WORK / MAJOR_RETHINK; the docs chapter's saved docs review returns PROMOTE, HOLD or INCONCLUSIVE, which the register does not hold.
- iss-2610262030587661The meta page says unsettled questions are recorded only as registered open questions or as explicit `Open question` notes; the reading chapter carries an owed product-thinker ruling inline, in neither form.
- iss-2610262030591199The mental model calls per-step lanes planned (itd-2609212103565953), while the build chapter describes one lane per spec step as shipped behaviour
- iss-2610262030597155The reserved review-verdict enum is SHIP/NEEDS_WORK/MAJOR_RETHINK, but the build loop parses SHIP/FIX FIRST and APPROVE/BLOCK/NEEDS-INPUT as review verdicts
- iss-2610262031003182/abcd:memory names the itd-36 curated memory substrate with ingest/ask/lint in the tradeoffs record, and a separate memory-notes store with add/list/remove in the memory chapter
- iss-2610262031008610Invariant 19 lists every record filed before the remedy field as ineligible, but the drain reads such a record's suggested_fix as its remedy
- iss-2610262031014454The dependencies page says abcd needs no external tools beyond the planned runner fence, yet the dashboard verb refuses to start without Tailscale running
- iss-2610262031016592Invariant 3 says every capability is reachable with no plugin host present, but the build chapter says a host session always drives the loop and the no-host path is not built
- iss-2610262031019028The naming rule forbids `<verb> show` at design time, but the inbox chapter ships a show sub-verb and does not mark it as a gap
- iss-2610262031021492The press release states as universal that a bare command shows status and mutations need a sub-verb, but bare `abcd drain` performs a mutating move
- iss-2610262031025833The press release says bare invocation only shows status, but bare `abcd report` opens an editor and files a report into the inbox
- iss-2610262031035884The register reserves 'claim' vocabulary for itd-33's later-phase coordination unit, while the implement chapter ships a different 'claim' as its unit of exclusion
- iss-2610262031039632The meta page says the brief/lifeboat skeleton is the one canonical shape, but the lab chapter calls an intention/method/candidates layout 'the lifeboat's section shape'
- iss-2610262031040280The mental model defines a step as one of a spec's ordered pieces, while the implement chapter also uses 'step' for the landing's sub-stages
- iss-2610262031042857The scope page says blocked_by and builds_on decide when a lane can take an intent, but the build's checks read only blocked_by
- iss-2610262031052928The press release says `disembark pack` runs three passes, chat retrieval among them, but the agent catalog says the pass A/B/C agents are unbuilt design targets
- iss-2610262031053276The press release says every state-mutating action needs an explicit sub-verb, but bare `abcd land` pushes and queues with no sub-verb
- iss-2610262031058243The press release puts `/abcd:run` operator-internal wiring in scope, but the surfaces index lists every registered verb and `run` is not among them
- iss-2610262031060442The press release lists golden-test fixtures, a periodic SOTA audit and a self-improvement pre-flight as in-scope plumbing, but the prompt-quality chapter says those layers are staged
- iss-2610262031062811The press release's acceptance has capture write an issue file, but universal patterns calls capture (and intent and spec) a read-only render
- iss-2610262031070645The context page calls the library's curated pages a 'memory store', but the surfaces index gives the name memory to the notes command only
- iss-2610262031074393The mental model gives intent-auditor a discipline role that checks every spec, but the agent catalog lists three roles and none of them is a discipline role
- iss-2610262031080269The mental model cites the lint chapter for the reserved code VR001, but the lint chapter says the engine has no numbered code catalogue
- iss-2610262031086206The mental model has principle-distiller extract each spec's Modification Grammar at spec completion, but the agent register says it serves only disembark, distilling a packed lifeboat
- iss-2610262031090459The naming register relies on Role 2 to verify spec vocabulary registration at every plan-review, but Role 2 reads only the brief and the intents, through its own verb
- iss-2610262031092650The naming register refers to lint rules by numbered codes (GL002, SD001, VR001), but the lint contract says rules are named, not numbered
- iss-2610262031105533The naming register says the glossary lives only under `glossary/`, but the designed grill log writes glossary terms to `terminology/`
- iss-2610262031105957The naming register ties the `review` bucket (a change judged) to family-1 verdicts, but the agent catalog says family 1 judges only lifeboats and the change reviewers' verdicts are not family 1
- iss-2610262031108321The naming register says the refresh backstop forces a full re-inject regardless of dedup, but the configuration chapter says a domain still in force is never re-injected unchanged within a session
- iss-2610262031110865The dependencies page presents the run seam (and the spec and history seams) as live, with external loops behind one contract, but the adapters chapter says those seams are design targets
- iss-2610262031113826The dependencies page says abcd stamps `schema_version: 1` everywhere, but the configuration chapter says six of the fourteen committed records carry no stamp
- iss-2610262031126042The platform page says the markdown plugin surface is a later front door, but the configuration chapter describes it as part of the shipped plugin shape
- iss-2610262031127666The platform page says an MCP server is a later front door, but universal patterns says abcd interoperates with the companion harness as an MCP server
- iss-2610262031138048Invariant 4 says all inter-agent data is JSON, but the agent catalog says the implement loop reads the reviewers' prose verdict headings
- iss-2610262031138510Invariant 6 says the voyage record is never committed, but universal patterns says voyage is tracked under the visibility rule
- iss-261026203114197804-scope counts eighteen agents in the canonical roster; 07-memory says the agent count stays at 15.
- iss-2610262031147190The scope page says an intent ships when its linked spec closes, but the spec verb ships it only when no open spec still names it
- iss-261026203115329204-naming registers /abcd:intent grill as a staged sub-verb under itd-27; the build sequence says itd-27's grilling is the planning interview under itd-94, which supersedes it.
- iss-261026203115927702-context lists grill and ship as remaining intent design targets; the build sequence says there is no intent ship and no grill sub-verb, shipping running through spec close and grilling through the planning interview.
- iss-261026203116196105-personas says the canonical create picks a persona for each press release; the verification matrix stages persona selection and says nothing selects.
- iss-261026203116704804-naming defines force_refresh_every_n as a full re-inject forced every N prompts; the verification matrix says the rules-loader refresh is event-driven and nothing counts prompts.
- iss-2610262031168083The press release's acceptance criteria have the bare quoted create complete an interview, and embark open with a press-release interview; the verification matrix says bare quoted text runs no interview and stages the embark interview.
- iss-261026203117603602-dependencies describes the native spec store as directories plus a dependency graph; the verification matrix stages the graph and says the spec core carries none.
- iss-261026203117749202-dependencies presents the pluggable run seam, with a native loop as its fallback, as a present native default; the build sequence marks the run seam a design target that does not ship.
- iss-261026203118694902-dependencies includes a thin native Go loop among the run seam's loops; the loop glossary entry says abcd never owns the run loop, an adapter supplying it.
- iss-261026203118863704-scope defines what has shipped by the intents in shipped/ and the derived release, phases being history; 03-out-of-scope still frames the brief around eight planned phases and defines what has shipped by which phases are complete.
- iss-261026203119546303-mental-model says planning several intents onto one spec in one act (itd-34) is planned; the verification matrix records the --bundle plan as shipped behaviour.
- iss-261026203119644003-mental-model says a bundle's shared spec carries intent: [itd-A, itd-B]; the verification matrix says it carries intents: and bundle:.
- iss-261026203120447503-mental-model says the step is not a record family; the record-families page lists step as one of abcd's record families.
- iss-261026203120918203-mental-model describes the itd-44 capture-time classifier as running; 03-out-of-scope lists itd-44 as an uncommitted draft.
- iss-261026203121391901-platform calls the markdown plugin surface a later front door and a new adapter over the core; the verification matrix treats commands/*.md shelling to the binary through the CLI as delivered wiring.
- iss-261026203121689003-mental-model says a spec orders its work as steps under ## Steps; the spec glossary entry defines a spec as broken into ordered tasks.
- iss-261026203122680304-naming dates its reserved commands to a later phase; the glossary retires the phase as a unit.
- iss-2610262031228119Invariant 8 says every brief phase has an ## Acceptance block; the glossary records the phase as superseded.
- iss-261026203122875201-platform uses transport for the front doors of a transport-agnostic core; the glossary defines transport only as the mechanism delivering context to an oracle.
- iss-261026203123005904-naming retires the logbook name and forbids re-minting it; the lifeboat glossary entry lists a logbook summary among a lifeboat's contents.
- iss-261026203123941306-framing calls its construal the ledger's, bare, meaning the ledger work; the ledger entry reserves bare 'the ledger' for the issue ledger.
- iss-261026203124609004-naming marks the voyage embark subtree as staged names nothing writes; the voyage entry defines the voyage as recording every embark run and lists the embark paths unmarked.
- iss-2610262031246229The press release calls the review model a host-delegated LLM; the oracle glossary entry forbids LLM as a synonym for oracle.
- iss-261026203125860404-tradeoffs records that a pack either completes or writes nothing, with no state file at any path; the verification matrix stages a forensic checkpoint written on a mid-pack interrupt.
- iss-2610262031259318The brief README reads spc-N references throughout the brief as predecessor-store ids; 04-naming says an unqualified spc-N resolves in the live store and a predecessor id must be marked as such.
- iss-261026203126277900-meta's truth rule has brief prose say what is shipped and what is staged; the brief README says delivery state lives in the roadmap dashboard and never in brief prose.
- iss-261026203126758104-naming sends readers to the roadmap dashboard for delivery state; the roadmap glossary entry says the Now / Next / Later status block replaces the roadmap document and the word.
- iss-261026203127167007-memory says session memory is distilled via dev-sync memory as existing behaviour; 04-naming's register of every surface carries no dev-sync verb.
- iss-2610262031278962The framing chapter already exists under 01-product/; 03-out-of-scope lists itd-143, which promises that chapter, as work not yet under way.
- iss-2610262031280238The press release counts /abcd:run, the itd-29 operator surface, among the plumbing in scope; the build sequence says the run seam does not ship, no run verb is registered and itd-29 is superseded.
- iss-261026203128458204-scope counts 11 adapters in abcd's plumbing; the build sequence says the scanner is the one capability seam standing beside four further adapter packages, the other seams being planned.
- iss-261026203129354702-context gives /abcd:library six corpus sub-verbs beside ingest, ask and lint; 07-memory says the shipped library surface carries ingest, ask and lint and nothing else.
- iss-2610262031298011itd-16 lands its hash chain under .abcd/logbook/audit/, the retired logbook locationrelated itd-16
- iss-2610262031299872itd-1 writes each audit run's forensic copy under .abcd/logbook/, a location the naming chapter has retiredrelated itd-1
- iss-2610262031301413itd-25 writes dredge synthesis reports under .abcd/logbook/dredge/, the retired logbook locationrelated itd-25
- iss-2610262031305231The naming chapter stages /abcd:audit lifeboat under itd-16, while itd-16 assigns that sub-verb to itd-35related itd-16
- iss-2610262031315138itd-25's dredge promote calls /abcd:intent new, which the brief says is refusedrelated itd-25
- iss-2610262031318900itd-25 designs a plain dredge list sub-verb, which the bare-command-as-render discipline forbidsrelated itd-25
- iss-2610262031326077itd-5 counts 14 (now 15) agents under its rule, while the press release counts eighteenrelated itd-5
- iss-2610262031329436itd-10's destroy removes an in-tree lifeboat inside .abcd/, but the platform rules say no in-tree lifeboat home existsrelated itd-10
- iss-2610262031337587itd-5 preserves a fixed oracle cascade that the dependencies chapter says does not existrelated itd-5
- iss-2610262031338081itd-5 has lint_prompts validate task_classes against an enum in internal/core/lint; the naming register says the binary carries no such schemarelated itd-5
- iss-2610262031343432itd-26 names the knowledge ingest verb /abcd:memory ingest, while the brief puts ingest under /abcd:libraryrelated itd-26
- iss-2610262031344534itd-26 designs a plain loot list sub-verb, which the naming discipline forbidsrelated itd-26
- iss-2610262031347358itd-26 calls loot-quartermaster the 16th agent, while the scope chapter already counts eighteenrelated itd-26
- iss-2610262031350187itd-126 drives the sources corpus through a source verb, while the brief keeps the corpus under /abcd:libraryrelated itd-126
- iss-2610262031355278itd-2609292108089653 refuses stubs at source add, while the brief's add for the sources corpus is a library sub-verbrelated itd-2609292108089653
- iss-2610262031362638itd-190 says the discipline template carries no claim sections, while the mental model says disciplines carry Given-When-Then acceptancerelated itd-190
- iss-2610262031362851itd-21 files the starter intent as itd-1, an id the collision-proof minting invariant does not allocaterelated itd-21
- iss-2610262031375064itd-196 runs its cumulative and closing rehearsals per phase, while the mental model retires the phaserelated itd-196
- iss-2610262031376440itd-192 decides a verdict by whether this phase wires a criterion, while the scope chapter makes phases historyrelated itd-192
- iss-2610262031376538itd-143 leaves the framing section's position and filename to its planning interview, while the product chapter already lists 06-framing.mdrelated itd-143
- iss-2610262031383285The lab discipline assembles its harvest in the lifeboat's section shape but names sections the canonical skeleton does not haverelated itd-2609251624540864
- iss-2610262031389232itd-142 pre-populates a brownfield repository from embark probe coverage, but embark probe reads a lifeboat, not a repositoryrelated itd-142
- iss-2610262031396689Invariant 17 lists three readers and what each does with no test behind it, the shape itd-195 forbidsrelated itd-195
- iss-2610262031398929Invariant 14 counts the committed scope as part of the construal, while the glossary says scope is never the construal
- iss-2610262031401131The read-block entry puts all the instrument's own outputs inside the block, while invariant 15 admits widening-run items at the comparative position
- iss-2610262031403463The press release gives the product-thinker role to Iris, while itd-106 gives it to Alicerelated itd-106
- iss-2610262031409019itd-2609301020001595 quotes an unnamed product thinker, while the personas principle forbids generic attributionrelated itd-2609301020001595
- iss-2610262031418522itd-2609301918174237 quotes an unnamed product thinker, while the personas principle forbids generic attributionrelated itd-2609301918174237
- iss-2610262031419126The naming register reserves `/abcd:audit` for itd-16's formal-verification surface, but itd-85 takes `abcd audit` for a repo-conformance check.related itd-85
- iss-2610262031420591Scope says the phase documents are history, but itd-78's graph lint fails on a phase that scopes an intent before its blocker's phase.related itd-78
- iss-2610262031429165The mental model retires the phase and the milestone, but itd-41 builds a negotiator that proposes phases and their Phase Acceptance under adr-9.related itd-41
- iss-2610262031430108Invariant 11 forbids minting ids from the current maximum, but itd-44 has capture write `adr-<next-free>-<slug>.md`.related itd-44
- iss-2610262031437177The naming register retires `.abcd/logbook/` and fails the build on it, but itd-35 writes its verification report under `.abcd/logbook/audit/`.related itd-35
- iss-2610262031439210Invariant 15 puts the session-transcript store at `~/.abcd.noindex/transcripts/<root-sha>/`, but itd-59 feeds a corpus at `~/.abcd.noindex/history/<root_sha>/`.related itd-59
- iss-2610262031445176Dependencies say abcd is a single Go binary and that flow-next is neither a dependency nor built, but itd-44 treats Python 3.12 and flow-next as existing plumbing.related itd-44
- iss-2610262031445910Context says `abcd intent new` is refused, but itd-30's format chooser runs on `/abcd:intent new --format=fiction`.related itd-30
- iss-2610262031451829The press release names the Role 1 auditor `intent-auditor`, but itd-30 calls the same reader `intent-fidelity-reviewer`.related itd-30
- iss-2610262031459784The press release says `/abcd:ahoy install` writes the AGENTS.md marker block, but itd-83 says `prepare-this-repo` owns that section.related itd-83
- iss-2610262031462724The naming register makes `/abcd:ahoy` the verb that installs abcd, but itd-57 scaffolds its sentinel with `abcd configure`.related itd-57
- iss-2610262031466884Context names `/abcd:ahoy install` as the install surface, but itd-91 puts its setup question in `/abcd:init` / `prepare-this-repo`.related itd-91
- iss-2610262031473469The naming rules forbid a plain unfiltered `<verb> list`, but itd-2609091014076309 makes `abcd ahoy worktree list` render the same thing as the bare verb.related itd-2609091014076309
- iss-2610262031474789The press release requires an explicit sub-verb for any state-mutating action, but itd-2610031215002409's menu under bare `abcd` starts a build at once.related itd-2610031215002409
- iss-2610262031474937The naming register already has `dashboard` as a verb of its own, but itd-2609151838312703 plans to rename the bare status board 'the dashboard'.related itd-2609151838312703
- iss-2610262031483571GRILL's asking rules say options never recommend, but itd-99 frames every technical choice put to the thinkers as options plus a recommendation.related itd-99
- iss-2610262031486321GRILL's asking rules say options widen and never recommend, but itd-97's escalation contract hands the product thinker a proposal with a recommendation.related itd-97
- iss-2610262031492489Invariant 15 refuses any path at a reading's invocation, but itd-86's cold reading takes exactly one target document.related itd-86
- iss-2610262031493380The brief-lifeboat mapping grounds the mental model partly from conventions, but itd-90 treats the mental model as a human-owned section.related itd-90
- iss-2610262031496655Scope says itd-29 is superseded, but itd-97 builds solo mode over the pluggable run seam it names as itd-29.related itd-97
- iss-2610262031503691The mental model uses 'brief' for the project's canvas, but itd-2609201916151817 uses 'the brief' for the file an implementer is handed for one lane.related itd-2609201916151817
- iss-2610262031505758Dependencies present RepoPrompt and codex as oracle adapters an operator can select, but itd-2609170822093401 says nothing reads the oracle backend value today.related itd-2609170822093401
- iss-2610262031514386The personas page forbids generic, unnamed quote attributions, but itd-57's customer quote is credited to 'a facilitator'.related itd-57
- iss-2610262031516342The personas page forbids generic, unnamed quote attributions, but itd-64's customer quote is credited to 'a maintainer'.related itd-64
- iss-2610262031524343The personas page forbids generic, unnamed quote attributions, but itd-2609201916151817's quote is credited to 'a technical facilitator'.related itd-2609201916151817
- iss-2610262031524510The personas page forbids generic, unnamed quote attributions, but itd-2609221009495079's quote is credited to 'a product thinker'.related itd-2609221009495079
- iss-2610262031532200itd-199 ships a scope operand at invocation that it says was 'carried into brief invariant 15'; invariant 15 says that operand is superseded and the operands are position and target only.related itd-199
- iss-2610262031532231itd-7 has disembark's pre-pack step write .abcd/rp/workspace.json into the repository being read; invariant 6 says disembark never writes to the source.related itd-7
- iss-2610262031537827itd-7 depends on a dev-sync pre-pack step it calls 'already in brief'; the brief lists dev-sync only among out-of-scope work not yet under way.related itd-7
- iss-2610262031545672itd-2610161733316518 turns off the host fallback inside a matrix cell; invariant 2 says a missing or failing adapter degrades to the native path, and the brief declares no exception for this.related itd-2610161733316518
- iss-2610262031549181itd-147's press release says the generated appendix carries exit codes, schema fields and counts; invariant 18 says flags and sub-verbs only.related itd-147
- iss-2610262031557361itd-200 installs the status-line defaults under ~/.abcd/; invariant 21 names the user-level home ~/.abcd.noindex.related itd-200
- iss-2610262031557534itd-117 puts the user-scope rules at ~/.abcd/rules.json; invariant 21 names abcd's user-level home ~/.abcd.noindex.related itd-117
- iss-2610262031560983itd-39 extends a Python hook, hooks/prompt_router_hook.py; 02-dependencies says abcd ships as a single Go binary with no required external tools.related itd-39
- iss-2610262031563379itd-50 calls the per-criterion auditor intent-fidelity-reviewer; the brief names the same role intent-auditor (Role 1).related itd-50
- iss-261026203156590604-tradeoffs records /abcd:memory as the curated store's command with ingest/ask/lint; itd-39 says memory is now the agents' notes command and the store is reached through library.related itd-39
- iss-2610262031575425itd-82 requires a remedy on every new issue; the brief's acceptance criterion has /abcd:capture "< text>" alone produce a structured issue.related itd-82
- iss-2610262031575529itd-82 makes bare abcd drain the unattended run that changes state; 04-naming rules that a bare invocation renders and that changing state is what a sub-verb is for.related itd-82
- iss-261026203158203805-personas requires press-release quotes from the persona registry; itd-82's quote is attributed to an unnamed product thinker.related itd-82
- iss-261026203158220704-scope defines operator-internal verbs, rules and spec among them, as wiring with no commands/ file; itd-146 says operator_internal only means 'needs no surface chapter' and treats rules as user-facing.related itd-146
- iss-2610262031588576itd-146 places a changelog verb in the root help's agent block; 04-naming's register of exempt surfaces, which says every exemption is on the record, does not list it.related itd-146
- iss-2610262031592610itd-24 uses voyage for a project's working life; 04-naming reserves voyage for the operator-level operations namespace.related itd-24
- iss-261026203159866502-dependencies says abcd stamps schema_version: 1 everywhere; itd-166 moves run state to schema 14.related itd-166
- iss-2610262032001815The mental model says per-step lanes are a planned intent; that intent is on the shipped shelf and says the build lands steps one lane at a time.related itd-2609212103565953
- iss-2610262032008964The mental model says the Now/Next/Later status block's intent is planned; that intent is on the shipped shelf and says the board shows the block.related itd-2609212103568351
- iss-2610262032015266The mental model says planning several intents onto one spec (itd-34) is planned; itd-34 is shipped and records the bundle command as built.related itd-34
- iss-2610262032018111The agent holding the shape-classification third role is `intent-auditor` in the mental model and `intent-fidelity-reviewer` in itd-34.related itd-34
- iss-2610262032022112The intent's back-link to its spec is the scalar `spec_id` in invariant 17 and `epic_id` in itd-34.related itd-34
- iss-2610262032024089Invariant 17 makes the intent-to-spec relation 1:n; itd-34 says a standalone intent maps 1:1 to a spec.related itd-34
- iss-2610262032024609The dependencies page says flow-next is not a dependency and is not built; itd-34's lifecycle paths call `/flow-next:plan`.related itd-34
- iss-2610262032031758The naming register retires `.abcd/logbook/`; itd-34 puts the shape-classification findings under `.abcd/logbook/audit/`.related itd-34
- iss-2610262032038666The press release says `/abcd:intent shape` (Role 3) is designed and not yet built; the shipped itd-34 has that role in scope, running from the pre-commit hook and on demand.related itd-34
- iss-2610262032042626The context page says `abcd intent new` is refused; itd-4's `capture promote` calls `/abcd:intent new`.related itd-4
- iss-2610262032044265The scope page counts eighteen agents; itd-34 says the agent count in the catalog stays at 15.related itd-34
- iss-2610262032046139The register reserves `voyage` for the operator-level operations namespace; itd-36 uses `voyage` to mean a project abcd manages.related itd-36
- iss-2610262032050596The dependencies page says abcd needs no external tool and ships as one Go binary; itd-3 makes the prompt router a Python hook.related itd-3
- iss-2610262032051655The register puts the history-store registry at `~/.abcd.noindex/history/index.json`; itd-40 puts it at `~/.abcd/history/index.json`.related itd-40
- iss-2610262032060007The register gives the forced rules refresh a default of 15 prompts; itd-3 says it defaults to 5.related itd-3
- iss-2610262032061118The naming register still schedules reserved commands by 'a later phase'; itd-2609211913453478 retired the phase as a unit of sequencing.related itd-2609211913453478
- iss-2610262032071046The naming register says current delivery state lives in 'the roadmap dashboard'; itd-2609212103568351 retired the word roadmap and calls the block status.related itd-2609212103568351
- iss-2610262032072943Invariant 8 requires an Acceptance block in 'every brief phase'; phase is a superseded term.related itd-2609211913453478
- iss-2610262032073819The press release's open question moves work 'into an earlier phase'; phases are retired.related itd-2609211913453478
- iss-2610262032080136The press release lists the itd-29 `/abcd:run` operator surface as in-scope plumbing; itd-2609201925079472 says those hand verbs were dropped with itd-29.related itd-2609201925079472
- iss-2610262032088777Invariant 19 hands an issue naming an intent back by the rule `promoted`; itd-2610161016394967, citing invariant 19, calls such an issue ineligible.related itd-2610161016394967
- iss-2610262032092604Invariant 21 names abcd's home `~/.abcd.noindex`; itd-2609221656361680 puts the inbox at `~/.abcd/inbox/`.related itd-2609221656361680
- iss-2610262032094044Invariant 21 names abcd's home `~/.abcd.noindex`; itd-2609212137128014 records lab evidence at `~/.abcd/lab/`.related itd-2609212137128014
- iss-2610262032099691Invariant 21 names abcd's home `~/.abcd.noindex`; itd-2609231434459890 keeps the load-check limits in a settings file under `~/.abcd/`.related itd-2609231434459890
- iss-2610262032102172The persona Iris is a product thinker in the brief's press release and a technical facilitator in itd-2609150819445595.related itd-2609150819445595
- iss-2610262032106392The personas page says customer quotes use named placeholder personas from the registry; itd-2609211116005482 attributes its quote to an unnamed product thinker.related itd-2609211116005482
- iss-2610262032111048The mental model says a standalone intent ships as one spec; itd-2609091034175565, planned alone, is delivered through two specs.related itd-2609091034175565
- iss-2610262032113433itd-42 ships its coherence tier as a capability of an existing `/abcd:intent grill`; the naming register says the verb is staged and no `intent grill` sub-verb is registeredrelated itd-42
- iss-2610262032120773itd-48 puts Role 2 in `agents/intent-fidelity-reviewer.md`; the naming register says the cross-document role belongs to the intent auditor, `agents/intent-auditor.md`related itd-48
- iss-2610262032124254itd-48 writes consistency reports under `.abcd/logbook/audit/`; the naming register says `.abcd/logbook/` is retired and must not be re-mintedrelated itd-48
- iss-2610262032125902itd-42's worked example says invariant 3 is about config never being written outside `~/.abcd/`; the invariants register's invariant 3 is the native default front doorrelated itd-42
- iss-2610262032131693itd-48 says `/abcd:intent shape` is now a working command surface; the brief's press release says it is designed and not yet builtrelated itd-48
- iss-2610262032133109itd-48 runs both roles through a CLI oracle in headless Ralph mode; the dependencies page says the autonomous run is not a Ralph portrelated itd-48
- iss-2610262032144104itd-6 keeps a fixed RP MCP → Codex CLI → in-session cascade; the dependencies page says no such fixed cascade exists and that RepoPrompt, codex and a direct API oracle are opt-in adaptersrelated itd-6
- iss-2610262032146377itd-67 picks the release bump through brief §4 phase-completion detection; the mental model computes the version from the impact of what shippedrelated itd-67
- iss-2610262032157319itd-69's checker takes `--tree dev|public`; the platform page says there is no dev→public mirrorrelated itd-69
- iss-2610262032158578itd-67 generates the changelog from git tags, commit/spec history and the launch report; the scope page composes it from the records that reached a terminal folderrelated itd-67
- iss-2610262032158901itd-76 puts abcd's user-level home at `~/.abcd/`; the invariants register gives the home as `~/.abcd.noindex`related itd-76
- iss-2610262032163067itd-80 names the Role 1 reviewer `intent-fidelity-reviewer`; the brief's press release says Role 1 belongs to `intent-auditor`related itd-80
- iss-2610262032168367itd-80 moves an intent to shipped when its linked spec closes; invariant 17 says a close never ships an intent that another open spec still namesrelated itd-80
- iss-2610262032172837itd-88 calls the packer `disembark <repo> to <dest>`; the platform page calls it `disembark pack <source-repo> <dest>`related itd-88
- iss-2610262032178049The brief's press release says pack runs three passes, including targeted chat retrieval over transcripts; itd-88 says Pass B ships only as a declared exemptionrelated itd-88
- iss-2610262032182670itd-95 says the richest present tier wins a section; the meta page says tiers are cumulative, so a richer tier can never ground a section worse than a poorer onerelated itd-95
- iss-2610262032188853itd-89 files transcripts in the local per-repo store; invariant 15 makes the user-level `~/.abcd.noindex/transcripts/<root-sha>/` the store, with a per-repo store only for a declared checkoutrelated itd-89
- iss-2610262032189264itd-96 grounds `internals` from conventions-tier documentation; the generated mapping table caps `internals` at partial for Tier 1 conventionsrelated itd-96
- iss-2610262032193797The mental model calls itd-60 planned, but itd-60 sits on the shipped shelfrelated itd-60
- iss-2610262032194841itd-46 treats `list` as a corpus-scope intent scan verb that already exists; the context page says there is no plain `list` sub-verbrelated itd-46
- iss-2610262032208043Capture says the release guard never blocks a record graded below major; launch says it also blocks an absent or unreadable grade
- iss-2610262032208504Ahoy says every launch verb refuses an undeclared artefact kind; launch says the cut, the archive render and the receipts check assume the plugin shape
- iss-2610262032212691Launch says intents carry no version label; the intent chapter says a planned intent may name the release vX.Y.Z it must land by
- iss-2610262032214284Launch says the repo organises work by phase; disembark says sequence is dependencies plus the lifecycle shelves, with phases retired
- iss-2610262032223832Ahoy's preparation reads the brief, principles, ADRs and intents from the plugin root; launch says the plugin payload never ships the .abcd/ record
- iss-2610262032225288Ahoy says the docs target defaults to skip, writing no conventions file; embark says no saved choice gives AGENTS.md
- iss-2610262032226321Ahoy calls the remote apply the one verb that mutates state outside the machine; launch says the reservation verb means a push to origin
- iss-2610262032231296Library says the memory command merged into library with no surviving name; ahoy names a live memory verb that writes memory notes
- iss-2610262032238170Ahoy presents its ~/.abcd.noindex tree as the one inventory; the board's session naming writes a sessions/names.json register it does not list
- iss-2610262032245453Library says embark carrying the memory store forward is designed behaviour; embark says the memory store is not an embark family and does not travel
- iss-2610262032245680Library defers the lifeboat's memory payload to the spec that wires the packer; disembark has the packer shipped with a fixed file set and no memory section
- iss-2610262032250865Reflect lists planned intents whose target_release names the release; the cut has already rewritten every such target to next
- iss-2610262032256736Launch names its docs-lint gate row the documentation audit; the intent chapter keeps audit and lint as separate verbs, the conformance check being lint
- iss-2610262032258227Reflect's set of intents a release shipped follows shipped_in both ways; the cut only drops records whose shipped_in an earlier tag reaches
- iss-2610262032262544Embark's lessons view reads only retrospective lessons; disembark's graveyard also writes lessons into the same lifeboat
- iss-2610262032268272Embark's refresh-audit modifier diffs against a disembark-time audit; disembark produces a review verdict and no audit
- iss-2610262032272603lint says the outbound-policy gate is the only surface that judges text before it is public; ahoy says the shell guard also refuses forge text carrying the same two shapes before it is posted
- iss-2610262032275161Embark writes the ledger and intent store under a target defaulting to the working directory; capture holds that the root is resolved, never taken to be the working directory
- iss-2610262032282645ahoy's inventory of ~/.abcd.noindex/ has no away store; mode keeps the away record in ~/.abcd.noindex/away/< root-sha>/
- iss-2610262032283069ahoy's inventory of ~/.abcd.noindex/ has no after-update store; update's news sub-verb writes under ~/.abcd.noindex/after-update/
- iss-2610262032283948ahoy's inventory of ~/.abcd.noindex/ has no ideas store; ideate writes private verdicts to ~/.abcd.noindex/ideas/< root-sha>/
- iss-2610262032291598'history' names two things: ahoy's 'history store' could be the registry directory ~/.abcd.noindex/history/ or the history verb's transcript store
- iss-2610262032297115ahoy's setup mints the drain rule as an accepted record carrying drain_ fields through the decision store's seam; decide says a minted record lands empty and proposed, and names embark, a restore, as the only other writer
- iss-2610262032307333launch's citation-baseline row refuses on an overdue citation; docs says the launch preflight only names what would stop a release, while the release still cuts
- iss-2610262032308835docs and launch each own a change-narration check over the same doc bodies and give opposite verdicts on an ambiguous phrase: a warning in the docs lint, a refusal in launch
- iss-2610262032310109launch's artefact declaration reserves an inert opt-in for the release-rendered site; site describes a shipped setup that already writes a workflow rendering the site from each published release
- iss-2610262032317368docs says the release workflow runs the lint's release-gate mode while the scaffolded release template never names the verb; launch says abcd's own release workflows are regenerated byte-exact from those templates
- iss-2610262032321103Ahoy's history store is a registry that holds no transcripts; build's history store is where a runner's transcript lands
- iss-2610262032326065Ahoy calls the remote apply the one verb that mutates state off this machine; reserve exists to write a branch on the shared remote
- iss-2610262032328073Implement's record verb captures transcripts into the history store, which ahoy says holds no transcripts
- iss-2610262032331100Ahoy says only host-delegated has a reviewer adapter; build routes lane reviews to RepoPrompt
- iss-2610262032338974Implement says abcd calls no model; ahoy has a delegating verb send its step to a configured provider itself
- iss-2610262032345454Lab says its harvest takes the lifeboat's section shape, but disembark gives the lifeboat a different set of sections
- iss-2610262032346952Ahoy's inventory of ~/.abcd.noindex has no dashboard/ entry, but the dashboard keeps its run file and device list there
- iss-2610262032353042Build's landing relies on the spec close to ship the intent, but no build check secures the impact that launch says the close requires
- iss-2610262032354048ahoy calls the remote apply the one abcd verb that mutates state outside the machine; land pushes branches to origin and queues pull requests
- iss-2610262032365346'decision log' is the live shared-tier store in configuration, but in ahoy it is a legacy single file kept as frozen history
- iss-2610262032368674configuration says install asks about the oracle backend; ahoy says the oracle backend is not asked
- iss-2610262032368998the ~/.abcd.noindex inventory is stated twice and says load-limits holds three limits in ahoy but two in configuration
- iss-2610262032378831ahoy says the docs check with empty roots warns at exit 0; the lint contract says a warning raises the exit code to 1
- iss-2610262032379645adapters has ahoy redirecting prompt exports into ~/.abcd.noindex/history/< root-sha>/; ahoy says history/ holds the registry only
- iss-2610262032381678agents puts press-release-composer under cite-or-be-dropped validation; disembark says the press release is accepted or refused as a whole
- iss-2610262032383787universal patterns puts the record of setup questions and answers in logs/ahoy/< timestamp>/prompts.json; ahoy writes it to .abcd/.work.local/interviews/
- iss-2610262032390626adapters lists a transcript reader that disembark packs from; embark says no source tier reads a transcript store
- iss-2610262032399341adapters says a user_docs reader copies the user docs verbatim into the lifeboat; disembark's output shape has only ADRs under docs/
- iss-2610262032399609the lint contract says documentation-auditor audits it on every disembark; disembark says packing dispatches no agents
- iss-2610262032400242universal patterns says the voyage store is tracked under the visibility rule; embark says it is never committed
- iss-2610262032400782embark treats an unset docs.target as agents_md; configuration says skip is the default
- iss-2610262032410731the lint contract counts 'previously' as change narration; launch's change-narration gate passes a bare 'previously' as present-tense prose
- iss-2610262032415141launch uses 'documentation-auditor' for its docs-lint warning gate; the agent catalog uses it for an unbuilt agent that audits docs
- iss-2610262032428223universal patterns says issue-ledger entries cannot change after creation; launch has the deferral verb write a waiver into an open record
- iss-2610262032429930configuration lists every .abcd/config.json key the binary reads, without release.digest; launch's cut reads release.digest from that file
- iss-261026203243169207-memory relies on the first /abcd:ahoy after itd-36 backfilling memory pages' source class; ahoy's detection and apply passes carry no such step
- iss-2610262032432036ahoy calls the library's store 'the local sources corpus'; the library glossary entry forbids 'corpus' as a synonym
- iss-2610262032437661ahoy says the user-scope ~/.abcd.noindex/memory/ resolves nothing today; 07-memory has the prompt hook querying the index of both the repo and the user memory scope
- iss-2610262032441828ahoy calls the setup answers file in the local tier an 'answers record'; the record entry says an artefact with no id and no minting command is not a record
- iss-2610262032445652the oracle glossary says a native, CLI, API or MCP oracle adapter is wired behind the seam; ahoy says every backend answer but host-delegated changes nothing about how reviews run
- iss-2610262032458294ahoy calls the remote apply the one abcd verb that mutates state outside the machine; 10-site has abcd site setup configuring forge environments through gh and the host through the hosting adapter
- iss-2610262032458879the verification matrix checks that ahoy's rules-loader install injects the marker block; ahoy's default docs target writes the block into no conventions file
- iss-2610262032464642the build sequence has the disembark pack run the host-delegated audit; disembark says packing dispatches no agents and runs no model passes
- iss-2610262032465065the build sequence says ahoy install carries its configuration as flags rather than a wizard; ahoy draws each value question and approval one at a time at a terminal
- iss-2610262032467744the matrix says the disembark read-only test hashes the source and asserts it byte-identical; disembark says the evidence is a fingerprint of path, mode and size, not a content hash
- iss-2610262032470373the voyage glossary's example has the voyage log record the host oracle a lifeboat was packed with; disembark says the voyage line carries no oracle backend
- iss-2610262032478338the matrix's multi-repo corpus check needs a validation corpus; disembark says the corpus manifest is not yet in the tree
- iss-2610262032480986the lifeboat glossary says a pack carries a logbook summary and configuration; disembark's output shape carries neither
- iss-2610262032482122disembark calls the packed lifeboat a 'snapshot'; the lifeboat glossary entry forbids 'snapshot' as a synonym
- iss-261026203249169007-memory names the lifeboat the surface that publishes curated project memory; disembark's pack inventory walks record families and brief sections and writes no memory
- iss-2610262032499433the matrix's round-trip check expects the embarked repo's memory to be a faithful subset; embark says the memory store does not travel
- iss-2610262032502060the voyage glossary says the voyage records every embark run; embark says voyage provenance on embark is not built
- iss-2610262032506491the record glossary says embark writes four record families; embark reads and writes five, adding release retrospectives
- iss-2610262032509493record-families maps intent, spec, step, bundle, issue, release and status; embark's 'record families' are ADRs, issues, intents, specs and release retrospectives
- iss-2610262032516143embark's lessons speak of 'the previous voyage' and 'the new voyage's brief'; the voyage glossary restricts the word to the operations namespace and forbids it for a project
- iss-2610262032517943'embark' names the grill session's unshipped opening move in the interview glossary and the shipped lifeboat-unpack command in 03-embark
- iss-2610262032520382the phase glossary names Phase 1 'Substrate'; launch links Phase 1 as the ahoy phase document
- iss-2610262032521502launch says the repo organises work by phase; the phase entry is superseded, sequencing being dependencies plus the lifecycle shelves
- iss-2610262032530356the version glossary's example has launch ship tag the repo; launch says the verb neither commits, tags nor publishes
- iss-2610262032536646launch lists the roadmap among the record's live documents; the roadmap entry says the status block replaces the roadmap document and the word
- iss-2610262032542009the lifeboat licence gate's allowlist is named .abcd/launch-allowlist.json; launch says that allowlist and release packaging are two mechanisms never given one name
- iss-2610262032545565the release glossary says a release is published via launch ship; launch says the verb publishes nothing
- iss-2610262032548523itd-10 lists a lifeboat among the .abcd/ contents destroy deletes; disembark always writes the lifeboat out-of-treerelated itd-10
- iss-2610262032556158itd-106 has abcd switch on auto-deletion of merged branches; ahoy says abcd only mirrors the repository's merge-hygiene settings and never sets themrelated itd-106
- iss-2610262032558851itd-81 names an embark-scaffolder agent; embark says no scaffolder and no model sit in its write pathrelated itd-81
- iss-2610262032561511itd-11 gives the lifeboat audit to a lifeboat-oracle; disembark's lifeboat review agent is lifeboat-reviewer, and no lifeboat-oracle appearsrelated itd-11
- iss-2610262032566420itd-5 applies its rule to a Pass A spine agent spec; disembark packs the spine in one deterministic run that dispatches no agentsrelated itd-5
- iss-2610262032572271itd-11 hardens an existing chat-distiller; disembark says the transcript-reading distiller is not built and waits on itd-11related itd-11
- iss-2610262032577014itd-12 has the principle distiller weigh .abcd/work/notes/, reviews and memory; disembark's agents read only packed lifeboat files, and the pack carries none of those sourcesrelated itd-12
- iss-2610262032578385itd-15 has every disembark of abcd-cli run an agent audit pass automatically; disembark's pack dispatches no agents, and synthesis runs only as later sub-verbsrelated itd-15
- iss-2610262032580449itd-37 extends principle-distiller into a curator that writes memory pages from specs when they complete; disembark says its lifeboat agents, principle-distiller among them, read the packed lifeboat's filesrelated itd-37
- iss-2610262032585048itd-26 calls the licence gate a launch gate; launch says the restrictive-licence gate is not the release artefact's gate, and that its consumer is the lifeboatrelated itd-26
- iss-2610262032595554itd-2609292107351737 has transcripts captured into the history store; ahoy says history/ is the registry only and holds no transcriptsrelated itd-2609292107351737
- iss-2610262032597891The lab discipline says a lifeboat's sections are intention, method, what worked, what is open, candidates and coverage; disembark takes a lifeboat's sections from the brief-section mappingrelated itd-2609251624540864
- iss-2610262033003041The glossary calls a phase the retired sequencing unit; launch says the repo organises its work by phase
- iss-2610262033006141The glossary keeps 'disposition' apart from 'fixed'; launch uses fixed, invalid and deferred as the dispositions of a release-gate finding
- iss-2610262033012386itd-83 puts a pointer to abcd's reviewer agents in the AGENTS.md conventions section that prepare-this-repo owns; the ahoy page says that block never mentions abcd, and the prepare page is retired.related itd-83
- iss-2610262033013099itd-85 wires a new abcd audit verb into prepare-this-repo's Phase 2 as the conformance report; the ahoy page already gives that phase to abcd lint's JSON form.related itd-85
- iss-2610262033019185itd-59 puts the transcript corpus at ~/.abcd.noindex/history/< root_sha>/; the ahoy page says history/ is the registry only and holds no transcripts.related itd-59
- iss-2610262033022683itd-91 adds a setup question that chooses an AI-acknowledgement convention; the ahoy page already has the install's attribution opt-in, a hook that asks each commit to declare assistance.related itd-91
- iss-2610262033027180itd-62 calls CI, pre-commit and runtime hooks 'the same three-tier model abcd uses elsewhere'; on the ahoy page, the three tiers are the .abcd/ record layout.related itd-62
- iss-2610262033030496itd-8 has a code-rescuer agent decide what code the pack copies; the disembark page says pack is one deterministic run that dispatches no agents.related itd-8
- iss-2610262033033258itd-90 relies on embark to write the product thinker's answers into the target; embark writes only its record families and never writes anything else from the lifeboat.related itd-90
- iss-2610262033041268itd-41 builds a negotiator over ordered phases with Expectation, Milestone and Phase Acceptance; the disembark page says sequence is dependencies plus the lifecycle shelves, and phases and milestones are retired.related itd-41
- iss-2610262033042911itd-35 writes its lifeboat report in the repository under .abcd/logbook/audit/; the embark page says lifeboat operations record at the operator level under ~/.abcd.noindex/voyage/, never committed.related itd-35
- iss-2610262033053387The announcements intent promises that nobody's session merges into a release being cut; the launch page says the release hold does not stop a merge armed or queued before the reservation.related itd-2609151838312703
- iss-2610262033055327The decision-adapter intent treats embark's lesson ranking as a judgement the host answers by default; the embark page ranks lessons by term overlap, with no judgement in that step.related itd-2609221009495079
- iss-2610262033059301The routing intent has the install render the proposal, a table with one row per agent, before consent; the ahoy page states the proposal in counts and names no agent.related itd-2609170822093401
- iss-2610262033062965itd-30 lets a user-facing intent carry a design fiction in place of a press release; the launch page composes the release page from the press releases of the user-facing intents shipped.related itd-30
- iss-2610262033066869The harness-version intent names a harness whose version cannot be read as not checked, never as current; the ahoy page's floor warning stays silent when it cannot read a version.related itd-2610031026190632
- iss-2610262033072029The embark chapter still calls the judgement over a lifeboat an 'oracle product audit'; itd-125 renamed it a review everywhererelated itd-125
- iss-2610262033075573itd-7 relies on disembark running dev-sync before the pack and writing a workspace file into the repo; the disembark chapter has no such step and never writes to the sourcerelated itd-7
- iss-2610262033081135itd-24 has the embark unpack show earlier retrospectives in the press-release interview; the embark chapter gives that job to the separate lessons sub-verbrelated itd-24
- iss-2610262033086503itd-24 says reflect reads a release's intents the way the cut does, but its shipped_in rule is not the one the launch chapter's cut appliesrelated itd-24
- iss-2610262033090287itd-146 puts a `changelog` verb in the agent help block; the launch chapter says the changelog verb is retired and refused as an unknown commandrelated itd-146
- iss-2610262033095338itd-122 says a shipped sub-verb with no table row fails the build; the launch chapter ships `smoke-pages` with no rowrelated itd-122
- iss-2610262033096678The launch chapter says the repo organises work by phase; itd-24 records that phases are retired and the release is the unitrelated itd-24
- iss-2610262033108186itd-147 says surface-chapter prose never states a flag; the launch chapter's prose names the `dry-run` flagrelated itd-147
- iss-2610262033109267The launch chapter's route receipt leaves an unreported model empty and has no served side; itd-166 says the receipt records both sides and gives a reason for every missing fieldrelated itd-166
- iss-2610262033114573itd-200 keeps the status line's user-level defaults under `~/.abcd/`; the ahoy chapter keeps `statusline.json` in `~/.abcd.noindex/`related itd-200
- iss-2610262033117994itd-117 puts the user-scope rules file at `~/.abcd/rules.json`; the ahoy chapter's user scope is `~/.abcd.noindex/`, and the file lives thererelated itd-117
- iss-2610262033124129itd-39 extends a Python prompt-router hook; the ahoy chapter says every hook event command is a shim that finds and runs the abcd binaryrelated itd-39
- iss-2610262033126804itd-39 names a 'workspace' memory scope; the ahoy chapter says abcd has no workspace layer, only the repository and the user scoperelated itd-39
- iss-2610262033133368itd-146 says the ahoy-installed marker block tells every managed repository to run `abcd rules`; the ahoy chapter says a default install writes that block into no conventions filerelated itd-146
- iss-2610262033133842itd-3 rejects a machine-wide rules.json outright, per-repo only; the ahoy chapter's home inventory has one as the user layer of the rulesrelated itd-3
- iss-2610262033139821itd-40 lists an in-tree .abcd/ directory as a strong managed marker; the ahoy chapter says it does not make a folder managed on its ownrelated itd-40
- iss-2610262033143329itd-3 puts the loader's marker block in CLAUDE.md; embark re-injects that same itd-3 block into AGENTS.md and treats claude_md as a retired targetrelated itd-3
- iss-2610262033144314itd-2609212130136102 retires `ahoy remote` as the old spelling of the remote report; the ahoy chapter still lists `abcd ahoy remote` as a shipped sub-verbrelated itd-2609212130136102
- iss-2610262033155666itd-36, closed as delivered, has the lifeboat licence gate refusing to surface kept originals; the launch chapter says that restrictive-licence gate is future and inertrelated itd-36
- 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 itd-2609231013154443
- iss-2610262033165546itd-2610030810350727 requires every question's label to say who it is for; the ahoy chapter chips setup questions "Setup Q< n>", naming the interview and no addresseerelated itd-2610030810350727
- iss-2610262033167999itd-2609211913453478 retires phase, milestone and roadmap; the launch chapter still says the repo organises work by phase (adr-9) and uses roadmap as a live recordrelated itd-2609211913453478
- iss-2610262033173969itd-67 has launch ship write plugin.json and tag the repo; 04-launch says the verb neither commits, tags nor publishesrelated itd-67
- iss-2610262033179679itd-67 keeps a `--version <x.y.z>` override on ship; 04-launch says there is no version flag at allrelated itd-67
- iss-2610262033180356itd-73 derives a major bump from any breaking intent; 04-launch says no set of records derives 1.0.0 from a 0.y.z baserelated itd-73
- iss-2610262033185478itd-67 has the catalog list the plugin with `source: "./"`; 04-launch has the cut replace the catalog's source with the pinned release archiverelated itd-67
- iss-2610262033189165itd-67 sends change-narration stripped from a doc into the changelog; 04-launch says rephrase the doc and never move the sentence into the changelogrelated itd-67
- iss-2610262033191807itd-88 names the packer `disembark <repo> to <dest>`; 02-disembark makes bare disembark a read-only listing and packing the `pack` sub-verbrelated itd-88
- iss-2610262033194284itd-69 says the version lives in both plugin.json locations plus marketplace.json; 04-launch says two locations are the whole of itrelated itd-69
- iss-2610262033202441itd-6 says abcd makes no direct LLM API calls, only RP over MCP; 01-ahoy has delegating verbs send steps straight to a configured providerrelated itd-6
- iss-2610262033205781itd-48 calls the lifeboat review agent `lifeboat-oracle`; 02-disembark calls it `lifeboat-reviewer`related itd-48
- iss-2610262033217382itd-89 files SessionEnd transcripts in the local per-repo store; 01-ahoy keeps the per-repo transcripts folder for opted-in checkouts onlyrelated itd-89
- iss-2610262033219255itd-6 has ahoy discover RP and lock `oracle.backend = "rp"`; 01-ahoy records host-delegated without asking, as the only answer with an adapterrelated itd-6
- iss-261026203322310705-intent defers the honoured/diverged/missing gap buckets, but 09-reflect reads gap counts from every ingested review.
- iss-2610262033224778itd-76 places the sources corpus at `~/.abcd/sources/`; 01-ahoy lists it under the user-scope home `~/.abcd.noindex/`related itd-76
- iss-261026203322851105-intent's cut rewrites every passed target_release to next, so 09-reflect's list of a cut release's unshipped targeted intents is always empty.
- iss-261026203323578205-intent keeps a re-run owed on an ingested review that left a check owed, but 08-abcd says an ingested review leaves nothing to do.
- iss-261026203323929105-intent gives ADR files as zero-padded NNNN-< slug>.md, but 24-decide mints adr-< yymmddHHMMSS>< rrrr> ids with stamp-named files.
- iss-261026203324146506-capture expects `abcd lint` to count a widening run's admitted, declined and held proposals, but 16-lint's rule set has no such check.
- iss-261026203324804105-intent names the phase plan as the canonical build order, but 08-abcd orders what gets built by build next's pick order.
- iss-261026203325082606-capture says the filing-time match runs on the ledger's two unattended writers, but 05-intent's audit ingest is a third writer that files through the match.
- iss-2610262033252259'Standing disposition' means a reading item's answer in 06-capture and a scope condition's current standing in 05-intent.
- iss-2610262033260091The intent chapter's audit-loop table never iterates on an INCONCLUSIVE verdict and never rolls it up as UNACHIEVABLE; the build chapter's fix loop fails the round on INCONCLUSIVE exactly as on NOT_MET.
- iss-261026203326020508-abcd says questions in a repository abcd does not manage are not gated, but 17-guard checks abcd's questions against the field limits whether the repository is managed or not.
- iss-261026203326286618-ideate says capture friction stays at one line, but 06-capture makes a capture one line of text plus one line of remedy.
- iss-2610262033270378'drain' names both the intent audit's owed-review queue and the top-level verb that works the issue ledger.
- iss-2610262033277086The build's landing runs the spec close as an automatic stage, but the close refuses without an impact judgement that no build check requires and no stage supplies.
- iss-2610262033286211Capture defines 'promoted' as the two-ended join between an issue and an intent; drain hands back as `promoted` any issue whose related_intents names an intent.
- iss-2610262033287288The library chapter says the `memory` command was merged into `library`; the memory chapter documents a live `/abcd:memory` verb for a different store.
- iss-2610262033292397The board restates the pick's candidate rule to choose its next-up head, but leaves out the pick's footprint exclusion.
- iss-2610262033299542The record page names closing the spec as a READY planned intent's next move; the build chapter makes READY the state from which an intent is built.
- iss-2610262033301184The board's Now row shows one lane and one awaited role per run; the implement chapter runs a run's lanes in parallel up to its ceiling.
- iss-2610262033306077Reflect's plain-Terminal interview treats a configured fallback host as a working route; the build chapter says the fallback-host path still waits on a decision.
- iss-2610262033311711The report chapter says the sources store is keyed by the full root-commit SHA; the library chapter names a repository's sources ledger by the first twelve hex digits of its root commit.
- iss-2610262033319993The intent chapter defers the honoured/diverged/missing prose audit, while the agent catalogue says the shipped fidelity role returns it.
- iss-2610262033322455The intent chapter ships a bounded drain for owed audits, while the configuration chapter says nothing drains today.
- iss-2610262033328180The intent chapter says the audit loop was re-scoped into the last stage of the build, while the configuration chapter still stages it as a per-intent mode.
- iss-2610262033335346The intent chapter runs the doc-fidelity gate on every close that ships an intent, while universal patterns calls that pass a draft that is not yet built.
- iss-2610262033340952The intent chapter's issue-drift form writes a report.json in the log tier, while universal patterns says the intent verb writes no report at all.
- iss-2610262033346897The intent chapter stages the fidelity audit's request under the local reviews directory, while universal patterns puts the same audit's output in a review sub-tier of the log tier.
- iss-2610262033354966The intent chapter reserves the word review for change-judgement, while universal patterns calls the audit and consistency sub-verbs review sub-verbs.
- iss-2610262033366548The capture chapter edits ledger records after they are filed, while universal patterns classes ledger entries as append-only and unchangeable once created.
- iss-2610262033372159The library chapter calls its distilled-pages half the memory store, while the surfaces register says the merge freed the name memory for the notes command.
- iss-2610262033374109The capture chapter keeps a scratch-to-ledger migration as owed design, while the configuration chapter says that migration has nothing left to migrate.
- iss-2610262033385114Exit code 3 means an absent corpus in the library chapter and contention in the land chapter.
- iss-2610262033399864The intent chapter has an armed record-lint rule that checks the promote back-link, while the lint contract lists that check as an unbuilt full-corpus tier.
- iss-2610262033404989The intent chapter describes numbered lint codes such as GL005, while the lint contract says rules are named, not numbered.
- iss-2610262033407239The intent chapter lists the armed record-lint rules and their severities by hand, while the lint contract says any literal list of rules belongs in a generated, gated region.
- iss-2610262033418681The intent chapter says itd-to-spc link drift warns and never blocks; the verification matrix says the same disagreement is a blocker that refuses to lint.
- iss-2610262033425782The intent chapter defers the honoured/diverged/missing prose review to a later spec; the verification matrix says the shipped auditor prompt already emits it.
- iss-2610262033433919The intent chapter says the quoted-text create seeds Why This Matters and Acceptance Criteria; the verification matrix says it also seeds Mechanism and Scope Conditions.
- iss-2610262033434648The out-of-scope page says itd-27 (the grill sub-verb) is scoped into the planned phases; the intent chapter says itd-27 is superseded by itd-94 and no grill sub-verb ships.
- iss-2610262033444397The out-of-scope page frames the brief as the work of eight planned phases; the reflect chapter says adr-2609212115255771 retired the phase.
- iss-2610262033451641The intent chapter names the phase plan under roadmap/phases/ as the canonical build order; the glossary marks phase superseded, with sequencing now dependencies plus the lifecycle shelves.
- iss-2610262033467091The glossary forbids 'corpus' as a synonym for the library; the library chapter calls the person's collection the 'sources corpus' throughout.
- iss-2610262033471150The memory substrate says abcd library's shipped surface is ingest, ask and lint and nothing else; the library chapter's generated appendix lists nine shipped sub-verbs.
- iss-2610262033478703'memory' names two things: the library's in-repo memory store, whose old memory command the library chapter says was merged away, and the glossary's memory note, written with /abcd:memory add and kept on the person's machine.
- iss-2610262033488570The memory substrate has principle-distiller route pages between a repo scope and a user scope; the library chapter says the curator role and user-scope memory are not built.
- iss-2610262033494841The memory substrate lists external_pdf pages as ingested through abcd library ingest; the library chapter says the binary rejects PDF sources.
- iss-2610262033500384The verification matrix says the lifeboat licence gate refuses to publish a kept original without an allowlist entry; the library chapter says that gate is not built.
- iss-2610262033503137The memory substrate says a failed coverage check refuses the next quotation block from that source; the library chapter says nothing enforces the budget at ingest.
- iss-2610262033514039The memory substrate has session_memory pages distilled via dev-sync memory; the board chapter says no dev-sync verb ships and no dev-sync code exists.
- iss-2610262033521157The reflect chapter uses 'voyage' for a project's lifetime ('every retrospective the voyage produced', 'the new voyage's store'); the glossary fixes voyage as the operator-level log of disembark and embark runs.
- iss-2610262033526755The board's six-section design reads a recent-logbook section; the build sequence says the logbook location is retired and a detector fails the build on any internal Go source that names it.
- iss-2610262033533504The board chapter calls admissions and surprises 'the issue ledger's two folderless families'; the glossary's one map of record families lists no such families.
- iss-2610262033534032The glossary says embark writes only the four record families; the reflect chapter says embark also writes retrospectives back, sealed with the other record families.
- iss-2610262033543354The glossary defines an intent as a press-release-shaped description of a feature; the intent chapter's discipline kind of intent skips the press release entirely.
- iss-2610262033548897The glossary defines a record as an itd, spc, adr, iss or rdg document; the record dispatcher treats dcn, adm, srp and rfm ids as records and gives rdg no dispatch.
- iss-2610262033556324The glossary says a spec is broken into ordered tasks with acceptance criteria; the intent chapter's spec stub carries Summary, Footprint and Steps sections and no criteria.
- iss-2610262033557020The intent chapter's kinds table maps a standalone intent to one spec (1:1); the record-families map says an intent has one or more specs.
- iss-2610262033559124The intent chapter makes the grill glossary-aware once a terminology/ directory exists; the glossary's home is .abcd/development/brief/glossary/.
- iss-2610262033567089itd-1 says plan's acceptance-criteria refusal is a record-lint hard block; the intent surface says it is the intent package's own check, not internal/core/lintrelated itd-1
- iss-2610262033569882The glossary allows bare 'the ledger' only for the issue ledger; the library chapter uses bare 'the ledger' for the sources ledger.
- iss-2610262033577968itd-84 calls the intent_sota gate unbuilt; the intent surface lists intent_sota as an armed record-lint rule at warnrelated itd-84
- iss-2610262033578037itd-190 makes a present-but-empty Mechanism section a readiness-gate fault; the intent template says a blank section passes the readiness gate with the nullity recordedrelated itd-190
- iss-2610262033586792itd-5 relies on intent-auditor's single-document role checking delivery against itd-5's own criteria; the audit refuses any record in disciplines/related itd-5
- iss-2610262033588599itd-81 requires judge agents, intent-auditor named first, to emit binary verdicts; the intent surface has intent-auditor emit four-valued per-criterion verdictsrelated itd-81
- iss-2610262033593092itd-192 decides a verdict by whether 'this phase' wires the producer; the intent surface says phases are retiredrelated itd-192
- iss-2610262033596296itd-196 keys its cumulative and closing rehearsals on the phase; the reflect surface says the phase was retired and the release is the grainrelated itd-196
- iss-2610262034005768itd-25 extends an 'intent-fidelity-reviewer'; the intent surface names the one agent that owns intent fidelity intent-auditorrelated itd-25
- iss-2610262034012499itd-25 grounds dredge's bare status+help in 'the universal convention'; the intent surface says bare-command-as-help is common, not universalrelated itd-25
- iss-2610262034017438itd-25 keys the intent side of an issue-to-intent link resolves_issues; the capture surface's promote join writes that side as related_issuesrelated itd-25
- iss-2610262034027543itd-16 writes the chain verification report under .abcd/logbook/audit/; the intent surface puts the chain sub-verb's receipts in the local ephemeral logs tierrelated itd-16
- iss-2610262034034042itd-21 has the scaffold's starter intent captured as itd-1; the intent create mints a timestamp-numeric idrelated itd-21
- iss-2610262034042710draft itd-165 promises that a failed fidelity verdict becomes visible work; the intent surface's audit ingest already files an issue for every failed or undecided checkrelated itd-165
- iss-2610262034045777draft itd-175 promises the product thinker writes down how an intent could be wrong; the readiness gate's grounds already record what would show the conjecture wrongrelated itd-175
- iss-2610262034051312draft itd-2609292108373494 hands over 'abcd's grill'; the intent surface says no grill sub-verb shipsrelated itd-2609292108373494
- iss-2610262034068157draft itd-143 says the brief gains a framing chapter whose position and filename are still to be fixed; the capture surface's reframe reads that chapter's Construal section as a committed surface at a fixed pathrelated itd-143
- iss-2610262034072525itd-2610141956319695 names a release-receipt finding's fixed/invalid/deferred state its 'disposition'; the capture surface's disposition is the researcher's record answering a reading itemrelated itd-2610141956319695
- iss-2610262034081102itd-2610141956319695 defines a deferral as capturing a finding as its own record; the capture surface's deferral is a waiver written onto an existing open record past one cutrelated itd-2610141956319695
- iss-2610262034081412the disposition glossary keeps disposition vocabulary apart from the issue ledger's wontfix; the capture surface records a wontfix under the token declined, a disposition state
- iss-2610262034090653itd-37 has principle-distiller, as itd-36's role-extended curator, extract each spec's Modification Grammar into memory pages at spec completion; the library surface says that curator role is not builtrelated itd-37
- iss-2610262034102286draft itd-126 names `abcd source ingest` for importing shared references into the corpus; the library surface retired `source` and keeps ingest for the memory store, which registers nothingrelated itd-126
- iss-2610262034111313draft itd-2609292108089653 calls registering a document into the sources corpus 'ingesting a source'; the library surface's ingest distils into the memory store and the corpus's add registersrelated itd-2609292108089653
- iss-2610262034120625itd-26 builds loot's refusing licence check on itd-36's shared substrate, launch licence gate included; the library surface says that gate is not built and ingest never refuses on a licencerelated itd-26
- iss-2610262034127412itd-26 names `/abcd:memory ingest` as the knowledge verb beside loot; the library surface merged `memory` into `library`related itd-26
- iss-2610262034130871draft itd-2610111655362931 uses 'memory' for notes agents write, with an `abcd memory promote` verb; the library surface's memory store is distilled source pages reached through libraryrelated itd-2610111655362931
- iss-2610262034143915itd-13's dev-sync keeps a last successful run timestamp shown by `abcd dev-sync status`; the board chapter says even in the dev-sync design no last-run timestamp is recordedrelated itd-13
- iss-2610262034151413itd-85 names `abcd audit` as the repository-conformance check; the intent chapter says the conformance check is `abcd lint` and reserves `/abcd:audit` for hash-chain checks.related itd-85
- iss-2610262034153896draft itd-169 promises a stopping agent loop says whom it is asking; the board chapter's badge already has the agent name whom it addresses at a stoprelated itd-169
- iss-2610262034164290itd-85 has `prepare-this-repo` read `abcd audit --json`; the board chapter says the install's preparation workflow runs `abcd lint` for its audit half.related itd-85
- iss-2610262034176558itd-83 puts its fallback pointer in an AGENTS.md section that `prepare-this-repo` owns; the board chapter says the `prepare-this-repo` page retired into the install.related itd-83
- iss-2610262034181775itd-44 says the planner's `_choose_candidate_kind` reads `suggested_kind`; the intent chapter says no shipped code reads that field and planning never consults it.related itd-44
- iss-2610262034182114itd-91 puts its setup question in `/abcd:init` / `prepare-this-repo`; the board chapter says the `prepare-this-repo` page retired into the install.related itd-91
- iss-2610262034191519itd-44 writes the diverted ADR as `adr-<next-free>-<slug>.md`; the intent chapter names the same ADR-store file `NNNN-<slug>.md`, zero-padded.related itd-44
- iss-2610262034207649itd-30 calls the promise-against-delivery agent `intent-fidelity-reviewer`; the intent chapter calls it `intent-auditor`.related itd-30
- iss-2610262034212278itd-30 builds on a `/abcd:intent new` interview; the intent chapter makes a leading quoted seed the canonical create and has no `new` sub-verb.related itd-30
- iss-2610262034220886itd-41 proposes ordered phases with Milestone and Phase Acceptance sections; the intent chapter says phases are retired.related itd-41
- iss-2610262034225527itd-78, still a draft, promises the `blocked_by` and `builds_on` edges; the intent chapter already ships them through the edge sub-verb with the same definitions.related itd-78
- iss-2610262034233163itd-57 proposes a sentinel spec that keeps planned work out of autonomous pickup; the board chapter says the build's start checks already skip a held record.related itd-57
- iss-2610262034242423itd-87 says capture matching covers only open entries and folds recurrences away; the capture chapter says the match already covers resolved issues and never drops a capture.related itd-87
- iss-2610262034255735itd-87 calls resolved and wontfixed issues 'dispositioned'; the capture chapter uses 'disposition' only for a researcher's answer to a reading item.related itd-87
- iss-2610262034261541The what-next menu makes opening the board change the status in a Terminal; the board chapter promises bare `abcd` is strictly read-only.related itd-2610031215002409
- iss-2610262034268156itd-86, still a draft, promises cold-reading detections that land as reading records; the capture chapter says the reading producer has shipped and owns that output contract.related itd-86
- iss-2610262034278916The announcements intent frees the word 'status' for `abcd status` by renaming the board; the board chapter still calls the bare board the Status Board.related itd-2609151838312703
- iss-2610262034286775itd-2610150602547271 shows the facilitator's mode (human or auto) on the board; the board chapter's mode is what `abcd mode` stores, the badge's state and the away mode.related itd-2610150602547271
- iss-2610262034293679itd-55 says abcd already stress-tests acceptance criteria with the grill; the intent chapter says no grill sub-verb ships.related itd-55
- iss-2610262034298178The memory-notes intent keeps agent notes in `.abcd/memory.json` under `/abcd:memory`; the library chapter's memory store is `.abcd/memory/` under `abcd library`.related itd-2610091918433290
- iss-2610262034302701itd-61 reuses the existing grill's interrogation machinery; the intent chapter says the grill sub-verb is an unshipped design target.related itd-61
- iss-2610262034312865itd-2609201916151817 attributes its quote to 'a technical facilitator'; the intent chapter says every press-release attribution is checked against the persona roster's names.related itd-2609201916151817
- iss-2610262034326107itd-2609221009495079 attributes its quote to 'a product thinker'; the intent chapter says every press-release attribution is checked against the persona roster's names.related itd-2609221009495079
- iss-2610262034333292The intent chapter keeps an UNACHIEVABLE intent in shipped/ and calls a drafts/ move a lifecycle break; itd-50 rules that unachievable reopens the intent to drafts.related itd-50
- iss-2610262034335136The intent chapter's loop treats INCONCLUSIVE as fail-closed with no iteration; itd-50 rules that an undecided criterion fails the round and reopens the work as NOT_MET does.related itd-50
- iss-2610262034345807The intent chapter records hand verification as a separate JSON verification receipt; itd-50 rules it is a grounds entry, not a separate receipt.related itd-50
- iss-2610262034354642The intent chapter names the Role 1 fidelity agent intent-auditor; itd-50 calls the same actor intent-fidelity-reviewer.related itd-50
- iss-2610262034360121itd-7 builds its workspace pull on dev-sync, a pre-pack step it says is already in the brief; the board chapter says no dev-sync verb or code exists anywhere.related itd-7
- iss-2610262034363298itd-7 has disembark write the RepoPrompt workspace into the repository; the board chapter says disembark is read-only and writes only to an operator-chosen destination.related itd-7
- iss-2610262034370169itd-39's hook queries a user-scope memory store at ~/.abcd.noindex/memory/; the library chapter lists user-scope memory outside the repo as not built.related itd-39
- iss-2610262034384038The library chapter says the memory command merged into library; itd-39 uses memory as the live name of the agents' notes command.related itd-39
- iss-2610262034397453itd-200 puts the user-level status-line defaults under ~/.abcd/; the library chapter names the user-level home ~/.abcd.noindex/.related itd-200
- iss-2610262034402021itd-201 says the itd-200 mode records which hat the human wears so it is not asked again; the board chapter says answering any abcd question resets the mode to managed.related itd-201
- iss-2610262034403157itd-117 puts the machine-wide rules layer at ~/.abcd/rules.json; the intent chapter puts the machine layer of layered configuration under ~/.abcd.noindex/.related itd-117
- iss-2610262034417109itd-122 says surface_coverage checks every surface file's sub-verb rows both ways; the board chapter says its table is compared with the command tree in neither direction.related itd-122
- iss-2610262034428117itd-179 says a capture triage without grounds is refused; the capture chapter says resolving records grounds only when given, their absence parked.related itd-179
- iss-2610262034431772itd-179 has intent ready refuse when grounds are absent; the intent chapter reports the readiness gate's grounds row as advisory, never withholding readiness.related itd-179
- iss-2610262034437300itd-177 has the readiness gate refuse an intent that leaves a context claim unrecorded; the intent chapter reports the claim rows as advisory, never withholding readiness.related itd-177
- iss-2610262034445775itd-2609020625405251 makes a condition's standing the latest block naming it; the intent chapter lets a reading-occasioned block stand over a later verdict that does not name its occasion.related itd-2609020625405251
- iss-2610262034450748The intent chapter says only the reading-ingest verb writes origin contributed-by-reading; itd-2609020625400169 has the capture promote path stamp it on the draft it mints.related itd-2609020625400169
- iss-2610262034461571itd-2609020625400169 has the reading-item promote link mode write promoted_from and promoted_to; the capture chapter calls those retired names that no reader tolerates.related itd-2609020625400169
- iss-2610262034468406itd-104 says abcd gates an idea and only a survivor graduates to a draft intent; the intent chapter calls ideate optional beside a create that drafts any quoted text.related itd-104
- iss-2610262034479574The intent chapter names the phase plan as the canonical build order; itd-24 records that phases are retired.related itd-24
- iss-2610262034489695itd-114's maintainer reads capture list newest-first; the capture chapter orders the list by derived priority, unblocked first and then by severity.related itd-114
- iss-2610262034492769itd-111 has abcd version show install mode and vintage; the board chapter says version is a retired name and the report is now a flag on the root.related itd-111
- iss-2610262034494554itd-138's install script finishes by running abcd version; the board chapter says version is a retired name answered with its replacement.related itd-138
- iss-2610262034508480The intent surface page names the roadmap phase plan as the canonical build order; itd-2609211913453478 retires phases and puts sequencing in dependencies and the lifecycle shelves.related itd-2609211913453478
- iss-2610262034513980itd-34 has the reclassify verb move a draft into disciplines/; the intent surface page says no reclassify writes a discipline and a move into disciplines/ is refused.related itd-34
- iss-2610262034520240itd-34 calls the three-role fidelity agent intent-fidelity-reviewer; the intent surface page calls the same agent intent-auditor.related itd-34
- iss-2610262034528274itd-34 links a bundle member to its shared spec through epic_id and an epic.intent list; the intent surface page links it through spec_id and the spec's intents list.related itd-34
- iss-2610262034535349itd-36 calls bare-command-as-render a universal discipline; the intent surface page says it is a common convention, not a universal one.related itd-36
- iss-2610262034543078itd-28 says no abcd verb files a dated review folder; the intent surface page has the consistency pass write a dated report under .abcd/work/reviews/.related itd-28
- iss-2610262034550860itd-4 has capture promote call intent new with the issue's body; the capture surface page says promotion mints the draft natively with a by-id pointer, not a copy.related itd-4
- iss-2610262034566586itd-4 names the issue ledger's spec-link field related_epics; the capture surface page's schema names it related_specs.related itd-4
- iss-2610262034567348itd-4's shipped scope migrates scratch issues through dev-sync; the capture surface page says that migration is not built and rides a dev-sync surface that is only a design target.related itd-4
- iss-2610262034572130The capture surface page counts a promoted inbox report among abcd's automatic filers; itd-2609221656361680 says nothing is filed until a person or a session acts and rules automatic filing out.related itd-2609221656361680
- iss-2610262034582374itd-2609212130146198 has the guard refuse a question while the mode reads managed; the board's surface page has the guard admit abcd's chipped question and set the state from it.related itd-2609212130146198
- iss-2610262034587290itd-36 says the lifeboat licence gate refuses to surface kept originals; the library surface page says that gate is not built and the ingest never refuses on a licence.related itd-36
- iss-2610262034598939itd-2610111707085098 says a hand-given session name is never replaced; the board's surface page replaces it in a fork once abcd has given that name to another session.related itd-2610111707085098
- iss-2610262035005988itd-28's press release lands spec-tied reviews in a store under .abcd/reviews/< spec-id>/; the board reads reviews as dated folders under .abcd/work/reviews/.related itd-28
- 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 itd-2609231013154443
- iss-2610262035028747itd-2609212103568351 lists every READY intent under Next; the board's surface page lists the pick's head under Now alone and never under Next.related itd-2609212103568351
- iss-2610262035030115The retrospective seed lists planned intents whose target_release names the cut release; itd-2609212103572513's cut has already moved every such target to next.related itd-2609212103572513
- iss-2610262035033556itd-48's press release says the shape role went live as a working verb; the intent chapter says itd-48 did not build the shape rolerelated itd-48
- iss-2610262035045702itd-48 puts consistency reports under .abcd/logbook/audit/; the intent chapter puts them on the reviews shelf under .abcd/work/reviews/related itd-48
- iss-2610262035056745itd-48 calls the three-role agent intent-fidelity-reviewer (agents/intent-fidelity-reviewer.md); the intent chapter calls the same agent intent-auditorrelated itd-48
- iss-2610262035065340itd-80 names the verdict-ingest verb abcd intent review ingest; the intent chapter's command tree names it abcd intent audit ingestrelated itd-80
- iss-2610262035071845itd-42's full grill loads the naming, scope and out-of-scope chapters as well as the invariants and principles; the intent chapter's pre-pass assembles four inputs and nothing elserelated itd-42
- iss-2610262035075414itd-42 is scoped as a capability of an existing /abcd:intent grill sub-verb; the intent chapter says no grill sub-verb shipsrelated itd-42
- iss-2610262035089991itd-46 calls bare-command-as-status a universal abcd convention; the intent chapter says it is a common convention, not a universal onerelated itd-46
- iss-2610262035091535itd-46 has promotion pass the issue text to the quoted-text create; the capture chapter has promotion mint a draft whose body is a by-id pointer, not a copyrelated itd-46
- iss-2610262035102052itd-53 calls the shipped-but-unreviewed listing a consistency gate; the intent chapter uses Consistency for the Role 2 cross-document passrelated itd-53
- iss-2610262035104777itd-53's press release has an opt-in drainer run owed reviews at loop ends, session edges and pre-commit or CI steps; the intent chapter says nothing starts the drain on its ownrelated itd-53
- iss-2610262035112905itd-53 says entries with no backend stay deferred; the intent chapter says such entries stay owedrelated itd-53
- iss-2610262035127167itd-94 says autonomous drain runs are held by the intent readiness gate; the intent chapter says the drain verb's lanes are issuesrelated itd-94
- iss-2610262035135419itd-76 puts the sources corpus at ~/.abcd/sources/ by default; the library chapter puts it at ~/.abcd.noindex/sourcesrelated itd-76
- iss-2610262035142666itd-67 picks the release bump tier from phase-completion detection; the intent chapter derives the version from each intent's impact judgementrelated itd-67
- iss-2610262035153070itd-67 keeps a hand-typed --version override for a release; the status-board chapter says the version is derived and never hand-authoredrelated itd-67
- iss-2610262035168556itd-73 derives the release version from the shipped intents alone; the capture chapter says a resolved issue's impact drives the derived version toorelated itd-73
- iss-2610262035169561itd-67 generates the changelog from git tags, commit and spec history and the launch report; the intent chapter says the cut composes only from terminal record foldersrelated itd-67
- iss-2610262035171024itd-6's scope makes RepoPrompt over MCP the preferred oracle transport ahead of a Codex CLI and the in-session agent; the status-board chapter says every delegated step runs through the harness unless a routing table is acceptedrelated itd-6
- iss-2610262035181369itd-43 rules its reviews rename moot because no reviews subsystem classifies reviews by kind; the status-board chapter describes a reviews reader whose rows carry a kind and a specrelated itd-43
- iss-2610262035195318The docs chapter has the spec close refuse without a saved docs review for HEAD, but the build chapter's unattended landing runs that close with no stage that records one
- iss-2610262035201511The reading chapter's ingest sends a position's input to a model provider, but the implement chapter rests its outage probe on abcd calling no model
- iss-2610262035213062The guard chapter describes agents abcd starts through its claude runner, but the implement chapter counts agents against the ceiling on the premise that abcd runs no agent
- iss-2610262035213176The scribe chapter says a reading receives no ledger, but the reading chapter hands the comparative position a prior widening run's ledger items
- iss-2610262035222673The lint chapter calls the outbound gate the only surface that judges harness-leak text before it is public, but the guard enforces a forge-text check on gh pr and gh issue text before it is posted
- iss-2610262035238503The identity chapter says bare abcd lint is the gate for positioning drift, but the lint chapter says no gate invokes bare abcd lint and the identity target runs in no gate
- iss-2610262035249588'The memory store' names a store whose ingest takes documents and web addresses in the history chapter, but the memory chapter's store takes notes on stdin and has no ingest
- iss-2610262035256103The history chapter keeps the history directory for ahoy's registry with no transcripts, but the build chapter calls the transcript store 'abcd's history store'
- iss-2610262035256968'Checked nothing' means a lint that exits 0 in the docs chapter and a refused check that must never exit 0 in the lint chapter
- iss-2610262035265656The docs chapter ships the itd-60 doc-fidelity gate, saving receipts keyed by commit; universal patterns calls the itd-60 pass a draft that is not yet built, keyed by input fingerprint.
- iss-2610262035274211The reading chapter derives a position's definition file from its name instead of looking it up; the agent catalogue says the locator finds the definition by its `position` frontmatter field.
- iss-2610262035280605The decide chapter says a decision record is never edited; the lifecycle taxonomy puts the decisions folder in the compounding-curated class, whose pages are modified, contradicted and deprecated.
- iss-2610262035294777The lint chapter runs its site and outbound targets as CI gates; the lint contract says record-lint and docs-lint are the whole of CI's lint coverage.
- iss-2610262035302318The docs chapter's lint walks its roots and prunes only git-ignored untracked paths; the lint contract says the tree gates read git-tracked bytes.
- iss-2610262035308321The lint chapter gives the record-lint engine two severities, `blocker|warn`; the lint contract gives the same engine three, `blocker`, `warn` and `info`.
- iss-2610262035312375The banlist chapter says this repository's docs-lint `names/` entries read `name_roots` that include `.abcd`; the lint contract limits docs-currency to `docs/` and the repo-root prose.
- iss-2610262035329500The lint chapter says the outbound gate is the fourth surface for its class and the only one that judges text before it is public; the configuration chapter has the shell guard refusing a posting gh pr/issue command over the same shapes.
- iss-2610262035332173The docs chapter says the release gate runs the docs-currency-reviewer; the agent catalogue says no verb starts that reviewer: the operator runs it and the gate only checks its receipt.
- iss-2610262035341739The history chapter says no shipped surface but `history` reads the transcript store; the adapters chapter gives disembark a transcript reader that reads the same corpus.
- iss-2610262035354961The mode chapter keeps the away record in `~/.abcd.noindex/away/<root-sha>/`; the configuration chapter's inventory of the user scope has no away store.
- iss-2610262035366440The update chapter's news sub-verb writes under `~/.abcd.noindex/after-update/`; the configuration chapter's inventory of the user scope has no after-update store.
- iss-2610262035367698The ideate chapter writes private verdicts under `~/.abcd.noindex/ideas/<root-sha>/`; the configuration chapter's inventory of the user scope has no ideas store.
- iss-2610262035378747The land chapter calls itd-97's auto/human merge toggle 'the facilitator mode'; the mode chapter uses `facilitator` as a value of `abcd mode`'s waiting-on state.
- iss-2610262035387982The lint chapter says its site target writes a render; universal patterns says lint and its targets are read-only renders and that `abcd lint` is documented as performing zero writes.
- iss-2610262035390841The guard chapter says the guard writes a created-branch record, the waiting-on mode and an open-question marker; universal patterns lists `guard` among the read-only renders.
- iss-2610262035399502The identity chapter's initialiser records the block and its pointer; universal patterns lists `identity` among the read-only renders.
- iss-2610262035409725The banlist chapter has write paths (add, remove, migrate); universal patterns lists `banlist` among the read-only renders.
- iss-2610262035412926The lint chapter says bare `abcd lint` runs when a human types it; the surfaces register lists `lint` with the agents, a block it reserves for commands no person types.
- iss-2610262035421014The guard chapter says a person or a script asks it about a command line; the surfaces register lists `guard` with the agents, a block it reserves for commands no person types.
- iss-2610262035432356The glossary says the reading chapter writes 'reading position' in full on first use; the chapter opens with bare 'position' and never writes the full phrase
- iss-2610262035439719The reading-position glossary entry says the comparative position does not assemble and refuses; the reading chapter says it assembles from a prior widening run
- iss-2610262035440979The glossary reserves bare 'surface' for a verb's front door and 'rendered surface' for identity-held text; the identity chapter uses bare 'surface' for identity-held text throughout
- iss-2610262035450179The glossary forbids bare 'the loop' for the agent loop; the mode chapter's title uses bare 'the Loop' for exactly that loop
- iss-2610262035462032The glossary allows bare 'the ledger' only for the issue ledger and spells the source-provenance store 'the sources ledger'; the guard chapter writes 'source-ledger' and then bare 'the ledger' for it
- iss-2610262035468845The glossary says abcd never owns the run loop; the site chapter reads the state file of abcd's own implement loop
- iss-2610262035476004The glossary lists 'corpus' as a forbidden synonym for the library; the banlist chapter calls the library 'the sources corpus'
- iss-2610262035484132The glossary puts outside documents and links in the library, not memory; the history chapter credits 'the memory store' with an ingest that takes documents and web addresses
- iss-2610262035497039The glossary says a record, an ADR included, carries no status field; the decide chapter mints ADRs with a `status: proposed` field the author later changes
- iss-2610262035505656The glossary defines a record by five id kinds and leaves out dcn-; the ideate chapter calls a decision a record cited by its dcn- id like any other
- iss-2610262035510145The voyage entry calls privacy-hygiene an 'audit rule' run by abcd's 'own audit'; the lint chapter says that verb is a lint and that 'audit' is reserved
- iss-2610262035514317The glossary says forbidden synonyms are registered there and nowhere else; the docs chapter registers the retired role word as a docs-lint banned token
- iss-2610262035524537The internals index says 'the `check` gates' ship; the lint chapter says the former check sub-verbs are unknown commands
- iss-2610262035538469The site internals page says `abcd site build` writes into `site/` and nowhere else; the site chapter names a write outside the output directory and an output directory the caller chooses
- iss-2610262035542834The site internals page puts a second-instance demonstration ahead of any repo-agnostic claim; the site chapter already ships site setup for any repository abcd manages
- iss-2610262035543059The out-of-scope list holds itd-85, 'A Read-Only Repo-Conformance Audit', as later-phase draft work; the lint chapter ships that read-only conformance verb and cites itd-85 as its intent
- iss-2610262035555270The out-of-scope list holds 'abcd Can Read Its Own Design Documents As A Stranger Would' as later-phase work; the reading chapter ships exactly that outside reading of the design
- iss-2610262035569535The brief index says spc-N references trace the predecessor implementation's spec store and are not delivery claims; the update chapter cites spc-32 as a closed spec in this repository's own store, paired with a shipped intent
- iss-2610262035572805The brief index says delivery state never lives in brief prose; every surface chapter records each verb's shipped or staged existence in its prose table
- iss-2610262035583798The verification matrix says an imported transcript merges by timestamp and content hash; the history chapter keys identity on content hash, session id and source labels, so the same content under another session is a new record
- iss-2610262035589664The verification matrix says an unreachable provider falls back to the harness rather than failing; the reading chapter's dispatch form exits 2 with nothing ingested when the provider cannot be reached
- iss-2610262035592770itd-140's armed-detector rung lives in `abcd site check`; 16-lint says the site verb's former check sub-verb is an unknown command.related itd-140
- iss-2610262036000485A draft filed for later wants every managed project to publish the public record site; 22-site already sets up and publishes that site for any managed repository.related itd-2610040754453237
- iss-2610262036018615The read-block glossary keeps every reading record of a prior run out of the next run; 23-reading hands the comparative reading a prior widening run's items.
- iss-261026203602430923-reading uses disposition for the researcher's recorded answer to a reading item; the deferred-finding discipline uses it for a review finding's fixed/invalid/deferred field in a release receipt.related itd-2610141956319695
- iss-2610262036027822The regime glossary says the supply-regime check validates at ingest what a reading may produce; 23-reading says the generative regime's constraint falls at admission, not ingest.
- iss-2610262036033754itd-142 names entailment as one of four question regimes; 23-reading makes entailment a position whose regime is explicative.related itd-142
- iss-2610262036040955itd-195 forbids an unexecuted list of which readers do what; 24-decide lists which readers call the ADR derivation and which carry their own, agreeing by inspection.related itd-195
- iss-2610262036053576itd-21's scaffold files the starter intent as `itd-1`; 24-decide says every minting family draws timestamp ids through one mint that reads no maximum.related itd-21
- iss-2610262036067608itd-16 makes /abcd:audit an open umbrella a schema or prompt-quality audit can join; 16-lint reserves it for hash-chain fidelity and calls a check of form a lint.related itd-16
- iss-2610262036068415itd-11 hardens a Pass B chat-distiller that reads the transcript store; 11-history says no shipped surface reads the store but history itself.related itd-11
- iss-2610262036076395The token-cost draft adds per-session token accounting at capture; 11-history already reports per-session token usage in reconstruct telemetry, with its own counting rule.related itd-2609292107351737
- iss-2610262036082275itd-134 renders a banner from the identity block's name, tagline and version; 19-identity's block holds a title, a tagline and an optional pitch, and no version.related itd-134
- iss-2610262036097307Draft itd-169 asks that a stopped agent loop say who it is asking; 26-mode already records whom the loop waits on in the badge's waiting-on state.related itd-169
- iss-2610262036101369itd-84 types a proposal's relation to existing records as supersedes/reverses/duplicates/refines; ideate's record grill types the same relation as covered/contradicted/superseded.related itd-84
- iss-2610262036101688The rewriter draft rests on abcd being unable to start an agent; 17-guard describes agents abcd starts through its claude runner.related itd-2610100627454580
- iss-2610262036113224The history chapter puts the transcript corpus under ~/.abcd.noindex/transcripts/ and keeps ~/.abcd.noindex/history/ for ahoy's registry, holding no transcripts; itd-59 places the corpus at ~/.abcd.noindex/history/< root_sha>/.related itd-59
- iss-2610262036129928itd-59 claims, as missing work, the capture of autonomous-run transcripts into the corpus; the history chapter says abcd build's delegated agent transcripts already reach the store through capture.related itd-59
- iss-2610262036131057The history chapter's 'memory store' is the store whose ingest takes documents and web addresses; itd-2610091918433290 says the name memory was freed into library, and gives /abcd:memory to agents' memory notes.related itd-2610091918433290
- iss-2610262036142715The lint chapter reserves /abcd:audit for itd-16's hash-chain fidelity surface and calls the conformance check abcd lint; itd-85, the intent the chapter cites, ships that same check as abcd audit.related itd-85
- iss-2610262036146367itd-86 defines the cold reading as one target document read against its own constraints; the reading chapter's detection position reads the shipped tree against the claim record, assembled at a commit from an include table.related itd-86
- iss-2610262036157324itd-87 treats matching captures against dispositioned entries, not only open ones, as new work; the reading chapter says capture's filing-time match already compares with open and resolved issues.related itd-87
- iss-2610262036163231itd-2609170822093401's press release says the oracle choice is one repo-wide value that nothing reads; the reading chapter has the ingest resolve that intent's model-tier route before anything runs.related itd-2609170822093401
- iss-2610262036171679itd-44 has capture write an ADR as adr-< next-free>-< slug>.md; the decide chapter mints ADR ids from a timestamp that reads no maximum, and names the file < stamp>-< slug>.md.related itd-44
- iss-2610262036186092The decide chapter makes abcd decide with the ADR flag the ADR store's minting verb, with embark counting only as a restore; itd-44 adds capture as a second path that writes new ADRs into the store.related itd-44
- iss-2610262036193171The site chapter's setup takes any managed repository's site live and gives every repository the same pages; itd-2610032150577708 rules that the record site is promised for abcd's own record only.related itd-2610032150577708
- iss-2610262036193721The site chapter's setup publishes a managed repository's site through a hosting provider adapter on a custom domain; itd-2610091010348892 publishes the same per-release record on the project's own GitHub Pages, with abcd running nothing.related itd-2610091010348892
- iss-2610262036208370The site chapter's 'status page' renders the board's Now/Next/Later block; itd-2609151838312703 renames the board so that the word status is free for abcd status, the view of announcements and reservations.related itd-2609151838312703
- iss-2610262036211949In the mode chapter, mode means the waiting-on badge (managed, facilitator, product-thinker) and the away mode set by abcd mode autonomous; itd-2610150602547271 adds 'the facilitator's mode', facilitator.mode human|auto, shown on the same board.related itd-2610150602547271
- iss-2610262036224651itd-2610170638184486 lets the person set away open-ended, ending only when they say they are back; the mode chapter caps every away record at seven days.related itd-2610170638184486
- iss-2610262036232872The guard's question gate assumes only abcd mode and the gate itself set a mode that names somebody; itd-2610031215002409 has bare abcd's Terminal menu set that waiting-on state too.related itd-2610031215002409
- iss-2610262036243501itd-185 has reading ingest check prose that ranks, settles or proposes; the reading chapter says that prose-signature layer was removed and only fields are refusedrelated itd-185
- iss-2610262036257320itd-185 says every refused run writes a refusal record; the reading chapter says refusals made before the run's identity is proven, a hash disagreement among them, leave nonerelated itd-185
- iss-2610262036260273itd-199 lets a reading's scope be widened or narrowed at invocation and records the override; the reading chapter says the invocation is a position and a target with no override and nothing to stamprelated itd-199
- iss-2610262036267743itd-199 has the comparative position refuse because it has no channel; the reading chapter has it derive its candidate set from a committed widening runrelated itd-199
- iss-2610262036279746itd-198 says the assembler states no size figure of its own; the reading chapter has every assembly report against a standing size targetrelated itd-198
- iss-2610262036286227itd-166 says a field a route cannot show is recorded as unpinned or self-reported, never left out; the reading chapter's route receipt leaves model_reported empty when the payload names no modelrelated itd-166
- iss-2610262036293167itd-2609020625407419's press release has the comparative assembly refuse when the widening run returned fewer than two configurations; the reading chapter has it stage an empty comparative runrelated itd-2609020625407419
- iss-2610262036303950itd-104 says an idea is gated before it can mint any record; the ideate chapter says ideate is optional, never a gate, and required by no other verbrelated itd-104
- iss-2610262036304277itd-201 uses the itd-200 mode to remember which role the person holds across questions; the guard chapter resets that mode to managed when each question is answeredrelated itd-201
- iss-2610262036312405itd-104 says every ideate run outputs a verdict and a recorded decision; the ideate chapter writes no decision for a private verdictrelated itd-104
- iss-2610262036322416itd-101 says the offline lint enforces no stale citation entries alongside no broken ones; the docs chapter says staleness only warns and never blocks an ordinary commitrelated itd-101
- iss-2610262036330589itd-102 calls the positioning check part of every audit; the identity chapter runs it as a rule of abcd lintrelated itd-102
- iss-2610262036341317itd-200 puts the status-line defaults in the user-level home under ~/.abcd/; the history chapter calls ~/.abcd a legacy locationrelated itd-200
- iss-2610262036343040itd-117 puts the user-scope rules file under ~/.abcd/; the history chapter calls ~/.abcd a legacy locationrelated itd-117
- iss-2610262036353820itd-130 names the staleness check abcd version --check; the update chapter makes the check a flag of abcd updaterelated itd-130
- iss-2610262036368072itd-147 says a chapter's prose above the generated appendix never states a flag or sub-verb; the docs chapter's prose states which of its verbs take the configuration and rootrelated itd-147
- iss-2610262036376225itd-122 says surface_coverage checks every sub-verb row against the command tree; the lint chapter's table note says a row's bucket cell is not checked against the treerelated itd-122
- iss-2610262036376499The badge intent refuses a question to the human while the mode reads managed; the guard chapter says abcd's question is never refused on the mode.related itd-2609212130146198
- iss-2610262036380647The question-layout intent refuses every question that breaks the asking rules; the guard admits a question whose only fault is going over the rows limit.related itd-2610030810350727
- iss-2610262036392981The reconstruction intent says reconstruction makes no write to the store; the history chapter says every history verb's resolve seam creates the store chain and moves a legacy corpus.related itd-2609091718595846
- iss-2610262036404974The verb-consolidation intent makes bare `abcd lint` run all targets; the lint chapter keeps the outbound target out of the bare run.related itd-2609212130136102
- iss-2610262036415345The site-setup intent says a result followed by the error envelope is the repository-wide JSON convention; the update chapter emits a refusal as a single document.related itd-2609061543533170
- iss-2610262036424620The folder-classification intent calls ahoy's registry of managed repositories "the history store"; in the history chapter that store is the transcript store, kept apart from the registry.related itd-40
- iss-2610262036429463The decision-log intent has the site list every decision from `.abcd/work/decisions/`; the site chapter says its one working-tier input is the issue ledger, off by default.related itd-2609151138388536
- iss-2610262036437864The rules-loader intent rejects a user-level rules.json and keeps rules per repository; the guard chapter counts a rules.json in abcd's home folder as part of the user layer.related itd-3
- iss-2610262036446593The conventions-file intent removes the CLAUDE.md and GEMINI.md links; the docs chapter still justifies its root-symlink rule by the bridge files it lets pass.related itd-2610030814013772
- iss-2610262036453716The menu intent hides the guard as a command only agents run; the guard chapter says a person or a script asks the guard about a command line.related itd-2610090831227812
- iss-2610262036460690The menu intent puts lint among the commands no person types; the lint chapter says bare lint runs when a human types it.related itd-2610090831227812
- iss-2610262036461110itd-89 files session transcripts in a local per-repo store; the history chapter says the store is user-level and the per-repo location is only an opt-inrelated itd-89
- iss-2610262036474703itd-76 puts abcd's user-level home at ~/.abcd/; the history chapter treats ~/.abcd as a legacy locationrelated itd-76
- iss-2610262036483439itd-60 names the shipped docs-currency lint `abcd docs lint`; the lint chapter says the docs verb's former check sub-verb is an unknown commandrelated itd-60
- iss-2610262036495984itd-60 says the gate writes its drafted brief edit into the shipping change itself; the docs chapter says the gate only proposes the edit and still refusesrelated itd-60
- iss-2610262036509587itd-65 calls its change-narration detector the `doc_fidelity` surface; the docs chapter uses doc-fidelity for the gate that checks the brief against the shipped surfacerelated itd-65
- iss-2610262036512603itd-93 says abcd's release workflows are generated from the one scaffold template, so abcd runs exactly what a managed repo gets; the docs chapter says abcd's release workflow has a docs-currency step that the scaffolded template never namesrelated itd-93
- iss-2610262036514870itd-6 says abcd never spawns Claude Code subprocesses; the guard chapter describes agents that abcd starts through its claude runnerrelated itd-6
- iss-2610262036529540itd-6 rules out direct provider integrations and sends everything through RP; the reading chapter routes a cold-reading position straight to a configured provider through abcd's own tier routingrelated itd-6
- iss-2610262036532725The surfaces register lists drain among the verbs no person types, while the drain chapter calls it the verb a person types
- iss-2610262036545848'Memory verbs' names the library's curation of `.abcd/memory/`, while `/abcd:memory` is a separate verb over memory notes
- iss-2610262036554739The build chapter refuses any key under `pace` the loop does not read, while the drain reads two more keys from that namespace
- iss-2610262036565450Multi-agent claims live in-tree under `.abcd/coordination/` per the universal patterns, but in the machine-scoped run store per the implement chapter
- iss-2610262036569134The configuration chapter counts two limits in load-limits, while the implement chapter names three keys in that file
- iss-2610262036573008The lifecycle taxonomy calls issue-ledger entries immutable after creation, while the drain's user-visible route writes `related_intents` into the issue
- iss-2610262036589915The register says chapters point to its bare-invocation list instead of restating it, but the announce chapter restates its bare behaviour
- iss-2610262036597501The user-scope inventory has no dashboard store, while the dashboard chapter keeps its run file and devices list in `~/.abcd.noindex/dashboard/`
- iss-2610262037002531The agent register says intent-auditor serves `intent` alone, while the build loop composes its request and validates its verdict
- iss-2610262037016704The memory internals chapter homes keyword-recalled personal and project memory in ~/.abcd.noindex/memory/ and .abcd/memory/; the memory verb homes the same in two memory.json layers.
- iss-2610262037018200The loop glossary says abcd never owns the run loop; the build chapter ships abcd's own implement loop.
- iss-2610262037021391The step glossary says the build loop takes a spec's steps one lane at a time; the build chapter runs lanes in parallel up to a ceiling.
- iss-2610262037031364The spec glossary says a spec is broken into ordered tasks; the build chapter breaks a spec into steps.
- iss-2610262037049481The out-of-scope page says the spec close that ships an intent is a manual step; the build loop's landing runs the close itself.
- iss-2610262037059425The build sequence says the dependency graph and the sequencing over it are a design target; the build loop sequences a spec's steps by their declared needs.
- iss-2610262037066238The brief index says spc references trace the predecessor's spec store and are not delivery claims; the build chapter cites a spec of this repository for what has landed.
- iss-2610262037067804The brief glossary says a project has exactly one brief; the build chapter gives every lane a brief of its own.
- iss-2610262037072482The record-families page says batch is not a term of the record; the implement chapter makes batch a named window mode.
- iss-2610262037080548The record-families page names status as a computed Now / Next / Later view; the announce chapter names a stored per-person branch of announcements status.
- iss-2610262037095269The record-families page lists the record families as intent, spec, step, bundle, issue, release and status; the inbox chapter calls adr, itd, iss, spc and dcn the record families.
- iss-2610262037099879The plan glossary keeps bare "plan" for the intent sign-off verb; the drain chapter uses bare "the plan" for a drain move's ordering of the ledger.
- iss-2610262037101841The loop glossary keeps bare "the loop" for the record loop; the build chapter uses it bare for its run iteration.
- iss-2610262037119222The only glossary entry for session is the unshipped grill exchange, which it says not to use generically; the implement chapter's session is a host agent session.
- iss-2610262037128325The release glossary accepts snapshot as an alias for a release; the lab chapter defines a snapshot as a standalone clone pinned at one commit.
- iss-2610262037133461The lab discipline lets no candidate into a harvest before a refutation pass; the lab verb's harvest lists candidates nobody tried to refute and only flags them.related itd-2609251624540864
- iss-2610262037138873itd-1 says a shipped intent's Audit Notes come only from an audit run by hand, because the automatic audit at ship time is deferred; the build loop already runs that audit and ingests it when the intent ships.related itd-1
- iss-2610262037142878itd-1 says reviews of implementations return SHIP / NEEDS_WORK / MAJOR_RETHINK; the build's implementation reviewers return SHIP or FIX FIRST.related itd-1
- iss-2610262037151611itd-190 says the readiness gate enforces the claim-recording rules; 34-build says the readiness gate only reports them as advisory and enforcement happens at a run.related itd-190
- iss-2610262037160502itd-191 allows selection only on its declared criteria, with the final choice made by the maintainer; the build pick chooses an intent itself on three computed scores and records that as a pursued: grounds entry.related itd-191
- iss-2610262037171531itd-2609292107351737 treats refusing to start a run on a budget as abandoned ground from a superseded intent; the build ships a budget check that refuses a run whose estimate is over quota.related itd-2609292107351737
- iss-2610262037186224itd-107 keeps forge calls (arming auto-merge, re-reading created items) out of the binary so it needs no forge command-line tool; the build loop's binary already makes those calls through gh.related itd-107
- iss-2610262037198530The bump re-authoring workflow stamps a commit message a machine wrote with Assisted-by: None; 34-build treats None as meaning human-only, which is false for machine-written text.related itd-2609301020001595
- iss-2610262037208650itd-2610070550516046 requires the pick's intent to be reconciled with it before either is built; the pick is already built and shipped as build next.related itd-2610070550516046
- iss-2610262037211310itd-19's per-stage defaults set the oracle to in-session, rp or rp+codex; the oracle.review key accepts only host or rp.related itd-19
- iss-2610262037219105itd-2609091416304128 treats 'the default branch' as refs/remotes/origin/main; 34-build defines it as origin's HEAD, falling back to main, master, trunk, then develop.related itd-2609091416304128
- iss-2610262037227384itd-25 calls an intent's back-link to its issues resolves_issues; 35-drain reads that same back-link as related_issues.related itd-25
- iss-2610262037238195itd-26 names /abcd:memory ingest as a user-facing verb for taking in knowledge; in 37-memory, /abcd:memory is an agents' command whose only sub-verbs are add, list and remove.related itd-26
- iss-2610262037246775itd-37 has an agent (principle-distiller) write memory pages into the repository's .abcd/memory/; 37-memory says agents write only the machine layer.related itd-37
- iss-2610262037255566itd-57 says nothing holds a planned item back from autonomous pickup today; the build brief's hold check already refuses any record carrying held:related itd-57
- iss-2610262037257443itd-2610170634394993 calls the hold on the shared remote a claim; in 27-implement, a claim is the run-state lock on this machine that keeps sessions apart.related itd-2610170634394993
- iss-2610262037262122itd-59 says the autonomous worker leaves only an ephemeral, pruned log; the build brief says a runner's transcript lands in the history storerelated itd-59
- iss-2610262037274982The sessions-announce intent promises every session's merge waits out a release cut; the reserve brief says merges armed before the hold still landrelated itd-2609151838312703
- iss-2610262037281449The sessions-announce intent plans to rename the status board (bare abcd) to the dashboard; the dashboard brief already uses that name for the Tailscale web serverrelated itd-2609151838312703
- iss-2610262037293150The worktree-store intent calls a pruned worktree's archived local tier its notes and keeps it under ~/.abcd.noindex/notes/; the memory brief's notes are the memory notes in memory.jsonrelated itd-2609091014076309
- iss-2610262037294601The build intent arms auto-merge wherever a queue gates the default branch; the build brief arms it only when a ruleset also requires a person's approvalrelated itd-2609201916151817
- iss-2610262037301480The build intent says each invocation does one step; the build brief keeps 'step' for a spec's steps and calls one invocation's work a stagerelated itd-2609201916151817
- iss-2610262037311796The build intent puts an issue lane's hand-back in the lane report; the drain brief puts handback in the receiptrelated itd-2609201916151817
- iss-2610262037323830The build brief says the no-host runner.fallback_host path waits on the ADR owed by the build intent's decision 6; the drive draft records the same reversal in an ADR of its ownrelated itd-2610222215485265
- iss-2610262037334466itd-44 files ADRs as adr-< next-free>-< slug>.md; the drain brief cites the store's ADRs as < timestamp id>-< slug>.mdrelated itd-44
- iss-2610262037339788itd-30 calls the fidelity auditor intent-fidelity-reviewer; the build brief calls that validator intent-auditorrelated itd-30
- iss-2610262037348735The decision-adapter intent needs lab harvest to report agreement rates with probability bands; the lab brief's harvest only assembles prose sections from findings and probe recordsrelated itd-2609221009495079
- iss-2610262037357893itd-86's cold reading takes exactly one target document; the implement brief says a cold reading is handed the union of every position's pathsrelated itd-86
- iss-2610262037365749The model-tier intent says nothing reads the oracle setting and every delegated step goes where the harness picks; the build brief reads oracle.review to route a lane's reviewsrelated itd-2609170822093401
- iss-2610262037372402itd-91 has every commit trailer follow the project's chosen AI-credit convention; the announce brief requires an announcement's Assisted-by to be abcd's own label and nothing elserelated itd-91
- iss-2610262037376558The cloud-session intent admits work-in-progress branches without a receipt as an entry in the reservation build's list; the reserve brief admits receipt-less pushes only when every commit has the empty treerelated itd-2610120738075547
- iss-2610262037387137itd-82 says a record filed before the remedy rule has no remedy and is ineligible; 35-drain reads such a record's legacy suggested_fix as its remedyrelated itd-82
- iss-2610262037392162itd-82 declares the drain order ends oldest first; 35-drain orders each group by a rendezvous hash on origin, with file paths ahead of directoriesrelated itd-82
- iss-2610262037409579itd-82's --max caps issues attempted and names --until-empty as the drain default's flag; 35-drain's cap counts lanes opened, and the drain has no --until-emptyrelated itd-82
- iss-261026203741032827-implement says the model service can only be probed through a canary agent because abcd calls no model; itd-166 records every model call abcd makesrelated itd-166
- iss-261026203741305635-drain counts spend only in agent runs because no runner reports tokens or money; itd-166 has every route record token counts and costrelated itd-166
- iss-2610262037423257itd-177 says the readiness gate refuses an intent with an unrecorded context claim; 34-build says the readiness gate only reports scope conditions and the mechanism prompt as advisoryrelated itd-177
- iss-2610262037438474itd-50 calls the fidelity verdict's agent intent-fidelity-reviewer; 34-build names the same validator intent-auditorrelated itd-50
- iss-2610262037443119itd-50 describes the implementation-grain fix loop as SHIP/NEEDS_WORK; 34-build's validators return SHIP or FIX FIRST, and APPROVE, BLOCK or NEEDS-INPUTrelated itd-50
- iss-2610262037453214itd-146 groups memory with the person's records verbs in help; 37-memory says help lists the memory verb with the agentsrelated itd-146
- iss-2610262037458871itd-117 puts the user-scope rules layer at ~/.abcd/rules.json; 30-inbox says the rules loader reads ~/.abcd.noindex/rules.jsonrelated itd-117
- iss-2610262037469144itd-200 places the user-level defaults under ~/.abcd/; 34-build reads the machine layer from ~/.abcd.noindex/config.jsonrelated itd-200
- iss-2610262037477814itd-147 rules that a surface chapter's hand-written prose never states a sub-verb; 27-implement states its sub-verbs above the generated appendix in a table and in proserelated itd-147
- iss-2610262037482641The pacing intent's bundled default has a 300-minute pause; the build chapter's bundled default has no pause.related itd-2609201925079472
- iss-2610262037492393The shipped runner intent has a no-host fallback to an operator-configured host in scope; the build chapter says a host session always drives and the no-host path waits on an ADR.related itd-2609201916056194
- iss-2610262037500468The spec-steps intent has `implement step` and the spec's steps share one word; the build chapter says steps and stages are two words for two things.related itd-2609212103565953
- iss-2610262037509765The spec-steps intent starts each step's lane only after the previous step merged; the build chapter opens a lane once the steps its needs line names have landed, so lanes can run side by side.related itd-2609212103565953
- iss-2610262037516372The reservation intent refuses any remote layout without origin; the build chapter reserves nothing in such a checkout and none of its checks refuses the run.related itd-2609091034175565
- iss-2610262037525523The stuck-lane intent sends a conflict on generated files back to the implementer as a fix round; the build chapter says a sync counts no fix round.related itd-2610161016391855
- iss-2610262037533417itd-34 names the fidelity-auditing agent intent-fidelity-reviewer and gives it a third role; the build chapter names the same agent intent-auditor.related itd-34
- iss-2610262037542283The load-check intent defines a stray as a process outside abcd's lanes at near full CPU; the implement chapter defines it by a share of the process's fair share, a 0.4-core loop included, with nothing exempt by name.related itd-2609231434459890
- iss-2610262037548530The load-check intent says the check never refuses and never waits; the implement chapter's load check, with its wait flag, holds make preflight's test stages until the load falls.related itd-2609231434459890
- iss-2610262037558450The load-check intent keeps the per-machine limits under ~/.abcd/; the implement chapter keeps them at ~/.abcd.noindex/load-limits.related itd-2609231434459890
- iss-2610262037561390The reservation intent's land fence renews for the merge queue's timeout plus a margin where a mirror exists; the implement chapter renews it for a day, with a mirror or without one.related itd-2609091034175565
- iss-2610262037571084The report intent files reports into ~/.abcd/inbox/; the report chapter files them into ~/.abcd.noindex/inbox/.related itd-2609221656361680
- iss-2610262037582823The build-next intent says --max and --until-empty are flags that next and drain share; the drain chapter's run ends at its cap and its shipped surface has no --until-empty.related itd-2609211116005482
- iss-2610262037591851The several-accounts intent asks the fork question once per process at a drain's start; the reserve chapter asks it at each drain lane's reservation, not at the start, and asks a failed question again after a minute.related itd-2610161016394967
- iss-2610262037594127The menu intent keeps drain on the agents' list until itd-82 ships; the drain chapter calls drain the verb a person types, with itd-82 still open.related itd-2610090831227812
- iss-2610262038000309itd-36 ships /abcd:memory as the ingest, ask and lint knowledge substrate under .abcd/memory/; the memory chapter's /abcd:memory keeps agents' memory notes with add, list and remove.related itd-36
- iss-2610262038011053The rules-loader intent rejects a machine-wide rules.json; the memory chapter reads a machine memory.json beside a machine rules.json layer.related itd-3
- iss-2610262038029972The glossary intent makes status the Now / Next / Later record family; the announce chapter's abcd status is the reader of announcements.related itd-2609211913453478
- iss-2610262038033829itd-6 selects the reviewer route with `oracle.backend` (rp, codex, in-session); 34-build selects it with `oracle.review` (host, rp)related itd-6
- iss-2610262038043808itd-6 falls an unreachable RepoPrompt through Codex and then an in-session subagent; 34-build falls a review the rp route does not return straight back to the hostrelated itd-6
- iss-2610262038051992itd-94 says autonomous drain runs inherit the implement-readiness gate, exit 1 a journaled SKIP; 35-drain's lanes are issue runs checked only by the drain rule and the peers checkrelated itd-94
- iss-2610262038052818itd-6 says abcd never spawns Claude Code subprocesses; 35-drain has the drain move start the claude runner for the drain judge itselfrelated itd-6
- iss-2610262038066422itd-67 has `/abcd:launch ship` tag the repo; 37-reserve has the release workflow push the release tag after the mergerelated itd-67
- iss-2610262038074426itd-89 files SessionEnd transcripts in the local per-repo store; 31-lab says the transcript store is machine-scoped and keyed on the root commitrelated itd-89
- iss-2610262038084949itd-76 puts the sources corpus under `~/.abcd/sources/`, abcd's user-level home; 29-report puts the sources store beside the inbox in the machine-scoped storerelated itd-76
- iss-2610262038097833itd-60 makes `abcd spec close` refuse while the brief lags, failing closed without a reviewer; 34-build's closing lane runs the spec's close with no doc-fidelity review among its stagesrelated itd-60
- iss-2610262038102197The configuration chapter says install asks about the oracle backend; the agent catalog says install records it without asking.
- iss-2610262038106941itd-80 names the Role 1 fidelity agent `intent-fidelity-reviewer`; 34-build gives the same closing-lane fidelity audit to `intent-auditor`related itd-80
- iss-2610262038113742The adapters chapter says `<seam>.backend` selects each seam's backend, oracle included; the agent catalog says `oracle.backend` routes nothing.
- iss-2610262038129584Universal patterns say an explicit `<seam>.backend` value selects a wired backend for history, spec, run and scanner; the configuration chapter lists those selectors as staged keys no code reads.
- iss-2610262038139122The surfaces register counts six hidden hook entrypoints; the configuration chapter wires two more, `hook stop` and `hook stop-failure`.
- iss-2610262038146233The configuration chapter has the STATUS block show each item once, newest first; the status chapter shows them in a fixed order, sums up the doubts and keeps only the newest announcement per item.
- iss-2610262038154778The configuration chapter has the binary read a prompt-counting refresh backstop; the verification matrix says nothing counts prompts.
- iss-2610262038166170Owed-review draining is described twice: staged run-seam gating that drains nothing today, and a shipped `intent audit --owed` that drains the owed set.
- iss-2610262038174723The lint contract says `documentation-auditor` audits it on every disembark; the agent catalog lists that agent in the design roster, none of which exists.
- iss-2610262038176813Universal patterns lean on a lint code reserved in the lint contract; the lint contract keeps no numbered code catalogue.
- iss-2610262038188161Universal patterns call `capture`, `intent` and `spec` read-only renders; the verification matrix has `abcd capture` write an issue into the ledger.
- iss-2610262038197762Universal patterns say the log tier and the voyage store are both tracked under the visibility rule; the voyage entry says the voyage is never committed.
- iss-2610262038201302The internals index says every agent has declared JSON inputs and outputs; the agent catalog says four agents declare no JSON contract.
- iss-2610262038210994The internals index says the config chapter covers seam-backend and adapter-registry config; the config chapter says there is no adapters registry block and the backend selectors are staged.
- iss-2610262038222403The brief index says spc-N references trace a predecessor implementation's spec store; the status chapter cites spc-2610150728396006 as this repository's design record, by step.
- iss-2610262038235036The brief index says delivery state never lives in brief prose; the surfaces register says 06-delivery, a brief chapter, carries it in detail.
- iss-2610262038247394The surfaces register keeps grill as a live design target to become an `intent` sub-verb; the build sequence says itd-94's planning interview supersedes it.
- iss-2610262038254260"status" names the Now / Next / Later record family and also the `/abcd:status` view of announcements on the shared remote.
- iss-2610262038256056The voyage entry has the voyage record every disembark and embark run; the configuration chapter says only disembark runs are logged and the embark side is staged.
- iss-2610262038269520The glossary says that in the build loop "step" names only a spec's piece; the agent catalog calls part of a lane's validate stage the implement loop's audit step.
- iss-2610262038278710The glossary defines a step as a landable piece of a spec; the land chapter uses "step" for its own gate, push and enqueue acts while also citing a spec's step.
- iss-2610262038283527The glossary keeps bare "the loop" for the record loop and says abcd never owns a run loop; the agent catalog uses bare "the loop" for abcd's own implement loop.
- iss-2610262038299872The glossary makes "memory" an alias of memory note; the configuration chapter says unqualified "memory" means the repo-scope `.abcd/memory/` page store.
- iss-2610262038308994The memory-note entry says a promoted note goes into the project's rules; the configuration chapter puts promoted notes in the project's own `memory.json` layer.
- iss-2610262038319450The surfaces register says library and memory are not one store under two names; the memory chapter's memory store holds the outside material the library ingests.
- iss-2610262038322994The library entry forbids "corpus" as a synonym; the surfaces register says "the corpus" and "the corpus verbs" for the library.
- iss-2610262038329713"persona" means a placeholder stakeholder from the personas registry, and also the name a session takes from a machine register.
- iss-2610262038336864The oracle entry forbids "LLM" for the oracle; the adapters chapter names the oracle seam's native default "host-delegated LLM".
- iss-2610262038344053The glossary retires "phase" for dependencies plus the lifecycle shelves; the configuration chapter still schedules work into "a later phase".
- iss-2610262038359555The memory chapter says the agent count stays at 15; the agent catalog ships eighteen.
- iss-2610262038368760The memory chapter says the lint contract §2 records library lint's warn-only exit-0 divergence; §2 records no divergence and says a warning raises the exit to 1.
- iss-2610262038376261Universal patterns say abcd and the companion harness interoperate as two MCP servers; the build sequence says abcd's MCP front door is a design target.
- iss-2610262038389473itd-1 says Audit Notes fill only from a hand-run audit; 01-agents says a build run audits automatically in the validate stagerelated itd-1
- iss-2610262038393994itd-1 writes each audit's forensic copy under .abcd/logbook/; 04-universal-patterns says that name is retired and must not be re-mintedrelated itd-1
- iss-2610262038399413itd-1 says the SHIP/NEEDS_WORK/MAJOR_RETHINK review verdicts score plan and implementation reviews; 01-agents limits them to a packed lifeboatrelated itd-1
- iss-2610262038415265itd-1 cites lint code IL002 and points to 06-lint.md for it; 06-lint says the engine has no numbered codesrelated itd-1
- iss-2610262038415713itd-5 keeps the candidate on a tie and says length is no tiebreak; 05-prompt-quality accepts a rewrite that ties and is more than 10% shorterrelated itd-5
- iss-2610262038425929itd-5 calls the prompt linter lint_prompts; 05-prompt-quality calls the one shipped prompt-tree rule agent_contractrelated itd-5
- iss-2610262038431352itd-5 preserves an oracle cascade it attributes to universal pattern § 7; 04-universal-patterns says the core imposes no cascaderelated itd-5
- iss-2610262038443634itd-5 counts 14 (now 15) agents under its rule; 01-agents says eighteen agent prompts shiprelated itd-5
- iss-2610262038457611itd-5's lock-time pre-flight submits prompts to lifeboat-oracle; 01-agents' rosters have no such agentrelated itd-5
- iss-2610262038460690itd-11 has lifeboat-oracle audit a lifeboat's output; 01-agents names the lifeboat auditor lifeboat-reviewerrelated itd-11
- iss-2610262038472526itd-14 marks a prompt's version with a `## Prompt Version: X.Y` field; 05-prompt-quality requires semver prompt_version frontmatterrelated itd-14
- iss-2610262038484184itd-14 keeps a changelog at agents/< name>/CHANGELOG.md; 01-agents keeps the changelog out of agents/, at .abcd/development/agents/related itd-14
- iss-2610262038490693itd-81 puts each judge's calibration corpus at agents/< name>/corpus/; 01-agents says agents/ holds prompts and fixture directories and nothing elserelated itd-81
- iss-2610262038495354itd-37 says Role 1 boilerplate detection runs at plan-review and ship time; 01-agents says the auditor's modification-grammar output is deferred and in no prompt or lintrelated itd-37
- iss-2610262038501901itd-37 defines the concreteness lint as numbered codes MG001 to MG003; 06-lint says the engine has no numbered codesrelated itd-37
- iss-2610262038511722itd-37 puts append-only pages into .abcd/memory/; universal pattern § 8 gives each namespace one lifecycle class and lists .abcd/memory/ as compounding-curatedrelated itd-37
- iss-2610262038521887itd-10's destroy deletes a lifeboat and a logbook inside .abcd/; 03-configuration says neither namespace exists in any treerelated itd-10
- iss-2610262038534481itd-13's dev-sync curates entries into the issue ledger; 03-configuration says capture writes the ledger directly and the sync has nothing left to migrate thererelated itd-13
- iss-2610262038541403itd-16 writes its chain report under .abcd/logbook/; 03-configuration says logbook/ is retired in favour of the local tier's logsrelated itd-16
- iss-2610262038559695itd-16 calls bare-command-as-help a universal convention; the surfaces register says bare invocation is a convention, not a universalrelated itd-16
- iss-2610262038565943itd-25 writes dredge reports under .abcd/logbook/dredge/; 04-universal-patterns puts dredge output in the local tier's logsrelated itd-25
- iss-2610262038572033itd-25 says other agents have RepoPrompt and Codex CLI alternatives; 02-adapters routes only a build lane's two reviews off the hostrelated itd-25
- iss-2610262038577903itd-25 calls issue-scout an existing agent; 01-agents lists it in a design roster of which none existsrelated itd-25
- iss-2610262038581765itd-26 names /abcd:memory ingest as the knowledge-ingest verb; the surfaces register gives the name memory to the notes commandrelated itd-26
- iss-2610262038595637itd-126 adds abcd source share and abcd source ingest; the surfaces register folds the old source command into libraryrelated itd-126
- iss-2610262039000162itd-2609292108089653 refuses a stub at source add; the surfaces register folds the source command into libraryrelated itd-2609292108089653
- iss-2610262039010827itd-2609292109475690's memory scenario asks the memory store a question; the surfaces register says notes come back automatically and asking is the library's jobrelated itd-2609292109475690
- iss-2610262039022652itd-107 keeps arming auto-merge and polling merge state out of the binary; 38-land's binary verb arms and confirms merges itselfrelated itd-107
- iss-2610262039030685itd-113 calls MCP abcd's second front door; 03-configuration calls an mcp/ door adr-23's thirdrelated itd-113
- iss-2610262039043469itd-2610170634394993 puts agents' work claims on the shared remote; 04-universal-patterns puts multi-agent claims in .abcd/coordination/related itd-2610170634394993
- iss-2610262039055212itd-2610070549060530 calls the board /abcd:abcd; the surfaces register calls it /abcdrelated itd-2610070549060530
- iss-2610262039059270itd-2610170634394993 proposes a central view of what every session is doing; 39-status already ships /abcd:status as that viewrelated itd-2610170634394993
- iss-2610262039066046itd-35 writes its lifeboat audit report under `.abcd/logbook/`, a root the universal-patterns page says was retired and must not be re-mintedrelated itd-35
- iss-2610262039086156itd-59 puts the transcript corpus at `~/.abcd.noindex/history/<root_sha>/`, but the configuration page puts it in the sibling store `~/.abcd.noindex/transcripts/<root-sha>/`related itd-59
- iss-2610262039090204itd-30 puts its format flag on `/abcd:intent new`, but universal patterns says the canonical create is bare `/abcd:intent "<text>"`related itd-30
- iss-2610262039093344itd-30 calls the fidelity agent `intent-fidelity-reviewer`, but the agent catalogue calls it `intent-auditor`related itd-30
- iss-2610262039106613itd-44 routes through an `abcd-intent-new` skill, but the surfaces register says abcd ships zero skillsrelated itd-44
- iss-2610262039128746itd-41 calls the grill a skill, but the surfaces register says the grill's design target is an `/abcd:intent` sub-verb, not a skillrelated itd-41
- iss-2610262039132211itd-55 says abcd already stress-tests acceptance criteria with the grill, but the surfaces register says no grill shipsrelated itd-55
- iss-2610262039144591itd-57 unblocks a spec with a native `spec rm-dep`, but the spec verb registers only its bare board and `spec close`related itd-57
- iss-2610262039150797itd-57 uses 'voyage' for a project's configured set of specs, but the configuration page defines a voyage as the user-scope log of disembark runsrelated itd-57
- iss-2610262039169067itd-61 says abcd already carries built reality forward into the brief (itd-60), but universal patterns says that forward pass is planned and not yet builtrelated itd-61
- iss-2610262039173971itd-8 extends a `code-rescuer` agent it calls currently principle-only, but the agent catalogue lists `code-rescuer` among the agents still to be builtrelated itd-8
- iss-2610262039184070itd-83 says the reviewer agents ship as-is at 0.1.0, but the prompt-quality page says they entered the changelog at 0.2.0related itd-83
- iss-2610262039188312itd-83's fallback for harnesses without hooks is a pointer in AGENTS.md's marked section, but the configuration page says a default install writes no marker blockrelated itd-83
- iss-2610262039195057itd-85 makes `abcd audit` a repository conformance check, but the agent catalogue reserves the top-level `/abcd:audit` for itd-16's hash-chain surfacerelated itd-85
- iss-2610262039214406itd-85's `abcd audit` checks whether a repository conforms, which the register already gives to `/abcd:lint`related itd-85
- iss-2610262039216588Draft itd-86 proposes a cold-reading surface that the agent catalogue says already ships as the four-position instrumentrelated itd-86
- iss-2610262039224536itd-91 puts its setup question in `/abcd:init` / `prepare-this-repo`, but the register says repository preparation moved into ahoy's install sectionrelated itd-91
- iss-2610262039245351The worktree-store intent makes its verb a sub-verb of `ahoy`, but the surfaces register lists it as a top-level `/abcd:worktree`related itd-2609091014076309
- iss-2610262039253719The oracle-routing intent sends a step to a configured provider that can serve its tier, but the adapters page says a tier alone never reaches a providerrelated itd-2609170822093401
- iss-2610262039259706The announce intent says a reservation records who owns an item, but universal patterns puts multi-agent claims in `.abcd/coordination/`related itd-2609151838312703
- iss-2610262039262634The build intent arms auto-merge wherever the ruleset gates merges through a queue, but the land page says AM1 arms it only where a queue and a required approval both existrelated itd-2609201916151817
- iss-2610262039276483The consistency-pass hook runs rule checks over the whole corpus at commit time, but the lint contract's pre-commit tier lints only staged lines so that old findings never blockrelated itd-2609291923559186
- iss-2610262039286595The memory-notes intent lets the status line write one fill file, but the configuration page says the status line writes nothing at allrelated itd-2610091918433290
- iss-2610262039290078The land page calls AM1's arming 'human mode', but the facilitator-mode intent rules that `human` arms nothing, even where the forge would hold the merge for approvalrelated itd-2610150602547271
- iss-2610262039297157The configuration chapter stages itd-50's audit loop as a per-intent frontmatter mode, while itd-50 rules that the loop is build's last stage for every intent, not a per-intent moderelated itd-50
- iss-2610262039302287itd-50 names the fidelity auditor `intent-fidelity-reviewer`; the agent catalog names the same agent `intent-auditor`related itd-50
- iss-2610262039314007itd-50 calls the implementation fix loop a SHIP/NEEDS_WORK loop; the agent catalog says the loop's reviewer states SHIP or FIX FIRST, and that NEEDS_WORK belongs to the lifeboat reviewrelated itd-50
- iss-2610262039325628itd-39 extends a Python hook file `hooks/prompt_router_hook.py`; the configuration chapter says the prompt router is the binary's `abcd hook prompt-router` entrypointrelated itd-39
- iss-2610262039330569itd-39 reuses the rules loader's context brackets (itd-3); the configuration chapter's loader has no context brackets and attributes the budget bracket to itd-39 itselfrelated itd-39
- iss-2610262039345320itd-39 has the prompt hook inject `.abcd/memory/` pages automatically on a prompt match; the surfaces register says library material comes back only when the person asksrelated itd-39
- iss-2610262039347531itd-7 packs the RepoPrompt workspace by running dev-sync, which writes into the repo, as a disembark pre-pack step 'already in brief'; the configuration chapter says disembark never writes to the source repositoryrelated itd-7
- iss-2610262039356482itd-117 puts the user rules layer at `~/.abcd/rules.json`; the configuration chapter puts it under `~/.abcd.noindex/` and treats any entry at `~/.abcd` as a stoprelated itd-117
- iss-2610262039366512itd-200 keeps the status line's user-level defaults under `~/.abcd/`; the configuration chapter says that while anything stands at `~/.abcd` the status line, like every command, writes nothingrelated itd-200
- iss-2610262039376194itd-201 scopes a GRILL domain in this repository's `.abcd/rules.json` kept in step with the bundled copy; the configuration chapter says GRILL is generated from one Go source and abcd's own repository declares no override of itrelated itd-201
- iss-2610262039378497itd-105 keeps every hook command calling `$CLAUDE_PLUGIN_ROOT/abcd` directly, with the bootstrap as the first SessionStart hook; the configuration chapter says every event's command is `sh` on a per-event shim and SessionStart is one chained commandrelated itd-105
- iss-2610262039384176itd-146 groups `spec`, `drain` and `memory` under records, `lint` under checks and `changelog` in the agent block; the surfaces register's help table puts those verbs with the agents and `changelog` in neither blockrelated itd-146
- iss-2610262039394542itd-130 names an `abcd version --check` command; the surfaces register says `version` is the root's `--version` flag, not a verbrelated itd-130
- iss-2610262039403534itd-111 says `abcd version` always shows install mode and vintage; the surfaces register says `version` is a root flag, not a verbrelated itd-111
- iss-2610262039410774itd-138's install script finishes by running `abcd version`; the surfaces register says `version` is a root flag, not a verbrelated itd-138
- iss-2610262039417690The surfaces register gives the hidden hook verb six entrypoints, while the away-mode intent adds a Stop hook that runs `abcd hook stop`.related itd-2610180912189125
- iss-2610262039423717The README's `abcd rules` loads a machine-wide rules.json layer, which itd-3 explicitly rejects.related itd-3
- iss-261026203943968103-configuration makes the rules refresh event-driven with a 15-turn backstop; itd-3 forces a full re-inject every N turns, N defaulting to 5.related itd-3
- iss-261026203944294303-configuration says the shared tier holds 'the append-only decision log'; itd-2609151138388536 replaced that log with one file per decision.related itd-2609151138388536
- iss-2610262039443223itd-34 calls the three-role audit agent `intent-fidelity-reviewer`; 01-agents calls the same agent `intent-auditor`.related itd-34
- iss-2610262039451705itd-34 ships a shape-classification role that runs from the pre-commit hook and `/abcd:intent shape`; 01-agents says the role is a design target with no `shape` sub-verb.related itd-34
- iss-2610262039463304itd-34 files shape findings under `.abcd/logbook/`, a name 04-universal-patterns retired and says must not be re-minted.related itd-34
- iss-2610262039476904itd-34 maps a standalone intent one-to-one to a flow-next spec; the surfaces register says an intent owns one or more specs in the native spec store.related itd-34
- iss-2610262039482748itd-2610030810350727 says a question that breaks the layout rules is refused before it reaches the person; 04-universal-patterns says a question that is too tall is shown anyway.related itd-2610030810350727
- iss-2610262039487315itd-4 ships a `dev-sync` migration of `.abcd/.work.local/issues.md`; 03-configuration says no `dev-sync` verb exists.related itd-4
- iss-261026203949497904-universal-patterns classes issue-ledger entries as immutable once created; itd-4's `capture resolve` moves an entry and adds a resolution note.related itd-4
- iss-2610262039504627itd-40 says identity and lineage live directly in the history `index.json`; 03-configuration puts lineage in a separate file per repository under that key.related itd-40
- iss-2610262039519748itd-40 has ahoy create `~/.abcd/history/`; 03-configuration says no reader ever reads the old `~/.abcd` name and that its presence stops every command.related itd-40
- iss-2610262039522985`/abcd:memory` is itd-36's curated knowledge store with `ingest`, `ask` and `lint`, and also the README's command for short lessons agents keep.related itd-36
- iss-2610262039527135itd-36 gives `principle-distiller` a curator role over memory ingest from external sources; 01-agents lists it as feeding only `disembark principles`.related itd-36
- iss-2610262039536939itd-2609212130136102 caps the person's default verb list at fourteen; the README says neither surface caps it and lists seventeen.related itd-2609212130136102
- 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 itd-2609231013154443
- iss-2610262039556194itd-2609212113220149 requires the verb's sentence to be byte-identical on the list, the help and the plugin page; the README adds a 'use when' clause to two pages' descriptions.related itd-2609212113220149
- iss-2610262039567036'Status' names both the board's Now / Next / Later block and `/abcd:status` with its `## STATUS` block of announcements.related itd-2609212103568351
- iss-2610262039572342itd-34 says its subtype deferral mirrors the lint-code namespace pattern in 06-lint; 06-lint says the engine has no code catalogue.related itd-34
- iss-261026203958198003-configuration schedules work 'in a later phase'; itd-2609211913453478 retired phases as the unit of sequencing.related itd-2609211913453478
- iss-2610262039584858itd-2609212137129937 bans 'maintainer' in every lint root, the command pages and rules included; 06-lint limits docs-lint to `docs/` and the repo-root prose.related itd-2609212137129937
- iss-261026203959075704-universal-patterns keeps multi-agent claims in `.abcd/coordination/` with local-only state; itd-2609091034175565 makes the reservation branch on origin the one record of who holds what.related itd-2609091034175565
- iss-261026204000411802-adapters sends spec-tied reviews to a native spec review store; itd-28 dropped that store, so the dated folders and gate receipts are the store.related itd-28
- iss-2610262040016204itd-2609091034175565 says a person sees reservations through `abcd peers`; the README lists `peers` as a verb for agents and hosts only.related itd-2609091034175565
- iss-2610262040028651itd-2610030720038073 says the stop names one rename command and abcd then runs as before; 03-configuration's stop also names a worktree repair.related itd-2610030720038073
- iss-2610262040034442The README requires a flat commands/ directory where a plugin-named subdirectory breaks every verb; itd-46 edits the intent page at commands/abcd/intent.mdrelated itd-46
- iss-2610262040034904The surfaces register says the intent verb ships no grill sub-verb; shipped itd-42 scopes itself as a capability of an existing /abcd:intent grillrelated itd-42
- iss-2610262040043356The help register names the verdict ingest `intent audit ingest`; itd-80 names it `intent review ingest`related itd-80
- iss-2610262040053417The README ships an intent only when no open spec still names it, because an intent owns one or more specs; itd-80's reconcile ships the linked intent whenever its spec closesrelated itd-80
- iss-2610262040062985The README's hook row says session-end only stages the transcript and session-start files it away; itd-89 says session-end calls history.Capture, which redacts and files itrelated itd-89
- iss-2610262040077279The agent catalog names the fidelity agent `intent-auditor`; itd-80, which created it, names it `intent-fidelity-reviewer`related itd-80
- iss-2610262040082360The agent catalog says the oracle seam is never a fixed cascade; itd-6 says its RP MCP, then Codex CLI, then in-session cascade is the fixed cascade of universal-patterns § 7related itd-6
- iss-2610262040083517The agent catalog says the auditor's third role, kind classification, is a design target; shipped itd-48 announces all three roles live, /abcd:intent shape includedrelated itd-48
- iss-2610262040093616The adapters chapter says the RepoPrompt route opens a new chat for each reviewer; itd-6 requires re-reviews to stay in the same RP chat, never a new onerelated itd-6
- iss-2610262040109467The adapters chapter says every lifeboat source reader implements probe → extract → copy; itd-95 says every adapter implements Section, Tier and Proberelated itd-95
- iss-2610262040116437The configuration chapter rules out an autodrain config knob on purpose; shipped itd-53 scopes an opt-in `review.autodrain` keyrelated itd-53
- iss-2610262040125215The configuration chapter says abcd never configures RepoPrompt or writes its route keys; itd-6 has ahoy find RP's server config and write it into .abcd/config.jsonrelated itd-6
- iss-2610262040135811The configuration chapter keeps transcripts in a user-scope store under ~/.abcd.noindex/transcripts; itd-89 files them in a local per-repo storerelated itd-89
- iss-2610262040149808The configuration chapter treats ~/.abcd as the retired home, read by no reader; itd-76 puts the sources corpus at ~/.abcd/sources/ by defaultrelated itd-76
- iss-2610262040159117The configuration chapter says abcd is one repository with no dev-to-public mirror; itd-69's checker takes an explicit `--tree dev|public` argumentrelated itd-69
- iss-2610262040161220Universal patterns put the consistency pass's report on the reviews shelf under .abcd/work/reviews/; itd-48 lands it under the retired .abcd/logbook/audit/related itd-48
- iss-2610262040177541Universal patterns call itd-60 a planned draft that is not yet built; itd-60 is shipped, and its gate refuses at spec closerelated itd-60
- iss-2610262040189116The lint contract says rules are named, never numbered; itd-43 says a `GL002` lint catches regressionsrelated itd-43
- iss-2610262040192600The lint contract calls the docs-currency gate `abcd lint docs`; itd-60 calls the same gate `abcd docs lint`related itd-60
- iss-2610262040206062The memory chapter says the agent count stays at 15; the internals index says eighteen agent prompts ship.
- iss-2610262040213900The memory chapter gives the prompt router a refresh every N prompts; the verification matrix says the refresh is event-driven and nothing counts prompts.
- iss-2610262040221402The memory chapter makes the in-tree repository store memory's primary home; the glossary says a memory note stays on the person's machine until it is promoted.
- iss-2610262040231103The memory chapter says /abcd:library ships ingest, ask and lint and nothing else; the library glossary entry says items are added with /abcd:library add.
- iss-261026204024531508-skills calls the library 'the sources corpus', a word the library glossary entry forbids.
- iss-2610262040249675The build sequence says itd-27's grilling is now the planning interview; the glossary README keeps /abcd:intent grill as a live itd-27 design target.
- iss-2610262040257210The internals index gives /abcd:grill a design target of promotion to /abcd:intent grill; the build sequence says the grill is superseded by itd-94's planning interview.
- iss-2610262040267270The out-of-scope page says a later intent enters work by being scoped into a phase; the build sequence says phases are retired and their documents are history.
- iss-2610262040273336The loop glossary says abcd never owns the run loop; the build sequence says abcd's own loop ships through abcd build without the seam.
- iss-2610262040284640The spec glossary says specs are driven to completion by the pluggable run seam; the build sequence says the run seam does not ship.
- iss-2610262040292997The spec glossary defines a spec as broken into tasks; the step glossary forbids 'task' for the unit below a spec.
- iss-2610262040295570The record entry and the record-families page use 'record family' for two different sets.
- iss-2610262040300326'position' names a cold-reading question in reading-position and a record's how-soon axis in record-families.
- iss-2610262040315792The voyage glossary says the voyage records every disembark and embark run; the verification matrix says the voyage ledger has a disembark half only.
- iss-2610262040327780The delivery index gives the build sequence an order of MVP, then companion harness, then a named host; the build sequence is a DAG of numbered Go build milestones.
- iss-2610262040339934The brief index says delivery state lives in the roadmap dashboard; the roadmap glossary says the status block has replaced the roadmap and the word.
- iss-2610262040343151itd-1 has every audit run write a forensic copy under .abcd/logbook/; the build sequence says .abcd/logbook/ is a retired location held retired by a detector.related itd-1
- iss-2610262040355731itd-1 says Audit Notes are filled only by a hand-run audit; the verification matrix says the shipping close itself requests the audit and can ingest the verdict.related itd-1
- iss-2610262040357240itd-16 puts its hash chain under .abcd/logbook/; the build sequence says that location is retired and a test fails the build on it.related itd-16
- iss-2610262040369028itd-25 writes dredge reports to .abcd/logbook/dredge/; the memory chapter puts them in .abcd/.work.local/logs/dredge/.related itd-25
- iss-2610262040379523itd-25 calls the intent-side back-edge to promoted issues resolves_issues; the verification matrix calls it related_issues.related itd-25
- iss-2610262040388759itd-25's dredge promote calls /abcd:intent new; the skills chapter says the canonical create is /abcd:intent with quoted text.related itd-25
- iss-2610262040391985itd-26 writes loot provenance cards to .abcd/work/loot/; the provenance substrate puts loot citations in .abcd/development/loot/.related itd-26
- iss-2610262040403877itd-26 calls the substrate's knowledge consumer /abcd:memory ingest; the provenance substrate calls it /abcd:library ingest.related itd-26
- iss-2610262040412521itd-2609292108089653 registers sources with `source add`; the library glossary registers them with /abcd:library add.related itd-2609292108089653
- iss-2610262040422553itd-2609292108373494 calls the planning interview 'abcd's grill'; the interview glossary says the interviews that ship are not grill sessions.related itd-2609292108373494
- iss-2610262040426321itd-2610070550516046 makes the product thinker's stored order decide what is built next; record-families says sequence comes only from dependencies and the shelves.related itd-2610070550516046
- iss-2610262040433257itd-140 names the site's gate `abcd site check`; the site chapter names it `abcd lint site`.related itd-140
- iss-2610262040442493itd-127 calls the source-to-decision trail 'the provenance ledger'; the ledger glossary calls that trail 'the sources ledger'.related itd-127
- iss-2610262040451252itd-196 builds its rehearsal rungs on the phase; the phase glossary entry says the phase is superseded and survives only as history.related itd-196
- iss-2610262040466411itd-192 decides a fidelity verdict by whether 'this phase' wires a criterion; the phase glossary entry says the phase is superseded.related itd-192
- iss-2610262040479670itd-10's destroy removes a lifeboat from inside .abcd/; the disembark glossary says there is no in-tree lifeboat directory.related itd-10
- iss-2610262040485856itd-5 has every agent spec carry prompt_version 1.0.0 at close; the verification matrix says no agent is at 1.0.0 and none is due to be.related itd-5
- iss-2610262040499690itd-5 says abcd ships 14 (now 15) agents under its rule; the internals index says eighteen agent prompts ship.related itd-5
- iss-2610262040499773itd-14 versions a prompt with a '## Prompt Version: X.Y' heading; the verification matrix says each prompt carries a semver prompt_version field.related itd-14
- iss-2610262040508345itd-37's discipline says every spec carries a Modification Grammar section; the verification matrix says no committed spec carries one and nothing checks for it.related itd-37
- iss-2610262040511595The construal glossary describes the brief's framing chapter as existing with a construal; itd-143, still a draft, has that chapter and its first instance still to be written.related itd-143
- iss-2610262040528498itd-142 writes interview grounds to a bare 'ledger'; the ledger glossary says every ledger but the issue ledger is always named in full.related itd-142
- iss-2610262040538618The site chapter's abcd site setup already lays the site into a managed repository; itd-2610040754453237 claims publishing that site for every managed project as later work.related itd-2610040754453237
- iss-2610262040545166The glossary says abcd never owns the run loop; the build intent makes abcd's own verb that loop.related itd-2609201916151817
- iss-2610262040551548The glossary keeps 'step' in the build loop for a spec's piece only; the build intent uses it for one invocation of the loop.related itd-2609201916151817
- iss-2610262040552734The glossary has a pluggable adapter supply the run loop; the drain draft puts the driving loop inside `abcd drain` itself.related itd-2610222215485265
- iss-2610262040570378The glossary makes planning the product thinker's sign-off and never unattended; the build intent adds `--auto-plan`, which plans with no human.related itd-2609201916151817
- iss-2610262040575327The glossary says signing off a dependency is never the technical facilitator's; the Terminal-interview intent records the technical facilitator signing one off.related itd-2610030810370060
- iss-2610262040588956A person's preferences have two user-level homes: the memory chapter's `~/.abcd.noindex/memory/` pages and the memory-notes intent's `~/.abcd.noindex/memory.json`.related itd-2610091918433290
- iss-2610262040599781The glossary sends a promoted memory note into the project's rules; the intent keeps promoted notes in `.abcd/memory.json`, apart from the rules people curate.related itd-2610091918433290
- iss-2610262041006295'status' is the glossary's Now/Next/Later record family, and the announcements intent gives the same name to `abcd status`, a view of announcements, reservations and release cuts.related itd-2609151838312703
- iss-2610262041018201The routing intent says nothing reads the oracle choice today; the verification matrix has close read the intent-auditor's own oracle role and send it to a provider.related itd-2609170822093401
- iss-2610262041020990The site chapter lays the record site into any managed repository; the dashboard intent promises the record site for abcd's own record only.related itd-2610032150577708
- iss-2610262041024277The site chapter puts abcd's record on abcdev.app as a surface of this repository; the Pages intent moves abcd's record to its own GitHub Pages route, like any project's.related itd-2610091010348892
- iss-2610262041032173The glossary keeps 'product thinker' off personas; the consistency-pass press release uses it as a persona's role hint.related itd-2609291923559186
- iss-2610262041043651The glossary forbids 'release' for a plan of what ships together; the checklist draft plans its bundle as 'the next big release'.related itd-2610170638184486
- iss-2610262041051263The glossary forbids 'corpus' as a synonym for the library; the relocatable-home draft calls the person's sources the 'confidential-sources corpus'.related itd-77
- iss-2610262041065877The attribution draft puts its setup question in `/abcd:init` / `prepare-this-repo`; the build sequence says there is no `abcd init` and install is `abcd ahoy install`.related itd-91
- iss-2610262041077645The skills chapter says repo preparation now runs from the install section of `commands/ahoy.md`; the audit draft wires itself into a 'prepare-this-repo Phase 2'.related itd-85
- iss-2610262041080508The skills chapter says itd-30 extends the bare create `/abcd:intent "<text>"`; itd-30 adds an `/abcd:intent new` sub-verb instead.related itd-30
- iss-2610262041095549The verification matrix says capturing an intent runs no interview; itd-30 assumes capture runs a headline/body/quote interview that it reshapes.related itd-30
- iss-2610262041101430The internals index calls the intent-vs-implementation reviewer `intent-auditor`; itd-30 calls it `intent-fidelity-reviewer`.related itd-30
- iss-2610262041102872The lifeboat-integrity draft writes its report under `.abcd/logbook/`, a location the build sequence has retired and a detector fails the build over.related itd-35
- iss-2610262041112989The manual-hold draft relies on a run-seam selector that already skips blocked specs; the build sequence says the run seam does not ship.related itd-57
- iss-2610262041122493The manual-hold draft lifts a hold with a native `spec rm-dep`; the verification matrix says the spec core has no graph and `spec` has one sub-verb.related itd-57
- iss-2610262041130402The solo-mode draft runs on the pluggable run seam via itd-29; the build sequence says itd-29's surface is superseded and the seam does not ship.related itd-97
- iss-2610262041140753The phase-negotiator draft depends on authoring new phase docs; the glossary retires the phase, keeping its documents as history.related itd-41
- iss-2610262041158645The brief-change derivation draft reuses 'the existing grill's interrogation machinery'; the verification matrix says nothing of the grill ships.related itd-61
- iss-2610262041158993The dependency-graph draft lints phase scoping against blockers; the record-families page says nothing sits above the intent for sequence.related itd-78
- iss-2610262041163346The glossary retires 'roadmap' as a word; the brief-change derivation draft uses it for the intent backlog.related itd-61
- iss-2610262041175899The foundations-auditor draft says abcd already stress-tests acceptance criteria with the grill; the build sequence says there is no grill sub-verb.related itd-55
- iss-2610262041183220The decision-verdict draft routes through an `abcd-intent-new` skill; the skills chapter says abcd ships zero skills.related itd-44
- iss-2610262041199183The decision-verdict draft adds a fourth verdict to the capture-time kind classifier; the verification matrix stages that classifier as unbuilt.related itd-44
- iss-2610262041209286The cold-reading draft only ever reads a design document, never code; the glossary's detection position reads the shipped tree against the claim record.related itd-86
- iss-2610262041210479The transcript-capture draft takes as given an autonomous worker running on the pluggable run seam; the build sequence keeps the run seam a design target.related itd-59
- iss-2610262041226231The memory chapter names the recall diagnostic a `recall` sub-verb of `abcd library`; itd-39 rules that the same diagnostic is `abcd rules --prompt` on the rules verbrelated itd-39
- iss-2610262041227792itd-7 has disembark write the RepoPrompt workspace file into the repository; the glossary defines disembark as reading the source repository without writing to itrelated itd-7
- iss-2610262041234230itd-39 extends a Python script `hooks/prompt_router_hook.py`; the memory chapter says the prompt router is a binary sub-command, not a script file in `hooks/`related itd-39
- iss-2610262041245870itd-39 keeps the prompt router's force-refresh-every-N; the verification matrix says the refresh is event-driven and nothing counts promptsrelated itd-39
- iss-2610262041254974itd-137 says the genealogy is the page `/record/timeline/`; the site chapter says the genealogy is folded into the `/record/` dashboard, not served as a page of its ownrelated itd-137
- iss-2610262041269672itd-135 says abcdev.app's front page is now the rendered landing story; the site chapter says abcdev.app still serves the MkDocs rendering at its rootrelated itd-135
- iss-2610262041275614itd-125 renamed the lifeboat judgement to a review; the build sequence still says disembark runs the host-delegated auditrelated itd-125
- iss-2610262041289117itd-147 is sequenced as Phase 8; the phase glossary entry says roadmap phases run 0–7related itd-147
- iss-2610262041291369itd-179 refuses capture promote, resolve and wontfix without grounds; the verification matrix says resolve records grounds only when they are givenrelated itd-179
- iss-2610262041299335itd-180 gives the disposition record five states; the glossary defines a disposition as one of four statesrelated itd-180
- iss-2610262041301883Shipped itd-24 has embark surface past retrospectives during its press-release interview; the verification matrix says embark's press-release interview is staged and what ships is probe-then-writerelated itd-24
- iss-2610262041318943itd-24 uses "voyage" for a project's lifetime of work; the glossary defines voyage as the operations namespace of disembark and embark runs and forbids it for a projectrelated itd-24
- iss-2610262041325659itd-50 says a NOT_MET verdict is logged and "the voyage moves on", using voyage for project progress; the glossary reserves voyage for the operations namespacerelated itd-50
- iss-2610262041338234itd-50 says the `intent-fidelity-reviewer` records today's NOT_MET verdicts; the verification matrix names that role `intent-auditor`related itd-50
- iss-2610262041342697itd-200 puts the status-line defaults in the user-level home under `~/.abcd/`; the memory chapter puts the user scope under `~/.abcd.noindex/`related itd-200
- iss-2610262041346676itd-117 puts the user-scope rules file at `~/.abcd/rules.json`; the memory chapter puts the user scope under `~/.abcd.noindex/`related itd-117
- iss-2610262041359075The reading-position glossary says `comparative` does not assemble and refuses for want of a channel; the comparative-reading intent says it can now be commissioned and assembles a derived widening runrelated itd-2609020625407419
- iss-2610262041364605The record-families page claims to be the one map of record families and lists seven; the reframe intent adds a reframe record family beside other reading families, none of which has a rowrelated itd-2609020625402518
- iss-2610262041372020The loop glossary says abcd never owns the run loop and an adapter supplies it; itd-82 sends drain's issues through the loop `abcd build` itself runsrelated itd-82
- iss-2610262041388352The persona glossary requires a registered persona for any press-release quote; itd-82 quotes an unnamed product thinker insteadrelated itd-82
- iss-2610262041393479itd-201 says the GRILL domain and the interview page carry the knowledge-floor text; the knowledge-floor glossary page says GRILL only points to it and the page states the floor in fullrelated itd-201
- iss-2610262041398357The record-families page lists the step intent itd-2609212103565953 as planned; that intent is filed under shipped/.related itd-2609212103565953
- iss-2610262041402639The step glossary entry calls itd-2609212103565953 planned, but that intent has shipped.related itd-2609212103565953
- iss-2610262041419578The step intent says `implement step` and the spec's Steps section share one word; the step glossary entry says `implement step` performs a stage, not a step.related itd-2609212103565953
- iss-2610262041427822The spec glossary entry says a spec breaks down into numbered tasks; the vocabulary intent made the step the unit below a spec.related itd-2609211913453478
- iss-2610262041438494The vocabulary intent says not_to_be_confused_with may name only families; the glossary README requires only that at least one member name a family.related itd-2609211913453478
- iss-2610262041445723The loop glossary entry says abcd never owns the run loop; the shipped pacing intent describes the loop abcd's own build, drain and implement verbs run.related itd-2609201925079472
- iss-2610262041454448The memory chapter says the prompt router is a binary sub-command, not a script in hooks/; the shipped rules-loader intent scopes it as hooks/prompt_router_hook.py.related itd-3
- iss-2610262041455139The verification matrix says the rules-loader refresh is event-driven and nothing counts prompts; itd-3 refreshes in full every N turns.related itd-3
- iss-2610262041468809The provenance chapter says the source-hash registry is durable and only partly regenerable; itd-36 scopes it as regenerable.related itd-36
- iss-2610262041476159/abcd:memory names the memory-note command in the glossary, but itd-36 names the curated knowledge substrate with ingest, ask and lint.related itd-36
- iss-2610262041481549The voyage glossary entry forbids using voyage for a project; itd-36 uses voyage to mean the project a researcher runs under abcd.related itd-36
- iss-2610262041499021In the glossary a voyage is the operations namespace of lifeboat runs; itd-34 calls an application project a voyage.related itd-34
- iss-2610262041504223The internals index counts eighteen shipped agent prompts; itd-36 says the agent count stays at 15.related itd-36
- iss-2610262041516427The internals index calls the fidelity agent intent-auditor; itd-34 calls the same agent intent-fidelity-reviewer.related itd-34
- iss-2610262041521807The verification matrix marks the capture-time kind classifier and the shape role as staged; shipped itd-34 claims both.related itd-34
- iss-2610262041529246The build sequence says .abcd/logbook/ is retired, with a detector that fails the build on it; itd-34 writes shape findings under .abcd/logbook/audit/.related itd-34
- iss-2610262041532193In the glossary a spec lives in abcd's native spec store; itd-34 maps each intent to a flow-next spec planned through /flow-next:plan.related itd-34
- iss-2610262041545005The spec glossary entry forbids 'epic' as a synonym; itd-34 has bundle members share an epic_id that holds a spec id.related itd-34
- iss-2610262041559803The glossary enforces 'epic' as a forbidden synonym; itd-4's issue schema names a related_epics field holding spec ids.related itd-4
- iss-2610262041563970The verification matrix marks migrating a flat issue list into the ledger as staged with no verb; shipped itd-4 scopes that migration.related itd-4
- iss-2610262041579226The verification matrix says the spec core has no review store; shipped itd-28's press release says every spec-tied review lands in the native review store.related itd-28
- iss-2610262041582285itd-2609150819445595 says every spec close mints an owed receipt; the verification matrix says only the shipping close does, and a build run ingests its verdict at that close.related itd-2609150819445595
- iss-2610262041590949The glossary defines a record as an itd, spc, adr, iss or rdg id; the decisions intent mints decision records with ids of their own.related itd-2609151138388536
- iss-2610262042009257The embark entry says the shipped interviews ask one thing at a time, not in rounds; the question-layout intent lets up to four tabbed questions share a screen.related itd-2610030810350727
- iss-2610262042019151Persona names identify stakeholder archetypes in press releases; the session-naming intent reuses them, in list order, as names for live sessions.related itd-2610111707085098
- iss-2610262042028384The site chapter says no repo-agnostic explorer claim is made until a second instance proves it; shipped itd-2609061543533170 claims the pages render for every managed repository.related itd-2609061543533170
- iss-2610262042029426The product-thinker entry says a persona's role hint is an outside job title, not the product thinker; itd-2610090831227812 attributes its quote to 'Iris, a product thinker'.related itd-2610090831227812
- iss-2610262042030813The memory chapter places abcd's user-level home at ~/.abcd.noindex/; itd-40 names ~/.abcd/history/index.json as the sole user-scope registry.related itd-40
- iss-2610262042040605The out-of-scope chapter says intents enter work by being scoped into a phase; the vocabulary intent retired phases in favour of dependencies and the lifecycle shelves.related itd-2609211913453478
- iss-2610262042051056The build sequence is organised around 'milestones' as a live term; the vocabulary intent marks milestone superseded.related itd-2609211913453478
- iss-2610262042063245The brief README sends readers to the roadmap dashboard for delivery state; the status-board intent retires the word and points it at the Now/Next/Later block.related itd-2609212103568351
- iss-2610262042079651itd-42 extends an existing `/abcd:intent grill` sub-verb; the build sequence says intent has no grill sub-verb at all.related itd-42
- iss-2610262042081902itd-42 records coherence findings in a grill report and a PRD behind the GR002 gate; the verification matrix says no grill report, no PRD and no GR* code exist.related itd-42
- iss-2610262042088869itd-46 lists `ship` and `grill` as existing intent sub-verbs that keep requiring an id; the build sequence says neither exists.related itd-46
- iss-2610262042091628itd-46 calls bare-invocation-renders-status a universal abcd convention; the skills chapter says it is a convention and not a universal.related itd-46
- iss-2610262042109861itd-48 lands its consistency and shape reports under `.abcd/logbook/audit/`; the build sequence says `.abcd/logbook/` is retired and guarded by a detector.related itd-48
- iss-2610262042115843itd-48 says Role 3 kind classification ships and `/abcd:intent shape` becomes a working surface; the verification matrix lists the shape-classification role as staged.related itd-48
- iss-2610262042125545The agent that audits intents is called `intent-fidelity-reviewer` in itd-48 and `intent-auditor` in the internals index.related itd-48
- iss-2610262042130595itd-6 keeps a re-review in the same chat for every backend, the in-session subagent included; the verification matrix says consecutive host-delegated calls are independent dispatches.related itd-6
- iss-2610262042134366The verb that ingests a fidelity verdict is `abcd intent review ingest` in itd-80 and `abcd intent audit ingest` in the verification matrix.related itd-80
- iss-2610262042143519itd-6 rules out direct provider API integrations and puts RP MCP first in the oracle cascade; the build sequence ships an opt-in OpenAI-compatible provider and makes the host the default.related itd-6
- iss-2610262042159336itd-60 is sequenced as a rung of Phase 8; the phase entry says roadmap phases run 0–7, and it retires the phase.related itd-60
- iss-2610262042162078itd-67 picks the bump tier from phase completion and writes the version into plugin.json; the version entry keeps the working tree unversioned and derives the version from impact.related itd-67
- iss-2610262042174713itd-67 builds the changelog from git tags, commit and spec history and the launch report, and lets a gate append to it; the release entry composes it from records that reached a terminal folder.related itd-67
- iss-2610262042183674itd-73 makes any breaking intent a major bump and a cut with nothing additive a patch; the version entry bumps the minor for a breaking change before 1.0 and derives no version for an empty cut.related itd-73
- iss-2610262042193372itd-76 calls its log of which source influenced which decision 'the provenance ledger'; the ledger entry keeps that name for another sense and calls this one 'the sources ledger'.related itd-76
- iss-2610262042201742itd-76 puts abcd's user-level home at `~/.abcd/`; the memory chapter puts the user scope under `~/.abcd.noindex/`.related itd-76
- iss-2610262042208017itd-88 writes the packer as `disembark <repo> to <dest>`; the disembark entry writes it as `abcd disembark pack <source-repo> <dest>`.related itd-88
- iss-2610262042214474itd-89 files captured transcripts in a local per-repo store; the build sequence keeps the transcript store outside every checkout, at the user level.related itd-89
- iss-2610262042222565itd-94 has the agent run `abcd intent plan` as the person's sign-off; the plan entry has the human run it and says it is never inferred from consent.related itd-94
- iss-2610262042237923A fidelity review that cannot run because no backend is reachable is 'deferred' in itd-53 and 'owed' in the verification matrix.related itd-53
- iss-2610262042244924The audit verb is the hash-chain umbrella in itd-16 and a repo-conformance check in itd-85related itd-16 · related itd-85
- iss-2610262042256389The glossary's detection reading compares the shipped tree with the claim record; itd-86's cold reading detects contradictions inside one documentrelated itd-86
- iss-2610262042269640The glossary forbids calling a cold reading a review; itd-90 says the cold reading reviews a documentrelated itd-90
- iss-2610262042279476The glossary keeps disposition apart from the issue ledger's resolved and wontfix; itd-87 calls resolved and wontfixed entries dispositionedrelated itd-87
- iss-2610262042284906Disposition has four states in the glossary; the deferred-finding discipline gives it three different wordsrelated itd-2610141956319695
- iss-2610262042289741Regime is a reading's licence (generative, explicative, evaluative, registrative) in the glossary; itd-142 names four question regimes with other valuesrelated itd-142
- iss-2610262042291241The glossary calls the phase a retired sequencing unit; the rehearsal discipline builds its rungs on live phasesrelated itd-196
- iss-2610262042302710itd-192 decides verdicts by whether this phase wires a criterion, a unit the glossary calls retiredrelated itd-192
- iss-2610262042314589itd-41 proposes phase plans as its whole capability; the glossary says the phase is retiredrelated itd-41
- iss-2610262042329594The glossary forbids calling a reading's position a step; itd-143 calls the widening reading the Step 2 readingrelated itd-143
- iss-2610262042332488itd-1 puts Acceptance Criteria in the discipline template; itd-190 says the discipline template carries no claim sectionsrelated itd-1 · related itd-190
- iss-2610262042345947itd-1 gives intent-auditor four verdict states and rejects binary pass/fail; itd-81 requires binary verdicts from every judge, intent-auditor named firstrelated itd-1 · related itd-81
- iss-2610262042351798itd-84's validator inherits itd-81 yet renders a three-outcome verdict; itd-81 requires binary verdictsrelated itd-81 · related itd-84
- iss-2610262042363456The agent that audits a shipped intent is intent-auditor in itd-1 and intent-fidelity-reviewer in itd-25related itd-1 · related itd-25
- iss-2610262042367104Persona Alice is a product thinker in itd-106 and a maintainer in itd-107related itd-106 · related itd-107
- iss-2610262042372556Persona Carol is an engineering manager in itd-12 and a facilitator in itd-115related itd-115 · related itd-12
- iss-2610262042381184Both itd-115 and itd-2610110940216682 have abcd set up the merge queue when preparing a managed repositoryrelated itd-115 · related itd-2610110940216682
- iss-2610262042399506itd-106 and itd-2610110940216682 each scaffold the managed repository's CI workflow, to different shapesrelated itd-106 · related itd-2610110940216682
- iss-2610262042403190Both itd-106 and itd-118 have abcd switch on deletion of merged PR branchesrelated itd-106 · related itd-118
- iss-2610262042412794itd-2609151838312703 plans to rename the status board to the dashboard; itd-2610070549060530 uses board and dashboard for two different surfacesrelated itd-2609151838312703 · related itd-2610070549060530
- iss-2610262042426018itd-19's stage profiles switch one oracle value per stage; itd-2609170822093401 says that repo-wide value is read by nothing and routes per agent tier insteadrelated itd-19 · related itd-2609170822093401
- iss-2610262042428344A draft for later and a planned intent both publish any managed project's record siterelated itd-2610040754453237 · related itd-2610091010348892
- iss-2610262042437551itd-140's gate hardens once itd-139's fixture exists; the dashboard intent replaced itd-139 and gave the genericity promise uprelated itd-140 · related itd-2610032150577708
- iss-2610262042445075itd-140 bars any intent from describing the site build as repo-agnostic before a sparse fixture proves it; itd-2610091010348892 promises it for every projectrelated itd-140 · related itd-2610091010348892
- iss-2610262042452621itd-26 makes /abcd:memory ingest the knowledge-ingest verb; itd-2610091918433290 makes /abcd:memory the agents' memory-notes commandrelated itd-26 · related itd-2610091918433290
- iss-2610262042462569itd-2609292108089653 refuses stubs at source add; itd-2610091918433290 says the sources command was merged into libraryrelated itd-2609292108089653 · related itd-2610091918433290
- iss-2610262042473980Ingest means importing shared bibliography entries in itd-126 and storing a source's text in itd-2609292108089653related itd-126 · related itd-2609292108089653
- iss-2610262042486043itd-142 states abcd ships zero skills; itd-44 routes capture through an abcd-intent-new skillrelated itd-142 · related itd-44
- iss-2610262042495955itd-81 puts judge panels out of scope; itd-98 runs a judge panel under the itd-81 disciplinerelated itd-81 · related itd-98
- iss-2610262042503210itd-84 says model contradiction detection must never hold a gate shut on its own; itd-2609291923559186's hook can refuse a commit on onerelated itd-2609291923559186 · related itd-84
- iss-2610262042504165itd-2610100704270254 makes the sub-agent budget a repository setting; itd-2609151838312703 calls it a property of one machinerelated itd-2609151838312703 · related itd-2610100704270254
- iss-2610262042513525itd-2610170634394993 and itd-2609151838312703 each define the one view of what every session is doingrelated itd-2609151838312703 · related itd-2610170634394993
- iss-2610262042524170itd-2609151838327688 mirrors messages to the session mailbox; itd-2609151838312703 says that mailbox is retiredrelated itd-2609151838312703 · related itd-2609151838327688
- iss-2610262042536971itd-2610070550516046 waits on two abcdesign.app drafts to settle how a reorder reaches a session; itd-2610091016262335 retired bothrelated itd-2610070550516046 · related itd-2610091016262335
- iss-2610262042541203itd-2610040817105016 and itd-61 both derive implied work from a brief edit, one advisory and one blockingrelated itd-2610040817105016 · related itd-61
- iss-2610262042556788itd-2610100627454580 rests on abcd being unable to start an agent; itd-2610120738075547 has abcd start cloud sessions itselfrelated itd-2610100627454580 · related itd-2610120738075547
- iss-2610262042568717itd-2610070549060530 puts the revisit list above everything else on the board; itd-2610031214560142 fixes the board's top as the view label, then now and nextrelated itd-2610031214560142 · related itd-2610070549060530
- iss-2610262042571852The glossary reserves 'disposition' for the researcher's response to a reading item; itd-82 uses it for a drain run's per-issue outcome.related itd-82
- iss-2610262042575392The disposition glossary entry fixes four states; itd-180 calls the same disposition vocabulary five-state.related itd-180
- iss-2610262042580667'declined' is a reading-item disposition state in the glossary and a capture-triage grounds value in itd-179.related itd-179
- iss-2610262042593698The glossary defines warm as what a cold reading must never see; itd-199 defines warmth as how much a reader is given.related itd-199
- iss-2610262043005827itd-192's verdict rule turns on 'this phase'; itd-24 records that phases are retired and the release is the unit.related itd-192 · related itd-24
- iss-2610262043017551itd-196's cumulative and closing rehearsal rungs are defined over a phase; itd-24 records that phases are retired.related itd-196 · related itd-24
- iss-2610262043026422itd-26 names the knowledge-ingest verb '/abcd:memory ingest'; itd-39 records that 'memory' is now the agents' notes command.related itd-26 · related itd-39
- iss-2610262043030522The sources-corpus draft names its ingest, consult and lint 'source add', a consult verb and a corpus lint; itd-39 says the store is already reached as library ingest, ask and lint.related itd-2609292108089653 · related itd-39
- iss-2610262043043502itd-1 names the agent that writes criterion verdicts 'intent-auditor'; itd-50 names it 'intent-fidelity-reviewer'.related itd-1 · related itd-50
- iss-2610262043043610itd-1 fixes the audit at four verdict states; itd-50 adds UNACHIEVABLE as a fifth terminal audit outcome.related itd-1 · related itd-50
- iss-2610262043053279itd-11 calls the lifeboat check 'the lifeboat-oracle's audit'; itd-125 consolidated that oracle/audit/review triple into 'review'.related itd-11 · related itd-125
- iss-2610262043063912itd-107 keeps the strict merge policy because ids minted on two branches can collide; itd-114 says such ids never collide.related itd-107 · related itd-114
- iss-2610262043071551itd-115 keeps the strict merge gate to catch duplicate ids from parallel sessions; itd-114 says ids are collision-proof with no coordination.related itd-114 · related itd-115
- iss-2610262043089096The delegated-payload draft refuses a payload that names no model; itd-166 records a missing served model as a reason, never leaving it out.related itd-166 · related itd-2609180517121254
- iss-2610262043093810itd-109 and itd-50 both define how a human's verification of an intent's criteria is recorded before shipping, as a receipt and as not a receipt.related itd-109 · related itd-50
- iss-2610262043101146The deferral discipline says every confirmed finding is fixed, invalid or captured, with no exception; the model-matrix run keeps confirmed check findings out of the ledger.related itd-2610141956319695 · related itd-2610161733316518
- iss-2610262043106501The brief-realisation draft treats the brief as the target design in the present tense; itd-147 sequences the brief as the shipped state.related itd-147 · related itd-2610040817105016
- iss-2610262043114601itd-168 claims the plain-language-and-options defaults for how abcd talks to the product thinker; shipped itd-201 already fixes them.related itd-168 · related itd-201
- iss-2610262043120814The person's user-level abcd settings live under ~/.abcd/ in itd-200 and under ~/.abcd.noindex/ in the provider-bundle draft.related itd-200 · related itd-2609301918174237
- iss-2610262043135705The product-thinker persona is Alice in itd-106 and Iris in itd-135.related itd-106 · related itd-135
- iss-2610262043143346The facilitator persona is Carol in itd-115 and Nia in itd-120.related itd-115 · related itd-120
- iss-2610262043159613itd-79 requires every press-release quote's persona to be the role's registered name; itd-198 attributes its quote to an unnamed role.related itd-198 · related itd-79
- iss-2610262043161268itd-196 makes the phase its unit of rehearsal, while itd-2609211913453478 retired the phase as a sequencing unitrelated itd-196 · related itd-2609211913453478
- iss-2610262043165117itd-192 decides a verdict by whether 'this phase' wires a criterion, a unit itd-2609211913453478 retiredrelated itd-192 · related itd-2609211913453478
- iss-2610262043179497itd-2609292107351737 cites 'the roadmap' as an authority after itd-2609211913453478 retired the wordrelated itd-2609211913453478 · related itd-2609292107351737
- iss-2610262043188086The cold-reading glossary entry names ledger/warm in not_to_be_confused_with, which itd-2609211913453478 restricts to record familiesrelated itd-2609211913453478
- iss-2610262043197794itd-191 assigns selection to 'the maintainer', a word itd-2609212137129937 removed in favour of naming the product thinker or the facilitatorrelated itd-191 · related itd-2609212137129937
- iss-2610262043202769itd-109 lets 'the maintainer' record a disposition, where itd-2609212137129937 requires naming the product thinker or the facilitatorrelated itd-109 · related itd-2609212137129937
- iss-2610262043210108itd-2610111655362931, filed after the ruling, counts 'maintainers' for promotion agreement while itd-2609212137129937 bans the wordrelated itd-2609212137129937 · related itd-2610111655362931
- iss-2610262043221489itd-1 calls the single-document fidelity auditor intent-auditor; itd-34 calls the same agent intent-fidelity-reviewerrelated itd-1 · related itd-34
- iss-2610262043232891itd-34 routes a standalone intent to a flow-next spec, while itd-37 places the spec template in abcd's native Go binaryrelated itd-34 · related itd-37
- iss-2610262043240944itd-81 requires binary verdicts from every judging agent; itd-28 locks reviewers to the three-valued SHIP / NEEDS_WORK / MAJOR_RETHINK enumrelated itd-28 · related itd-81
- iss-2610262043257570itd-1 says Audit Notes fill only when the audit is run by hand; itd-2609081951381895 has spec close send the review and ingest the answerrelated itd-1 · related itd-2609081951381895
- iss-2610262043265040itd-106 gives the product-thinker persona the name Alice; itd-2610090831227812 records the registry's product-thinker persona as Irisrelated itd-106 · related itd-2610090831227812
- iss-2610262043268358itd-79 requires they/them for every persona; itd-2610180912189125 refers to its persona Alice as 'her'related itd-2610180912189125 · related itd-79
- iss-2610262043273885itd-2610070550516046 requires build-next to be reconciled with it before either is built, but itd-2609211116005482 has already shippedrelated itd-2609211116005482 · related itd-2610070550516046
- iss-2610262043285832itd-2610100704270254 sets a run's sub-agent budget at eight middle-class agents from repository config; itd-2609201925079472 already ships the run's ceiling at two lanes, layered from flag to bundledrelated itd-2609201925079472 · related itd-2610100704270254
- iss-2610262043297244itd-25's dredge promote calls /abcd:intent new, which itd-2609212130136102 removedrelated itd-25 · related itd-2609212130136102
- iss-2610262043303389itd-25 reads every repo listed in .abcd/corpus.json; itd-40 says abcd does not group repos and keeps one registryrelated itd-25 · related itd-40
- iss-2610262043310309itd-26 names /abcd:memory ingest as the user-facing knowledge-ingest verb; itd-2610090831227812 makes /abcd:memory an agent's command for memory notesrelated itd-26 · related itd-2610090831227812
- iss-2610262043322187itd-126 adds abcd source share and abcd source ingest; itd-2610090831227812 merged the source family into library with no aliasrelated itd-126 · related itd-2610090831227812
- iss-2610262043323769itd-2609292108089653 builds ingest and consult as their own verbs; itd-2610090831227812 merged consult, ingest and source into libraryrelated itd-2609292108089653 · related itd-2610090831227812
- iss-2610262043334834itd-2609292109214516 puts its setting in the rules configuration's layered files; itd-3 rejects any personal cross-repo rules filerelated itd-2609292109214516 · related itd-3
- iss-2610262043347672itd-2609292107351737 measures per-session token cost at capture; itd-2609091718595846 already ships per-session token telemetryrelated itd-2609091718595846 · related itd-2609292107351737
- iss-2610262043356566itd-2610040754453237 files the record site for every managed project as later work; itd-2609061543533170 already ships those pages for every managed repositoryrelated itd-2609061543533170 · related itd-2610040754453237
- iss-2610262043369188itd-140 makes the landing page opt-in and never a default; itd-2609061543533170 renders it for every managed repository and forbids switching it offrelated itd-140 · related itd-2609061543533170
- iss-2610262043379064itd-2610031259176838 tells people about 'the claim branch'; itd-2609091034175565 ruled the person-facing word is reservation and the branch prefix abcd-reserved/related itd-2609091034175565 · related itd-2610031259176838
- iss-2610262043385436itd-2609091034175565 hands reservation tombstone deletion to itd-118, whose scope covers PR branches and local residue onlyrelated itd-118 · related itd-2609091034175565
- iss-2610262043392051itd-1 calls the Role 1 fidelity agent intent-auditor; itd-48 calls the same agent intent-fidelity-reviewerrelated itd-1 · related itd-48
- iss-2610262043395075The lab discipline records knowledge through 'a decisions-log line'; itd-2609151138388536 retired the append-only decision logrelated itd-2609151138388536 · related itd-2609251624540864
- iss-2610262043406581itd-1 calls the fidelity-review sub-verb /abcd:intent audit; itd-80 ships it as abcd intent review ingestrelated itd-1 · related itd-80
- iss-2610262043417816itd-1 has a repeat review replace the one Audit Notes block in place; itd-80 appends each ingested verdict, keyed on its receiptrelated itd-1 · related itd-80
- iss-2610262043429522itd-81 requires binary verdicts from every verdict-rendering agent, the intent auditor included; itd-80 ships that reviewer with four-state verdictsrelated itd-80 · related itd-81
- iss-2610262043436609itd-37 gives Role 1 the job of spotting spec boilerplate at plan-review; itd-48 defines Role 1 as grading a shipped intent's criteria against delivered realityrelated itd-37 · related itd-48
- iss-2610262043446144itd-142 takes brownfield coverage from embark probe; itd-88 ships the coverage report as disembark proberelated itd-142 · related itd-88
- iss-2610262043456762itd-142 says the tool never recommends; itd-42 lets the grill pre-pass recommend an answer in proserelated itd-142 · related itd-42
- iss-2610262043466977itd-25's dredge promote calls /abcd:intent new; itd-46 replaced the new sub-verb with quoted-text createrelated itd-25 · related itd-46
- iss-2610262043469929itd-142 says abcd ships zero skills; itd-43 still treats the grill SKILL.md as a live surface to rewriterelated itd-142 · related itd-43
- iss-2610262043470447itd-25 says agents are host-delegated by default with RepoPrompt opt-in; itd-6 keeps RP MCP as the preferred first backend in the oracle chainrelated itd-25 · related itd-6
- iss-2610262043485833itd-19 sets the oracle backend from the project's stage; itd-6 has ahoy lock it based on whether RP is reachablerelated itd-19 · related itd-6
- iss-2610262043494574itd-2609301918174237 sends the auditor and consistency pass to remote providers; itd-6 rules out direct provider API integrationsrelated itd-2609301918174237 · related itd-6
- iss-2610262043501753itd-76 puts abcd's user-level home at ~/.abcd/; itd-2609301918174237 puts the owner's machine-layer settings under ~/.abcd.noindex/related itd-2609301918174237 · related itd-76
- iss-2610262043515080itd-85 names the repo-conformance check `abcd audit`; itd-124 says the conformance check is `abcd lint` and `audit` is reserved for something elserelated itd-124 · related itd-85
- iss-2610262043520946The dashboard intent limits the record site to abcd's own record; the record-pages intent builds a record site for every project that opts inrelated itd-2610032150577708 · related itd-2610091010348892
- iss-2610262043528869`abcd audit` is the repo-conformance verb in itd-85 and the lifeboat-integrity verb in itd-35related itd-35 · related itd-85
- iss-2610262043535279The build loop arms auto-merge whenever the ruleset gates through a queue; the facilitator-mode intent says that by default abcd never arms or queues a pull requestrelated itd-2609201916151817 · related itd-2610150602547271
- iss-2610262043542024itd-82 says merging the drain's pull requests is a human gate by design; itd-2610150602547271 says that in auto mode a ready pull request merges with no human steprelated itd-2610150602547271 · related itd-82
- iss-2610262043555411itd-117 puts the user-scope rules at `~/.abcd/rules.json`; itd-77 puts abcd's user-level home at `~/.abcd.noindex/`related itd-117 · related itd-77
- iss-2610262043562914itd-200 puts the status line's user-level defaults under `~/.abcd/`; itd-77 puts the user-level home at `~/.abcd.noindex/`related itd-200 · related itd-77
- iss-2610262043574593itd-146 lists `memory` among the person's records verbs; itd-2610091918433290 says `/abcd:memory` is an agent's command for memory notesrelated itd-146 · related itd-2610091918433290
- iss-2610262043581439'dashboard' is the new name for the terminal status board in itd-2609151838312703 and the browser page reached through Tailscale in itd-2610032150577708related itd-2609151838312703 · related itd-2610032150577708
- iss-2610262043598494itd-98 leaves model-level benchmarking to itd-17; itd-2609221009495079 records itd-17 as supersededrelated itd-2609221009495079 · related itd-98
- iss-2610262043598765The routing intent leaves updating the proposal from measurements to itd-17; the decision-adapter intent records itd-17 as supersededrelated itd-2609170822093401 · related itd-2609221009495079
- iss-2610262044004875itd-97 builds solo mode on the run seam of itd-29; itd-2609201916151817 says itd-29 is supersededrelated itd-2609201916151817 · related itd-97
- iss-2610262044017905The phase negotiator (itd-41) proposes and argues over roadmap phases; itd-24 records that phases are retiredrelated itd-24 · related itd-41
- iss-2610262044029050The dependency graph (itd-78) lints phase ordering; itd-24 records that phases are retiredrelated itd-24 · related itd-78
- iss-2610262044038958itd-44 writes ADRs under a next-free ordinal; itd-114 makes every minted id collision-proof across branchesrelated itd-114 · related itd-44
- iss-2610262044045987itd-8 leaves adding code to old lifeboats to itd-9; itd-9 migrates structural schema only and excludes lifeboat contentrelated itd-8 · related itd-9
- iss-2610262044057318itd-59 and itd-2609201916151817 both claim capturing the autonomous run's transcripts into the transcript storerelated itd-2609201916151817 · related itd-59
- iss-2610262044060780Keeping a record from autonomous pickup is a sentinel-spec dependency in itd-57 and a held state the build loop checks in itd-2609201916151817related itd-2609201916151817 · related itd-57
- iss-2610262044079779itd-87 escalates a finding that matches a resolved or wontfixed record as a new entry; the consistency pass marks such a finding addressed and files nothingrelated itd-2609291923559186 · related itd-87
- iss-2610262044082114itd-86 says the cold reading's target is a design document and not code; itd-184 makes the detection reading the shipped tree against the claim recordrelated itd-184 · related itd-86
- iss-2610262044093076The agent that judges delivery against an intent is `intent-fidelity-reviewer` in itd-30 and the intent auditor in itd-24related itd-24 · related itd-30
- iss-2610262044094024The facilitator mode's values are `duo | solo` in itd-97 and `human` / `auto` in itd-2610150602547271related itd-2610150602547271 · related itd-97
- iss-2610262044102287itd-24 says abcd is single-developer or pair shaped; itd-99 says the product thinker can be a teamrelated itd-24 · related itd-99
- iss-2610262044119054itd-99 has a team of product thinkers write independently before anything is merged; itd-2610091016262335 has the team edit the brief live, each seeing the others' changesrelated itd-2610091016262335 · related itd-99
- iss-2610262044129717The phone dashboard was ruled read-only and declined answering questions; the phone checklist app exists to answer themrelated itd-2610032150577708 · related itd-2610222029228127
- iss-2610262044136729itd-2610222029228127 sends a private shared copy of every checklist through abcdev.app; itd-2610091010348892 rules that abcd never runs a server holding project contentrelated itd-2610091010348892 · related itd-2610222029228127
- iss-2610262044146391The phase negotiator drafts phases, milestones and phase acceptance, but the shipped glossary intent retired phases and milestonesrelated itd-2609211913453478 · related itd-41
- iss-2610262044146690The routing intent always falls back to the harness when a provider cannot serve; the model-matrix intent switches that fallback off inside a cellrelated itd-2609170822093401 · related itd-2610161733316518
- iss-2610262044159830The dependency-graph draft lints phase ordering, but phase is a superseded termrelated itd-2609211913453478 · related itd-78
- iss-2610262044160347The dependency graph says severity inheritance decides what to build first, but build next picks readiest first and explicitly not most-important-firstrelated itd-2609211116005482 · related itd-78
- iss-2610262044170732The design-fiction draft adds a format flag to intent new, which the verb consolidation removedrelated itd-2609212130136102 · related itd-30
- iss-2610262044186274The decision-verdict draft routes capture through an abcd-intent-new skill, but abcd ships zero skillsrelated itd-2610090831227812 · related itd-44
- iss-2610262044191365Two routes mint an ADR: the draft's capture writes adr-< next-free>, and the shipped decide verb mints ADRs with --adrrelated itd-2609151138388536 · related itd-44
- iss-2610262044201056The audit draft adds a separate repo-conformance check verb, while the shipped consolidation folded every 'check this repository' spelling into one lintrelated itd-2609212130136102 · related itd-85
- iss-2610262044218994`abcd audit` names a repo-conformance check in one record and is reserved for the hash-chain merkle audit in anotherrelated itd-4 · related itd-85
- iss-2610262044221992The recurrence draft says the ledger folds a match into the closed entry, but the shipped matcher always writes a new record and links it as a duplicaterelated itd-2609212137116617 · related itd-87
- iss-2610262044229426The audit draft wires into prepare-this-repo Phase 2, but prepare-this-repo has folded into ahoy install with no aliasrelated itd-2610090831227812 · related itd-85
- iss-2610262044237764The cold-reading draft introduces a cold reading as new, while a shipped record already dispatches cold readings by positionrelated itd-2609081951381895 · related itd-86
- iss-2610262044240923The manual-hold draft relies on the selector skipping specs with a non-done dependency, but the shipped pick selects planned intents by their blocked_by edgesrelated itd-2609211116005482 · related itd-57
- iss-2610262044255432The worker-transcript draft says autonomous passes leave only an ephemeral log, but the shipped runner captures every role's transcript into abcd's storerelated itd-2609201916056194 · related itd-59
- iss-2610262044265126The relocatable-home draft has abcd move its home on command, but the shipped rename ruled that abcd moves nothing and fixed the name at ~/.abcd.noindexrelated itd-2610030720038073 · related itd-77
- iss-2610262044274697The drive draft treats a plain-terminal drain that runs on its own as new, but the shipped drain bundle says drains already run unattended in a plain terminalrelated itd-2610161016401115 · related itd-2610222215485265
- iss-2610262044279216The checklist draft allows an open-ended away state, but the shipped away mode is capped at seven daysrelated itd-2610170638184486 · related itd-2610180912189125
- iss-2610262044285635Tier routing sends a row to a provider that can serve its tier, but the shipped adapter rules that no provider serves any tierrelated itd-2609081951381895 · related itd-2609170822093401
- iss-2610262044295915`status` names the Now/Next/Later record family in the glossary and the people's view of announcements and reservations in the planned verbrelated itd-2609151838312703 · related itd-2609211913453478
- iss-2610262044300840`peers` means records held by sibling worktrees in the shipped reader, but the planned announcements ruling reserves it for sessions running nowrelated itd-2609091416295622 · related itd-2609151838312703
- iss-2610262044310958The shipped inbox hands cross-machine report delivery to the announcements intent, which carries no free textrelated itd-2609151838312703 · related itd-2609221656361680
- iss-2610262044322326The worktree-block intent assigns typed claims to itd-33, but the shipped reservation intent delivered the claimrelated itd-148 · related itd-2609091034175565
- iss-2610262044330700The dashboard ruling promises the record site for abcd's own record only, but the shipped site verb renders the same pages for every managed repositoryrelated itd-2609061543533170 · related itd-2610032150577708
- iss-2610262044344649Memory notes sit beside each rules.json layer, including a machine layer, but the shipped rules loader rejected any machine-wide rules.jsonrelated itd-2610091918433290 · related itd-3
- iss-2610262044347395Two records build and publish a managed project's record site at each release by different routes: the shipped provider adapter, and the planned GitHub Pages routerelated itd-2609061543533170 · related itd-2610091010348892
- iss-2610262044356372'memory' names the curated knowledge namespace .abcd/memory/ and also the agent memory-notes file .abcd/memory.jsonrelated itd-2610091918433290 · related itd-36
- iss-2610262044370559Memory notes give the status line one written file, but the shipped home-gitignore intent states the status line writes nothing at allrelated itd-2610091918433290 · related itd-2610140858048004
- iss-2610262044373028The memory-notes promotion rule is stated in terms of maintainers, a word the shipped vocabulary ruling retiredrelated itd-2609212137129937 · related itd-2610091918433290
- iss-2610262044382852The board intent calls an intent listed under both Now and Next a defect, but the shipped status block lists the pick head in both by constructionrelated itd-2609212103568351 · related itd-2610031214560142
- iss-2610262044392775The what-next menu makes bare `abcd` write, against the stated convention that bare invocations are read-onlyrelated itd-2609150819445595 · related itd-2610031215002409
- iss-2610262044407176A shipped connection step uses the picker owned by the plain-Terminal interviews intent, which is still planned and unbuiltrelated itd-2610030810370060 · related itd-2610030821294016
- iss-2610262044419558The review-bar draft says prepare-this-repo owns the AGENTS.md conventions section, but prepare-this-repo has folded into ahoy installrelated itd-2610090831227812 · related itd-83
- iss-2610262044429007The attribution-preference draft puts its setup question in `/abcd:init` / `prepare-this-repo`, surfaces the verb split retired or never hadrelated itd-2610090831227812 · related itd-91
- iss-2610262044430202itd-30 builds its fiction format on an `/abcd:intent new` sub-verb, but shipped itd-46 removed that sub-verb and made quoted text the create pathrelated itd-30 · related itd-46
- iss-2610262044449331itd-77 says abcd's user-level home defaults to `~/.abcd.noindex/`; shipped itd-76 says it defaults to `~/.abcd/`, with the sources corpus at `~/.abcd/sources/`related itd-76 · related itd-77
- iss-2610262044453777itd-61 says itd-60 carries built reality into the brief and the public docs; shipped itd-60 covers the brief only and leaves the public docs to a later rungrelated itd-60 · related itd-61
- iss-2610262044454212itd-57 holds a spec back through a native spec dependency that the selector already honours; the native spec store shipped by itd-80 has no dependencies between specsrelated itd-57 · related itd-80
- iss-2610262044466021itd-8 writes the lifeboat packer as `/abcd:disembark pack <repo> <path>`; shipped itd-88 writes it as `disembark <repo> to <dest>`related itd-8 · related itd-88
- iss-2610262044474439Shipped itd-46 states a universal rule that a bare command never changes state; in itd-2610031215002409, opening the bare `abcd` board writes the waiting-on statusrelated itd-2610031215002409 · related itd-46
- iss-2610262044485589Shipped itd-6 says abcd has no oracle logic and no routing of its own; itd-2609170822093401 has abcd propose and apply a model tier for each agentrelated itd-2609170822093401 · related itd-6
- iss-2610262044499326Shipped itd-6 sends a lane's reviews to RepoPrompt through `oracle.review`; itd-2609170822093401 says nothing reads the oracle value and builds a separate routing table for each agentrelated itd-2609170822093401 · related itd-6
- iss-2610262044503777Shipped itd-6 says abcd only uses agent sessions and never starts Claude Code ones itself; itd-2610222215485265 has `abcd drain --drive` start Claude sessionsrelated itd-2610222215485265 · related itd-6
- iss-2610262044512344Shipped itd-6 leaves cost tracking per model to itd-17; itd-2609221009495079 records itd-17 as supersededrelated itd-2609221009495079 · related itd-6
- iss-2610262044513201Shipped itd-48 says Role 2 findings are only reported and a person acts on them; itd-2609291923559186 adds an automatic mode that fixes mechanical contradictions in the commitrelated itd-2609291923559186 · related itd-48
- iss-2610262044520698itd-55's foundations auditor claims to dig out an intent's unstated premises; the grill shipped by itd-42 already questions hidden assumptionsrelated itd-42 · related itd-55
- iss-2610262044537770Shipped itd-69 says the brief-change derivation gate (itd-61) produced it; itd-61 is still a draft that has not yet given abcd that gaterelated itd-61 · related itd-69
- iss-2610262044540397itd-44 puts its refusal for the decision kind into a Python plan path (`_choose_candidate_kind`, `plan_single`); in shipped itd-80, planning is the native `abcd intent plan` verbrelated itd-44 · related itd-80
- iss-2610262044555198itd-3 explicitly rejects a personal cross-repo ~/.abcd/rules.json; itd-117 ships exactly that user-scope rules filerelated itd-117 · related itd-3
- iss-2610262044561718itd-39 reuses the rules loader's context brackets from itd-3, but itd-3's loader defines no bracketsrelated itd-3 · related itd-39
- iss-2610262044572933itd-39 plans to extend a Python prompt-router hook; itd-105 says the plugin's hooks call the abcd binaryrelated itd-105 · related itd-39
- iss-2610262044580425itd-146 files drain in the person's records group; itd-82 says drain joins the person's list only when itd-82 shipsrelated itd-146 · related itd-82
- iss-2610262044589669itd-146 keeps rules and spec listed so --help matches the marker block; itd-2610090831227812 makes rules and spec agent-onlyrelated itd-146 · related itd-2610090831227812
- iss-2610262044591588itd-24 has the person run /abcd:reflect < tag>; itd-2610090831227812 makes reflect an agent-only page the host refuses when a person types itrelated itd-24 · related itd-2610090831227812
- iss-2610262045007603itd-201 asks which hat the human wears before the mode is set; itd-2609212130146198 refuses every question while the mode reads managedrelated itd-201 · related itd-2609212130146198
- iss-2610262045017395itd-102 records a canonical project title that surfaces derive from; itd-2610031348087517 says nothing in a project derives a title reliablyrelated itd-102 · related itd-2610031348087517
- iss-2610262045024914itd-138's install script ends by running abcd version; itd-2609212130136102 removes that verb in favour of --versionrelated itd-138 · related itd-2609212130136102
- iss-2610262045033573itd-111 names abcd version as where install mode and vintage always show; itd-2609212130136102 removes the abcd version verbrelated itd-111 · related itd-2609212130136102
- iss-2610262045047151itd-122 gives every surface chapter a hand-kept sub-verb table; itd-147 forbids a chapter's hand-written text from stating any sub-verbrelated itd-122 · related itd-147
- iss-2610262045054264The agent that writes per-criterion audit verdicts is the intent-fidelity-reviewer in itd-50 and the intent auditor in itd-24related itd-24 · related itd-50
- iss-2610262045054936itd-187 holds two assemblies byte-identical with only the manifest excluded; itd-2609020625402599 puts a per-run stamp naming the run in every bundlerelated itd-187 · related itd-2609020625402599
- iss-2610262045065649itd-200 keeps the status line's user-level defaults under ~/.abcd/; itd-2610030720038073 makes an existing ~/.abcd stop every abcd commandrelated itd-200 · related itd-2610030720038073
- iss-2610262045072539itd-117 puts the machine's shared conventions in ~/.abcd/rules.json; itd-2610030720038073 renames the home to ~/.abcd.noindexrelated itd-117 · related itd-2610030720038073
- iss-2610262045089996itd-7 has disembark run dev-sync, which writes .abcd/rp/workspace.json into the repo; itd-88 says disembark never writes into the source repositoryrelated itd-7 · related itd-88
- iss-2610262045091104itd-39 extends a Python hook, hooks/prompt_router_hook.py; itd-66 says the payload has no Python and hooks/ ships shellrelated itd-39 · related itd-66
- iss-2610262045100283The prompt router is the Python file hooks/prompt_router_hook.py in itd-39 and the shipped hidden verb `hook prompt-router` in itd-89related itd-39 · related itd-89
- iss-2610262045119850abcd's user-level home is ~/.abcd.noindex/ in itd-39 and ~/.abcd/ in itd-76related itd-39 · related itd-76
- iss-2610262045122268itd-53 calls loop-toward-acceptance a facilitator-elected policy riding on its drainer; itd-50 ruled the loop is build's last stage, not a per-intent moderelated itd-50 · related itd-53
- iss-2610262045126115itd-50 relies on a drainer that runs queued reviews at a safe boundary; itd-53 ruled out any boundary-hooked autodrainrelated itd-50 · related itd-53
- iss-2610262045139907itd-94 has autonomous drain runs implementing intents; itd-82 defines drain as working issues only and leaves picking intents to `abcd build next`related itd-82 · related itd-94
- iss-2610262045146746itd-6 rules out direct provider API integrations and routes everything through RP; itd-166 records model calls made through command-line runners and provider connectionsrelated itd-166 · related itd-6
- iss-2610262045156888The verdict verb is `abcd intent review ingest` in itd-80 and `abcd intent audit` in itd-123related itd-123 · related itd-80
- iss-2610262045168363The agent that grades shipped intents is `intent-fidelity-reviewer` in itd-48 and 'the intent auditor' in itd-24related itd-24 · related itd-48
- iss-2610262045177576itd-6 still calls the lifeboat verdict pass lifeboat-oracle and re-audit; itd-125 renamed it a review so that one word names itrelated itd-125 · related itd-6
- iss-2610262045183188itd-42 defers full-body comparison of intents to itd-39; itd-39 recalls keyword-matched memory pages and compares no intent bodiesrelated itd-39 · related itd-42
- iss-2610262045198472itd-67 picks the release bump by phase-completion detection; itd-24 records that phases are retired and the release is the unitrelated itd-24 · related itd-67
- iss-2610262045199145itd-46 says quoted text alone creates a capture; itd-82 requires a remedy field on every new issuerelated itd-46 · related itd-82
- iss-2610262045201587itd-94 has the agent run `abcd intent ready itd-93` with no other argument and read its verdict; itd-179 makes `intent ready` refuse without a grounds argumentrelated itd-179 · related itd-94
- iss-2610262045214826The lifeboat packer is `disembark pack <repo> <path>` in itd-24 and `disembark <repo> to <dest>` in itd-88related itd-24 · related itd-88
- iss-2610262045222030itd-124 keeps 'audit' for checking a promise and 'lint' for checking form; itd-65 calls its docs-lint row the documentation-auditorrelated itd-124 · related itd-65
- 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 itd-2609020625400194 · related itd-46
- iss-2610262045246595itd-46 lists `ship` and `review` among the intent sub-verbs; itd-121 says shipping an intent is a spec verbrelated itd-121 · related itd-46
- iss-2610262045254107itd-3 has ahoy own a CLAUDE.md marker block; itd-2610030814013772 rules that projects carry no CLAUDE.md at allrelated itd-2610030814013772 · related itd-3
- iss-2610262045266820itd-3 rejects a user-level rules.json outright; itd-2610030720038073 records that every managed project's block names the home's top-level rules.jsonrelated itd-2610030720038073 · related itd-3
- iss-2610262045278708itd-3 ships the prompt hook as a Python file in hooks/; itd-66 says hooks/ ships shell and the payload carries no Pythonrelated itd-3 · related itd-66
- iss-2610262045286894itd-3 names a ROADMAP rule domain and teaches 'draft a milestone'; itd-2609211913453478 retires roadmap and milestone as superseded termsrelated itd-2609211913453478 · related itd-3
- iss-2610262045292501itd-2609221656361680 puts the inbox under ~/.abcd/; itd-2610030720038073 makes an existing ~/.abcd stop every abcd commandrelated itd-2609221656361680 · related itd-2610030720038073
- iss-2610262045296807itd-40 names ~/.abcd/history/index.json as the sole user-scope registry; itd-2610030720038073 renames the home to ~/.abcd.noindexrelated itd-2610030720038073 · related itd-40
- iss-2610262045302788itd-2609231434459890 keeps the load-check limits in a settings file under ~/.abcd/; itd-2610030720038073 renames that homerelated itd-2609231434459890 · related itd-2610030720038073
- iss-2610262045316034itd-2609212137128014 records lab evidence at ~/.abcd/lab/; itd-2610030720038073 renames the home the lab lives inrelated itd-2609212137128014 · related itd-2610030720038073
- iss-2610262045327872itd-34 says shape classification runs continuously in the pre-commit hook; itd-48 defers continuous pre-commit shape scanningrelated itd-34 · related itd-48
- iss-2610262045336833itd-34 has bundle members share an epic_id field; itd-43 says the intent field is spec_id and epic is gonerelated itd-34 · related itd-43
- iss-2610262045343669itd-4's issue schema carries related_epics; itd-43 says the validator uses related_specs exclusivelyrelated itd-4 · related itd-43
- iss-2610262045357230itd-34 maps a standalone intent to a flow-next spec made by /flow-next:plan; itd-80 has intent plan mint a native spc-N recordrelated itd-34 · related itd-80
- iss-2610262045365573itd-6 says abcd never spawns claude -p; itd-2609201916056194 ships a claude CLI print-mode runnerrelated itd-2609201916056194 · related itd-6
- iss-2610262045372683itd-6 rules direct model API integrations out and routes everything through RepoPrompt; itd-2609081951381895 ships an OpenAI-compatible API adapterrelated itd-2609081951381895 · related itd-6
- iss-2610262045379282itd-67 picks the bump tier by phase-completion detection and keeps the version in plugin.json; itd-73 derives it from shipped intents' impact on an unversioned treerelated itd-67 · related itd-73
- iss-2610262045380381itd-67 makes the changelog the reroute target for itd-65's doc-history gate; itd-65 supersedes the reroute wholerelated itd-65 · related itd-67
- iss-2610262045391451itd-2609231013154443 excludes intents with impact: internal; itd-73 defines impact as additive, breaking or fix onlyrelated itd-2609231013154443 · related itd-73
- iss-2610262045409665itd-2609231013154443 names abcd changelog as the read-only preview; itd-2610090831227812 merges changelog into launch with no aliasrelated itd-2609231013154443 · related itd-2610090831227812
- iss-2610262045411383itd-2609212130136102 caps the person's list at fourteen verbs; itd-2610090831227812 rules that neither surface caps itrelated itd-2609212130136102 · related itd-2610090831227812
- iss-2610262045422454itd-2609212103565953 starts each step's lane only after the previous has merged; itd-2609201925079472 runs independent steps' lanes side by siderelated itd-2609201925079472 · related itd-2609212103565953
- iss-2610262045435815itd-2609231434459890 says the pre-push hook runs make preflight; itd-2609091034175565 has the pre-push hook gate on a preflight receiptrelated itd-2609091034175565 · related itd-2609231434459890
- iss-2610262045442294itd-80 names the verdict ingest abcd intent review ingest; itd-2609150819445595 names the same review family abcd intent auditrelated itd-2609150819445595 · related itd-80
- iss-2610262045454143itd-60 attributes decisions and reviews to the maintainer; itd-2609212137129937 retires the word in favour of the two named rolesrelated itd-2609212137129937 · related itd-60
- iss-2610262045459641itd-60 calls the docs-currency lint abcd docs lint; itd-2609212130136102 moves every check under abcd lint, as lint docsrelated itd-2609212130136102 · related itd-60
- iss-2610262045465811itd-60 is sequenced as Phase 8; itd-2609211913453478 retires phases as the sequencing devicerelated itd-2609211913453478 · related itd-60
- iss-2610262045478245itd-4's capture promote calls /abcd:intent new; itd-2609212130136102 removes intent newrelated itd-2609212130136102 · related itd-4
- iss-2610262045489203itd-2609091034175565 refuses any footprint overlap with a live reservation; itd-2610161016394967 lets generated files and a person's own overlap throughrelated itd-2609091034175565 · related itd-2610161016394967
- iss-2610262045493440itd-2609061543533170 makes the site's status page the record health page; itd-2609212103568351 makes it the Now, Next and Later blockrelated itd-2609061543533170 · related itd-2609212103568351
- iss-2610262045503347--release lands a held lane on implement step but gives back a reservation on buildrelated itd-2609091034175565 · related itd-2609201925079472
- iss-2610262045516387itd-2609091416295622 defines peers as a read-only view of this checkout's common dir; itd-2609091034175565 has peers fetch origin and list every person's reservationsrelated itd-2609091034175565 · related itd-2609091416295622
- iss-2610262045524988itd-42 updates a grill SKILL.md; itd-2610090831227812 says abcd ships zero skillsrelated itd-2610090831227812 · related itd-42
- iss-2610262045533651itd-53 calls the owed review a queue entry; itd-80 calls it a parked OWED receiptrelated itd-53 · related itd-80
- iss-2610262045546558itd-2609150819445595 gives the persona Iris the technical facilitator's role; itd-2610090831227812 says the registry picks the name from the role, Iris being the product thinkerrelated itd-2609150819445595 · related itd-2610090831227812
- iss-2610262045552105itd-46 lists ship as a live intent sub-verb; itd-2609111003026787 holds intent ship for a cyclerelated itd-2609111003026787 · related itd-46
- iss-2610262045557535itd-2609211913453478's record-families page has a row for step; itd-2609212103565953 says a step is a section, not a record familyrelated itd-2609211913453478 · related itd-2609212103565953
- iss-2610262150120055The brief's 00-meta.md states as current fact that /abcd:embark reads a lifeboat and writes a new repo's brief by walking the brief-lifeboat mapping in reverse, with the amended press release becoming the new repo's initial brief. Shipped embark does no such thing: internal/core/lifeboat/embark_types.go classes every brief/** file of a lifeboat as report-only (IgnoredReportOnly, reportOnlyPrefixes), never written into a target. The reverse walk is a design target, so the sentence is a staged claim written in the present tense, and it misled a session into telling the product thinker that every managed repository's brief is written from the lifeboat's shape.
- iss-2610262154123870abcd ideate record has no field for the reframing a reframed verdict carries. commands/ideate.md says a reframed idea's graduation 'carries the reframing recorded in leg 3, not the original wording', and the verb's own next line says the same, but the verdict document (internal/core/ideate/ideate.go) holds only claims, hits, kill attempts with an outcome, the verdict and rejected alternatives: the reframing has to be smuggled in as a kill attempt marked survived, which a later reader or a graduating intent cannot find by its role.
- iss-2610262155232329A load-gate slot held by a run that has stopped using the machine is never released: a holder that hangs or idles keeps its slot until its own timeout, and every other waiter waits behind it (part of the remedy of iss-2610241414124940, split out of itd-2610262127138979 at its planning on 2026-10-26, because whole-run admission does not decide it). Admitting a run on the headroom it will need rather than the load at one instant (part of iss-2610241911052191) moves with it to the adaptive count, itd-2610262141001890.
- iss-2610262205347315The status bar shows no session name (Alice, Bob, ...) although itd-2610111707085098 shipped it in v0.15.1: the product thinker asked on 2026-10-26 for the name to be on the bar. The renderer works: the installed v0.15.1 'abcd statusline', fed a payload carrying session_name 'Alice', renders 'abcd-managed · Alice · abcd · main · ...', and without the field it renders no name. So the live bar lacks the name because the payload the harness hands the status line carries no session_name for these sessions (the field abcd reads may not be the one the harness sends), and sessions started before v0.15.1 never took a persona name at all (they list under names like abcd-0d, while sessions started since, such as Frank and Grace, carry persona names).
- iss-2610262219309883The shell guard reads a syntax check of a script, bash -n <file>, as running it: abcd guard check --command 'bash -n .githooks/commit-msg' judges the hook's every line as a run would, and refused the check outright once one line of the hook read as a hazard (script-runs-hazard), though bash -n executes nothing.
- iss-2610262219399974In .githooks/commit-msg, a top-level line 'if git rev-parse -q --verify MERGE_HEAD >/dev/null 2>&1; then' placed after the hook's RS004 setup made the guard's script reading block the hook's later '"$go_bin" build -buildvcs=false -o "$work/abcd" ./cmd/abcd' line as kill-by-holder (a program name from a command substitution reading as a refused command), where the hook without that line reads as a warn only. The same if without the redirection, or the check read into a variable first, reads as before; a six-line script holding only go_bin, that if and the build is allowed, and respelling is_scissors without && inside [[ ]] does not clear it, so the earlier context that triggers it is not isolated.
- iss-2610262229344994The shell guard's forge-text check reads a short text flag only from the second character of its word (forgeFlag, internal/core/guard/forge.go), so gh pr create -db 'text', pflag's cluster of --draft and --body, posts a body the check neither judges nor marks as unread.
- iss-2610262229350942gh pr create --fill, --fill-first and --fill-verbose have gh compose the title and body from the branch's commits, which the shell guard's forge-text check neither judges nor reports as unread, so a body the attribution gate refuses after the push is posted with no warning.
- iss-2610262229362789abcd land rewrites its composed body file under .abcd/.work.local/scratch/land/ on every run, so a person who edited the body before running the printed gh pr create command, then ran land again, loses the edit without a word.
- iss-2610262259078996The preflight's govulncheck scan warns, rather than stops, on a finding when the branch changes neither go.mod nor go.sum, taking that to mean the finding stands on the default branch; govulncheck judges reachability, so a branch that adds a call newly reaching a vulnerable symbol in a module already required is only warned about, and with govulncheck not a required check its pull request can land with the finding.
- iss-2610270257082620TestTheStoredLineReadEndsWithItsContext (internal/gitutil/stored_each_test.go) required the stubbed git to have run exactly once. Its first read has a 300ms deadline, and on a loaded machine that deadline passed before the stub wrote its run marker, so the test counted 0 runs and failed a preflight whose change touched no gitutil code (fix/fork-approval-mirror, 2026-10-27).
- iss-2610270659564789Two abcd implement load --wait waiters in one copy renew the same reservations at once, and the one that loses reports each loss as a fault. On 2026-10-27 at 01:51Z a preflight's waiter and a gated test run's waiter, both in one worktree, renewed the same five reservations together. One renewed all five. The other logged 'could not renew your reservation' for each, four of them as origin refusing a non-fast-forward reservation push, and the fifth as 'its latest commit is not one this copy pushed, so it is not renewed from here', though this copy had pushed that commit seconds before. Nothing lapsed, but the lines read as a reservation at risk and the last one names the wrong cause.
- iss-2610270815076960CI's Linux check job runs within about two minutes of its 30-minute timeout, so a branch that adds tests can be cancelled with no test failing. On 2026-10-27 the two successful Linux check jobs before 07:00Z took 28 minutes each, their race stage over internal/ about 25 of them. Pull request #1147's job was cancelled at 30m16s while its race stage was still printing results, though every gate and the race run had passed in make preflight. A cancelled required check costs a rerun, and the merge-queue entry runs the same job under the same limit.
- iss-2610270934594826abcd drain --unskip names the wrong thing when the issue it is given is held back by a path: with internal/core held back, --unskip iss-A for an issue whose found_at lies in internal/core says iss-A was not held back, while the same move lists iss-A among the held-back issues (applySkips in internal/core/implement/loop/drain_skip.go). The command that would lift the hold, --unskip internal/core, is still shown, so nothing is lost, but the summary line is false. Found by the round-2 ruthless review of itd-82 lane-1 (build/run-2610260500113538-lane-1).
- iss-2610270935000288abcd drain --unskip given alone, on a drain that has ended, begins a new drain: the skip list is applied after a finished drain's state is reset, so a command meant only to lift a hold starts a drain run the person did not ask for. Found by the round-2 ruthless review of itd-82 lane-1 (build/run-2610260500113538-lane-1).
- iss-2610271115000748Filing every minor editing inconsistency as an issue costs far more than fixing it where it is found. The 2026-10-26 consistency pass filed 1301 records from 1307 findings. Its triage then found 584 of them to be one-passage edits with a known fix, 648 to need no change at all (duplicates, conflicts a later record already settles, or no real conflict), and only 69 to need a person's ruling. Every one was filed, read by a triage agent and approved, and the edits still have to be made: work an in-place fix at discovery would have done once, with none of the noise. The product thinker's lesson (2026-10-27): a minor editing inconsistency should become an issue only when it cannot be fixed in place, because it needs a ruling, crosses a boundary the finder may not change, or is too large for the change at hand. Otherwise it is fixed in place as it is discovered.
- iss-2610271913060860The footprint of spc-2610262202438999 lists only Go packages, yet its Approach rewrites the Makefile's preflight target and edits AGENTS.md. A build reserves the footprint alone, so it does not hold those files, and its refusal on 2026-10-27 named only the overlap on internal/core/rules while two live reservations of the Makefile went unnoticed. Nothing compares the files a spec's Approach names with its footprint, so a build can start against a peer that is editing the same file.
- iss-2610272027437423abcd's ruthless reviewer definition tells the reviewer to run the project's test and lint commands, and the docs-currency reviewer to run the tests that pin documented behaviour. On a machine several sessions share, every review then runs a go test that no load gate admits, beside the preflight the gate did admit. On 2026-10-27 the reviewers of three lanes did so: lane D's at 19:22Z, when the one-minute load reached 71.96 on 16 cores and then 97.61 at 19:24Z; lane C's at 20:26Z, at a load of 60.32; and lane A's step-1 review of the merge gate. Each of those times, the admitted preflight's test stage was running at go test -p 16. A reviewer reads a copy and judges it; the test run is the preflight's job.
- iss-2610272041031418A context-bound git read can fail on a loaded machine after git has already answered: isolatedGitContext (internal/gitutil/repo.go) sets WaitDelay to 50 ms whenever the context can end, and exec starts that timer when git exits on its own, so the copy of git's output can miss it and Wait reports exec.ErrWaitDelay over a successful git. The status reader runs under a deadline, so on 2026-10-27 TestADoubtfulAnnouncementIsFlaggedAndEveryOtherBranchStillRead (internal/core/claim/status_test.go:300) failed a records-only preflight with 'reading the status branches: exec: WaitDelay expired before I/O complete', and in use the prompt hook would print 'status unavailable' for the same reason. The fix for iss-2610100846469473 removed the delay only for callers with no deadline.
- iss-2610272112319234A bare abcd ahoy worktree prune reclaims a merged, clean worktree without saying that the files git ignores outside the local tier go with it: the tier is archived, but an ignored .env.local, local database or nested checkout is deleted unarchived and the row reads reclaimed. Only a quiet candidate's dossier names them. This matches git worktree remove's own judgement, which the spec adopts on purpose.
- iss-2610272126405270The sweep's probe takes the unfinished build runs as ProbeOptions.Runs, a plain list with no error: a front door that reads the runs and swallows a read failure passes an empty list, and the run proof then silently holds nothing, so a worktree a crashed-but-resumable run names could be reclaimed.
- iss-2610272213410875The layered configuration reader silently ignores a misspelt namespace at a file's top level, such as facilitater for facilitator, or one padded with whitespace: only a claimed namespace's own spelling, its case twins and its dotted form are refused, because nothing claims a file's top level. So a person who writes {"facilitater":{"mode":"human"}} in the machine file is outvoted by a repository's auto with no word, and the same holds for every claimant's namespace. Found by the review pair of the merge gate's step 1 on 2026-10-27.
- iss-2610272352153282abcd peers names one sibling worktree two ways in a single listing: a reservation row and the ceiling show its folder name (siblingCopies, a capped worktree listing excluding this copy by key), while a release hold or refusal from the same worktree shows its full home-redacted path (siblingCopy, an uncapped streamed listing excluding this copy by path), and a copied worktree reads as 'lane-c or lane-d' on one side and whichever path was found first on the other
- iss-2610272352168723Two sibling worktrees whose directories share a name and a parent's name (x/a/lane-b and y/a/lane-b) both read as 'a/lane-b' in abcd peers, and the ceiling counts them as one sibling 'a/lane-b' with both holds: the total stays right, but which worktree holds what is lost
- iss-2610272352179242The live-reservation cap refusal drops the reason the sibling worktrees could not be listed (Snapshot.SiblingsUnread), so a sibling's hold is grouped under elsewhere with no word why, and its copy labels are keyed by record id with no holder or live-state filter, so another holder's tip on the same record could relabel the reader's own
- iss-2610280032429024abcd reserve refuses a footprint whose reservation message passes the 4096-byte cap, and takes only an explicit list of paths, so a large stacked build cannot name its whole diff: renewing the worktree store's reservation after a rebase with its 83 changed paths was refused at 4740 bytes, and the renewal had to fall back by hand to the store's original 50 paths, leaving the rebased-in paths unreserved.
- iss-2610280051498465A file an agent writes with the host's own edit tools into a main checkout two or more live sessions share is not refused. On 2026-10-28 the record writers (capture, intent, decide, spec close and the index generator) began refusing a shared main checkout through a per-session occupancy marker (iss-2610240859590333), but an agent's direct Write or Edit of a record file, or of any tracked file, goes through the host's file tools, which the shell guard never sees. The 2026-10-24 incident used the verbs, so the verbs were closed first; the same mistake made with the file tools lands the same way.
- iss-2610280103486084A tracked embargo state file pre-seeds a new embargo store, letting a planted entry exempt an advisory from the check
- iss-2610280103488091Graveyard lessons are written into a packed lifeboat without the secret scan pack applies
- iss-2610280103488668The external-review check runs the fork's own copy of itself on a pull_request_review event
- iss-2610280103491547abcd reserve pushes a reservation naming an embargoed record and its footprint paths to origin
- iss-2610280103491905A new tag on an old main commit passes release provenance, rolls installs back and freezes updates at the raised mark
- iss-2610280103492687The rules session ledger falls back to a predictable shared temp path another account can plant
- iss-2610280103493414Scanner reports a multi-member gzip as fully decoded while later members' header fields go unscanned
- iss-2610280103495259A committed identity.json symlinked to /dev/zero hangs the session-start hook in an unbounded read
- iss-2610280103498613The native secret patterns miss several prefix-anchored vendor tokens, which capture writes into the committed ledger
- iss-2610280107422462Every records pull request that adds, plans or moves a draft intent rewrites the generated drafts index in .abcd/development/brief/06-delivery/03-out-of-scope.md, so two such pull requests open at once conflict as soon as the first merges: their insertions into the sorted one-per-line list land in neighbouring lines. On the night of 2026-10-27/28 it happened three times, #1131 against #1147, #1162, and lane E's rebase, and each was fixed by hand by merging the default branch, taking its side of the region and running go generate again. The forge applies no merge driver (iss-2609240646538011), and no verb regenerates the region when it files a record (iss-2610241256347199).
- iss-2610280910566850An intent build re-widens its reservation to the spec's whole footprint at every step, instead of reserving only the packages of the lanes it has open. A spec footprint that names whole packages (or the whole of commands/) then overlaps peers' narrow file reservations, so the build's renewal at land is refused until the peer releases by hand, and a hand-narrowed reservation is widened again at the next step. Seen 26-28 Oct on run-2610252354599453: a peer's commands/land.md and commands/guard.md reservations blocked lane 1's renewal.
- iss-2610280910599224When implement load --wait gives up at its timeout inside a make recipe, the log ends with only exit status 1 after the waiter's last status line, which can be hours old, so a session sees a failed gated run with no cause named. Gated runs timed out after 2-3h on 27-28 Oct showing nothing more.
- iss-2610280911205938Re-running abcd reserve <id> --footprint X on an id already held replaces the held footprint with X instead of adding X to it, so extending a reservation path by path silently drops the earlier paths and leaves them open to peers. Two sessions met it on 27-28 Oct and had to re-reserve with the full list in one call.
- iss-2610280911221843abcd reserve --release run from a worktree other than the one that made the reservation is refused as held by your copy on another computer, though the holder is the same account on the same machine. Once that worktree is removed its reservations can only lapse. Two sessions met it, 25-28 Oct.
- iss-2610281259462058Closing a Claude Code session shows: SessionEnd hook [sh "${CLAUDE_PLUGIN_ROOT}/hooks/session-end.sh"] failed: Hook cancelled. Seen by the person on 28 Oct 2026 while closing several sessions at a 1-minute load near 290 on 10 cores, with the plugin still at 0.13.3. Each cancelled hook means that session's transcript was not staged. The fix for the cancellation is on fix/session-end-stage (iss-2610241519088123: the hook runs no git and only stages the raw transcript), but it reaches this person only after a release and a plugin update, because the installed plugin is 0.13.3 while v0.15.1 is released (iss-2610241228359748, which copy runs).
- iss-2610281328229800The drain should start by itself whenever a runner with an API key and remaining credit is available, and pause by itself when that credit runs out, picking up again once the account is recharged. Today a run that hits an exhausted balance stops, and a person has to notice and restart it. The build loop already ends a window early on a rate-limit response and writes next_eligible_at, and its budget check asks each runner for its remaining quota, but nothing treats an exhausted balance as a pause that ends when credit returns, and nothing starts a drain when a funded key appears. Raised by the product thinker on 2026-10-28.
- iss-2610281338119523TestAFullPageOfTheForgesRecordKeepsNoMarkForWhatItDidNotCover (internal/surface/cli/status_forge_page_test.go) fails when the machine is slow enough. It runs abcd status with the production budget for each forge lookup, and in a preflight's race stage on 2026-10-28, at a one-minute load near 180, a git rev-list ran past that budget. So the reply said the forge's record was not placed in full, where the test wants it said to be read in part. The branch under test changed only records, and the same test passed in the stage before.
- iss-2610281402204506The site's history pass dates a record from every commit it walks, branch sides included, and reads a merge commit's diff against its first parent. A branch that merges main the usual way, with the branch as first parent, so carries a commit whose diff shows every record main moved since the branch was cut, dated the day of that merge. Once such a branch lands, those records read as having entered their folders on that day. The home page features the most recently shipped intent whose audit is met, so the featured quotation can change for reasons the landing diff does not contain, and the site's banned-token gate then judges a different press release. On 2026-10-28 an unpushed merge of main into the ideate-librarian bundle branch, from 23 Oct, re-dated main's shipped intents. That made itd-2609091034175565 the featured intent, its press release tripped present_tense/no-longer, and site-render failed on a branch whose diff touched no shipped intent. The branch was rebuilt with main as the merge's first parent and passed.
- iss-2610281502581386On 28 Oct 2026 the development machine's data volume fell to 658 MiB free of 926 GiB and a peer's verify failed with No space left on device. The Go build cache had grown to 177 GiB: every store worktree, race build and pinned-toolchain build adds entries, and Go trims only entries unused for five days, so days of many-worktree autonomous runs fill the disk, and every preflight on the machine then fails or writes truncated files with no gate naming the cause. Entries unused for two days (79 GiB) were deleted by hand.
- iss-2610281503005495On 28 Oct 2026 one login reached reservation.max_live (40 of 40) with every hold live and in use: 24 from 15 store worktrees on this machine and 16 from the person's other machine, all counted against the one total. A new pre-cut fix's reserve was refused (exit 2), and the cap was raised to 50 by hand in the machine config. Two machines' autonomous runs under one login share a ceiling that neither machine can see the other's share of.
- iss-2610281718353935Publishing a release waits for a person to approve the release environment's pending deployment. The product thinker ruled on 2026-10-28 that publishing a release and deploying the site run with no approval step by anyone, so the reviewer on the release environment, and every description of it, no longer matches what the project wants.
- iss-2610281719275461A released reservation branch, one whose tip is a plain release commit, waits seven days before the daily reservation sweep deletes it, so spent branches pile up on the forge for a week after the work was handed in. The product thinker ruled on 2026-10-28 that such a branch is deleted at the next daily sweep run instead, keeping the sweep's other safety rules.
- iss-2610281753392222Site deploy can run an unreviewed commit's build configuration with the deploy credentials
- iss-2610281754577313abcd site setup creates the site-render and site environments admitting the default branch and v* tags, and the site workflow it writes also runs on a published release. The intended contract is that both environments admit only the default branch, and that every run of the site workflow starts from it.
- iss-2610282016250805The load gate leaves the machine idle: a make preflight queued at its race gate still counts as Busy at the first gate, so with load.preflights=2 one preflight running its race stage and a second waiting idle at the race gate fill both slots and every other preflight waits. Observed 2026-10-28 20:02-20:15Z: four preflights queued, one test stage running, load 13 on 16 cores. MaxPreflightSlots also caps the setting at 2.
- iss-2610282035340363The macOS leg of the check job in ci.yml cancels merge-group runs at its 70-minute ceiling: on 2026-10-28 run 40752008734 (PR #1196's merge group) had check (macos-latest) cancelled after about 71 minutes, from 19:11:30Z to 20:22:05Z, and the queue dropped the group with failed_checks. That day's passing merge-group runs took roughly 46 to 68 minutes, so the leg runs near its cap and each cancel rebuilds every group queued behind it. The lasting remedy is a faster suite (iss-2610181711260494, resolved by the raise to 70, which named a faster race pass, iss-2610181757540736, as the longer lever).
- iss-2610282209509491A drain trusts a run-state file that a repository's own history can supply
- iss-2610282211249070abcd reads the files of its per-checkout local tier (.abcd/.work.local/) without checking that git does not track them. The tier is this checkout's alone and is ignored by design, so a copy of one of its files that a commit carries is not this checkout's state, yet it is read as if it were.
- iss-2610282340087862abcd reserve lets a footprint path through when it is a file origin's default branch declares generated, but says nothing about it: a person reading the reservation cannot tell that it shares docs/reference/cli/commands.md with another live reservation, which the second lander must regenerate after merging main. The act names a shared path only when it backs off, warns of the person's own other copy, or cannot read the declaration.
- iss-2610290033556553The load.preflights setting is described as how many preflights may be in their test stages at once, in its refusal, the help, the command page, the bundled LOAD rule and the code comments, but since iss-2610282016250805 a preflight queued at its race gate takes no slot, so a race stage can run beside as many unit stages as the setting: it bounds what the first gate admits, not what runs. The configuration chapter of the brief still says the setting takes 1 or 2, where 4 is now the most.
- iss-2610290504257814abcd embargo check --range reads a merge commit against its first parent, so on a branch that merged the default branch every line the merge brings in from it is judged as the branch's own: text already public on the default branch is refused, including the id of an advisory this repository has already published, which the store need not hold. Two sessions met it on 2026-10-29 and had to check around the merge by hand.
- iss-2610290507512835abcd reserve over this copy's own live reservation writes the new --footprint in place of the held one, so a path the held footprint named and the new one leaves out stops holding off peers, and nothing says it was dropped.
- iss-2610290507514841abcd reserve keeps a footprint path named twice: each --footprint is written as its own Abcd-Footprint line, so a renewal script that passes the held footprint again plus the new paths grows the message with repeats until it passes the 4096-byte cap and the renewal is refused.
- iss-2610290507526253The own-copy overlap warning of abcd reserve says only that the person holds the other record from their other copy, never which copy: a lane reserved over files a copy on another computer held with no sign the other work was elsewhere, as both lanes and the laptop's files read alike.
- iss-2610290709017008A session start says nothing when the installed plugin is older than the newest published release, so a fix that has shipped (such as the SessionEnd staging change) never reaches a person whose plugin did not update, and nothing tells them to update. The start-of-session notice that exists compares the plugin surface with the binary serving it, and only reports a plugin newer than its binary; asking for the newest release is left to abcd update --check alone, which a session never runs.
- iss-2610290717018523The load gate now refuses a test stage when the volume holding the Go build cache or the worktree store has less than its floor free (iss-2610281502581386), but nothing keeps the cache from growing back. Go trims only entries unused for five days, and every store worktree, race build and pinned-toolchain build adds entries, so a machine running many worktrees for days still fills its disk and then stands until a person trims the cache by hand; on 29 Oct 2026 the cache on the development machine had grown back to about 291 GiB. The first issue's remedy also asked the worktree store's reclaim to trim cache entries older than a day when it removes worktrees; that was left out of its fix because abcd deleting another tool's cache is a trust change that needs its own decision.
- iss-2610290720087336CI's macOS check runs internal/core/implement/loop as one test process under -race, and it now takes most of the step's 40-minute budget: 2244s on a passing run (Actions run 40821104565), and on 29 Oct a queue entry for pull request 1201 timed out on it (run 40825987527) with no test hung, dropping the change from the merge queue. Preflight already runs the three longest packages as three processes each through internal/testshard (ABCD_TEST_SHARDS=3); CI sets no shards, so every queued change risks the same timeout.
- iss-2610290730196083Private and unfinished work cannot move between accounts or computers. Private lab sessions and ideate verdicts live only in the running account's own owner-only stores (~/.abcd.noindex/lab/<root-sha>/ and ~/.abcd.noindex/ideas/<root-sha>/). Unfinished work lives in local branches and store worktrees: commits not yet on origin, uncommitted diffs, untracked files and each worktree's local-tier notes. A person who moves to a second account or computer, or hands work to a colleague's account, can carry none of it over except by hand: a git bundle of the branches, a patch and a tarball per dirty worktree, and a hand-written status table and handover note saying which branch is which and what comes next. That route skips redaction, integrity checks and the owner-only modes the private stores rely on. It also says nothing about what cannot travel: preflight receipts, implement-loop run state and reservations held by the old checkout. On the receiving side nothing ingests the material, so later lab, ideate or build runs there cannot read it, and it does not stay private by default.related itd-2610290858096130
- iss-2610290730539347Nothing limits who may make a private lab or ideate verdict public: once a promote path exists, any account able to run it could move private material into the committed research store. A check inside abcd alone cannot hold, because a contributor controls their own machine and can copy the files by hand; the boundary that holds is the forge, where only an account with write access can merge. A contributor's pull request is also public the moment it is opened, before any review, so the forge keeps such material out of the project's record but cannot stop a contributor disclosing it there.blocked by iss-2610170717491755 · related itd-2610290858115394
- iss-2610290741142392A branch cleanup keeps no backup of what it deletes in a place abcd manages. The product thinker decided on 2026-10-29 that the backup taken before a cleanup is kept on purpose in a store of its own under ~/.abcd.noindex/backups/, keyed on the repository's root commit like abcd's other machine stores, so it lasts beyond the cleanup and can be cleared away later, for instance once it is thirty days old. Today no such store exists: an unmerged branch the cleanup removes survives only as long as git's reflog keeps it, and nothing names where to find it or when it goes.
- iss-2610290748300390A managed repository with no CI workflow gets no required status check from abcd ahoy remote apply (itd-2610290746077716), because no workflow reports one. iss-2610121535283764 proposed that abcd offer such a repository a minimal starter workflow, gitleaks plus abcd lint, and then require those checks. That was split out of itd-2610290746077716 because nothing in abcd writes a CI workflow yet. A correct one needs a gitleaks binary pinned by version and verified by checksum (the gitleaks Action needs a paid licence on organization repositories), abcd itself installed and verified in CI, and every action pinned by commit SHA so it passes the SHA-pinning baseline it would sit under.
- iss-2610290750089812When load.preflights is lowered to one while two whole runs are admitted, the race gate's at-one shortcut opens for a run that is waiting behind the other's live race run, so two race stages overlap. At two slots, runs A and B are both admitted. A is in its race stage, and B waits at its race gate because A's race run is live. The person lowers the count to 1, and B's race gate opens at its next look. The shortcut assumes a first gate that admitted this run alone, which no longer holds for runs admitted under the higher count. Lowering the count is meant to reduce load, and here it does the opposite. The spec of itd-2610262127138979 asks for this shortcut, and TestWaitRaceGateOpensOnceTheCountFallsToOne asserts it.
- iss-2610290755587946abcd ahoy remote apply (itd-2610290746077716) reports a missing or partial CODEOWNERS file as advisory and does not write it. Whether a managed repository keeps a CODEOWNERS file at all is now part of the maintainer-gate record iss-2610290730539347, which is not yet on the default branch. A maintainer is anyone with Write access or above, and GitHub counts approvals only from those, so the approval gate does not depend on CODEOWNERS naming a team. <!-- record-lint: forward-looking -->
- iss-2610290809526033Reservation and announcement commits that abcd pushes to origin name the holder by their forge login: the Abcd-Holder and Abcd-Sender trailers carry it, and the announcement branch is named after it, so every reservation publishes which account made it in text and in the branch list.
- iss-2610290811187925abcd should help the technical facilitator of every abcd-managed repository set up the same personal-identifier protection this repository now has, as easily as possible. That means: no org member's login or name in any tracked file or anything abcd pushes or publishes (records, fixtures, credits, the site's contributors page, reservation and announcement trailers and ref names), with commit author fields left as the person's identity; code-owner sign-off through an org team rather than named people; test fixtures that use the standard abcd personas from .abcd/development/personas.json instead of invented or real names; and a private-names list that always and automatically includes the machine's names, its local user accounts and the org's members and collaborators. Today each of these was set up by hand in one repository, and a managed repository gets none of it.
- iss-2610290855523061Tracked files name the organisation's members and collaborators: about 63 files carry a member's GitHub login or display name, in credits, the plugin manifests, the code-owners file, the mailmap, the committed identity pin, test fixtures, attribution cases, research notes and records. The product thinker ruled on 2026-10-29 that a login appears only in commit metadata (the author and committer of a pushed commit), never in the content of prose or code, and that people are named by role. The one exception the product thinker kept is the copyright line in LICENSE, which still names its holder.
- iss-2610290913450522The settings baseline requires each status check from any source. GitHub lets any person or integration with write access set the state of any status check, and the statuses API lets a push-access token post any context, so a required check left on any source can be set to passing by someone other than the workflow that runs it. Choosing the app as the source refuses a status set by anyone else. Assessed against the abcd-fixes-what-it-adds principle: the route exists without abcd (it is GitHub's default for any required check), and abcd's apply adds no weaker state, since without it the repository requires no check at all; pinning is a tightening of a setting abcd itself writes, applied only on the person's yes, and changes nothing else about how the repository works. No released abcd has ever applied a required check: the apply that writes one ships for the first time in the change itd-2610290746077716 delivers, so abcd has put no managed repository in this state.
- iss-2610291028185585The website abcd builds for a repository names every human author on its contributors page, with a forge profile link built from their noreply address, which carries their login. The product thinker ruled on 2026-10-29 that no member's login or name appears in what abcd publishes: credits name no person. The page reads git shortlog and prints each author's name and commit count, and the record JSON beside it carries the same fields, so every site abcd builds publishes its contributors' names.
- iss-2610291130262302The retrospective seed counts an intent whose fidelity review was dead-lettered as audited, and offers no audit for it, while the list of reviews owed reports the same intent as unreviewed with its reason. A review that never landed reads as an audit in one reader and not in the other, which runs against the rule of 29 October that both readers judge audited by one rule.
- iss-2610291509190406An announcement on a status branch named by a holder id always shows its sender as claimed: abcd no longer asks the forge who pushed it, because a holder id names no account the forge's record could match. So a later commit on that branch from a different pushing account looks the same as the branch owner's own, where on a branch named by a username the forge's record could mark it doubtful. Nothing acts on the sender check beyond what status, peers and the prompt hook display.
- iss-2610291946475029Twenty-one test packages depend on internal/core/github but have no TestMain hiding the machine's gh login: afterupdate, ahoy, autonomy, capture, embargo, github, ideate, implement, lifeboat, reading, record, release, repolint, report, reservesweep, scribe, site, sweep, update, surface/session and surface/session/web. A test in any of them that reaches the forge reads the developer's real login and tokens, so it can pass locally and fail on CI, which has no login, as the landing body test did in the merge queue for #1147.
- iss-2610292103069395abcd ahoy --remote names the missing scope and the command that grants it only for the organization's Actions policy. The fidelity review of itd-2610290746077716 (rcp-6083de2cef52, ac-8 met with concerns) found that a 403 or 404 on a repository settings read says the sign-in needs admin rights on the repository but gives no command or next step (internal/core/ahoy/remote_baseline.go:459). A failed read of the owner's plan returns an empty plan and no reason at all (remote_baseline.go:478), so the person cannot tell why the plan-dependent settings read as they do.
- iss-2610292103119559abcd ahoy --remote can report the SHA-pinning advisory without its count of unpinned uses. The fidelity review of itd-2610290746077716 (rcp-6083de2cef52, ac-9 met with concerns) found that when any workflow or local action went unread, the switch takes the unread branch before the count branch, so the advisory names what was unread but drops the count of tag-referenced uses abcd did read (internal/core/ahoy/remote_baseline.go:913). An Actions answer that carries no sha_pinning_required field reads as unknown before the workflows are looked at (remote_baseline.go:911), so a repository with unpinned uses gets no advisory at all there.
- iss-2610292103166339abcd ahoy --remote decides that a setting is owed by the plan from the repository being private or internal and from GitHub's refusal text containing the word upgrade, not from the owner's plan. The fidelity review of itd-2610290746077716 (rcp-6083de2cef52) found its scope condition cond-2610290749118129 (a setting the plan or the visibility does not offer is reported as owed) narrowed: a refusal GitHub words any other way reads as unknown, though never as a failure (internal/core/ahoy/remote_baseline.go:452, remote_baseline.go:236). iss-2610161632245527, which asks abcd to probe what the forge allows before picking a route, is the wider form of this.
- iss-2610292237259195embargo check --range flags advisory-shaped ids that the default branch already carries once a branch has merged the default branch in, though the branch's own changes add none. The merge commit itself is not the cause: mergeAdds keeps only lines the merge adds against every parent. The likely cause is the range's commit list: rev-list a..b lists every commit reachable from b and not from a, so with a base older than the merged default branch, that branch's own commits brought in by the merge are judged as the branch's.
- iss-2610292307181518A bounded git commit whose hook never finishes overran its stop by far more than its design allows. In a preflight's race stage, TestAPickCommitAndASyncMergeWhoseHookNeverFinishesAreRefused (internal/core/implement/loop/pickgit_deadline_test.go:105) failed: the pick commit, under a 1s deadline with a pre-commit hook that execs sleep 60, came back after 49.7s against the test's 20s bound, while the worst stop the code allows is about 21s (the 1s limit, a process-table read under its 5s cap, the 5s WaitDelay, then the descendant sweep's 5s grace and its reads of up to 5s each). The plain test stage passed the same package in the same run. The five-minute load was about 280 to 340, mostly Spotlight indexing and a sync client rather than the tests, on 16 cores. An unproven hypothesis: under that load git forks the hook after Cancel has taken its snapshot of git's descendants, so the sleep is outside the set the sweep signals and kills, and something else holds the run until the sleep nears its end. The overrun is in a test bound; no user path that hangs has been shown yet, though abcd implement step runs pick commits through the same call.
- iss-2610300120250873A rules domain points at its home with a bare repository path, and nothing checks that the path still resolves. The link check reads markdown links only, and the one test that reads an OPINIONS path checks the users-directory principle alone. So renaming or moving a principle leaves its OPINIONS rule pointing at a file that is gone, the loader keeps injecting the dead pointer into every matching prompt, and every check stays green.
- iss-2610300838089246/abcd:ideate asks private or public before every run, and its record verb refuses a run that names neither. The product thinker has ruled that ideate defaults to private and does not ask.
- iss-2610301026198794When git's identity in a session is not a person's, abcd authors and commits each reservation and announcement commit it pushes as the account the forge token resolves to, with that account's login and no-reply address, so those commits' author and committer fields carry the login that the holder id keeps out of every trailer and ref name. That is the stated exception for the release bringing the holder id; the follow-up is an author identity for those commits that the human-author attribution gate accepts and that carries no login.
- iss-2610301246136766RS006 in scripts/check-issue-resolution.sh reads a test name out of any word that contains Test followed by a capital, so a resolution naming a function such as GoTestTimeout is refused as naming a test no _test.go file defines. It refused the load-scaled-timeout resolution, which named machineload.GoTestTimeout, on 30 Oct 2026; the note had to be reworded to pass.
- iss-2610301320457709abcd has no machine-readable list of its verbs: abcd --help --agent --json ignores --json and prints the text menu, so an agent learns the verbs, their flags and how to call them only by parsing help prose or reading every commands/*.md page. The list must be built from the same source as --help --agent and must carry machine-readable instructions for an agent to use abcd.
- iss-2610301330557789AGENTS.md says a commit or push never skips the repository's hooks, but in this repository the guard refuses the hook-skipping flag only on git commit and git push. git merge, git rebase, git am and git pull each take the same flag, and the guard allows all four, so for those verbs the rule is prose alone.
- iss-2610301822150004abcd has no comprehensive, deterministic system for acknowledging prior art. ACKNOWLEDGEMENTS.md is one hand-edited file that many agent sessions append to at once, so it conflicts on merge (the one-writer-per-file principle names a multi-writer single file as a merge hotspot), and nothing decides what qualifies for an entry: on 2026-10-30 three intents' cited papers and tools were found never credited. The product thinker proposed one file per acknowledged source in a folder under .abcd/development/, a root file regenerated only when a release is cut, and clear deterministic rules for what qualifies. The state-of-the-art check of 2026-10-30 (.abcd/development/research/notes/2026-10-30-acknowledgements-sota.md) supports all three, with one change: the root file should be a real generated file, not the proposed symlink, since Go module zips omit symlinks, core.symlinks=false checks them out as text, and GitHub and GitLab show the link path instead of the content. Related: itd-163 (citation closure and the acknowledgements mirror gate), itd-126 (one shared bibliography).
- iss-2610301855200679A question that breaks abcd's asking rules still reaches the person as an error, after the product thinker asked several times for it to stop (2026-10-30, and before in iss-2610230745597968). In one planning interview the abcd:question-drafter returned a refusal for 3 of 10 drafts because the quoted material and its options did not fit the 24-row limit for one decision; the calling agent then put over-limit questions to the person itself, and once skipped the drafter altogether, so the question check blocked the question in front of the person (no Decide later option, 28 rows). Three gaps let this through: the drafter may give up and hand back a refusal instead of working until its draft passes; it counts rows by its own reckoning rather than through abcd's check; and nothing makes the calling agent ask only a question that passed, so the hook's refusal is the first check the question meets, and the person sees it. The product thinker's proposal: a sub-agent keeps working on the question until it conforms, and only then is it put to the person.related itd-2610230756259215
- iss-2610301916124914The setup command page and the identity brief chapter describe behaviour the binary does not have. The page names a later verify step that reads the GitHub settings mirror, but no verb reads it beyond one field. It tells the identity migration as a change in the past tense, and leaves out what blocks the move. The page also leaves the shell-settings line out of what uninstall removes, and states the copy of the shell file and the workflow filters without their conditions. The brief chapter ends with a clause of history.
- iss-2610301918307812Four brief sentences for shipped intents describe a plan or a past event instead of what abcd does now (22-site.md twice, 37-embargo.md, 18-ideate.md), so the cut's docs review would hold; the embargo triage CLI example also gives --by a made-up personal name, and three command pages overstate or narrate history
- iss-2610301943552138abcd records nothing about what each question it puts to a person costs in tokens. A question passes through the question-writing agent, which may draft and check it several times before it passes (up to five checks to a part under itd-2610230756259215), so one question can cost far more than the text the person sees, and no record says how much: a single drafter run in an interview on 2026-10-30 used between 58 and 73 thousand tokens, and one on 2026-10-23 used about 174 thousand while counting rows by hand. Without the count, nobody can tell whether the writer's loop is worth its cost, compare drafting strategies, or see what an interview costs as a whole. The product thinker asked for the tokens of each question to be recorded, as part of a wider account of what abcd's work costs in tokens (a tokenomics intent), whose nearest home is the draft itd-2609292107351737, which measures a development session's token cost against its spec's predicted size class.
- iss-2610302057380175The status line's merging element drops from a person's row on a loaded machine. It reads the default branch's facilitator.mode with git questions of its own, inside the row's 300ms git share, alongside the badge, branch and root-commit reads. When the machine is busy (load above 100 is common here in the evening) those questions outlast the share, the element drops, and every render writes a note to stderr. The race-enabled test run on a loaded CI runner failed the same way, and the tests now widen their budgets; the person's row has no such room.
- iss-2610302058222905CI's plain unit test step, which runs on a records-only or docs-only change, sets no -timeout, so each package inherits go test's ten-minute default. The implement loop package's plain time on the ubuntu runner has grown from 466s to 593s across recent runs and crossed 600s on 2026-10-30 with no test hung, failing a records-only pull request and dropping it from the merge queue. The race steps and make preflight already declare a 40-minute budget.
- iss-2610302058287983The implement loop package's plain test time on the ubuntu CI runner, run as one process, grew from 466s to 593s across recent runs and then crossed 600s; internal/surface/cli ran at 400 to 550s. The goroutine dumps show the time going to git process spawns in the state and tracked-file reads. CI's plain step now shards both packages as make preflight does and declares a 40-minute package budget (iss-2610302058222905), but the packages keep growing, and the margin narrows again at this rate.
- iss-2610310054494441procgroup.RunToEOF reports a command its context stopped as an ordinary failure when the command's pipes close before RunToEOF's wait sees the context end: exec kills the command, the pipes close, the drained branch wins the second select, cut stays false and the bare exit error (signal: killed) is returned without the context's error. internal/procgroup TestRunToEOFStopsACommandThatHangs fails on it intermittently under load and drops merge-queue entries.
- iss-2610310331087925The naming chapter's exemption register omits the shipped top-level verbs checklist and session, though it says it lists every remaining surface.
- iss-2610310331094561The surfaces index says the hidden hook verb has nine entrypoints; abcd hook --help registers eleven, dogfood-binary and dogfood-build included, which no surfaces chapter names.
- iss-2610310331097661The surfaces index's help-placement row for the agents-and-hosts block omits checklist and guard approve, which abcd --help --agent lists there.
- iss-2610310331105899The ahoy chapter and the configuration chapter still describe the worktree store's verbs, reclaim and notes archive as not built, though ahoy worktree add, list and prune ship and prune writes the archive.
- iss-2610310331111109The ahoy chapter's user-scope tree, which must agree with the configuration chapter, leaves out dogfood-roots, filter-roots, shell-path.json, tools.json and the identity files, and its closing sentence speaks of three declaration files while listing two.
- iss-2610310331124321The dashboard chapter says exit 1 only follows something started; dashboard start also exits 1 with nothing started when it cannot read whether abcd manages the checkout.
- iss-2610310331125678The capture chapter's exit codes leave out exit 3, which every capture write returns in a main checkout two or more live sessions started in.
- iss-2610310331135173The decide chapter says internal/core/site does not import core/recordid at all; it does (project.go), though it still derives handles with its own pattern.
- iss-2610310331141902The embargo chapter's check bullet omits that check refuses an advisory id neither --allow names nor the forge lists as published, and never says what --allow does.
- iss-2610310331142572The decide chapter documents exit codes 0, 1 and 2 only; the command page documents exit 3 for a write refused in a shared main checkout.
- iss-2610310331154547The guard chapter's opening says the verb writes nothing but two records; guard allow --once writes a one-shot allow record in the home folder, described later in the same chapter.
- iss-2610310331160987The implement chapter says three sub-verbs drive the loop, but its own intro and verb table list four, record included.
- iss-2610310331161123The land chapter says a review receipt is recorded through the verb but never documents the --record-review act, its inputs, where it writes, its refusal or its JSON.
- iss-2610310331170759The library and configuration chapters say no verb writes user-scope memory and nothing resolves it; memory add writes the machine-layer memory.json and the prompt recall reads both layers.
- iss-2610310331187921The reserve chapter's forms omit the sweep form (reserve --sweep, --apply, --older-than) that the help and the command page describe.
- iss-2610310331189807The reserve chapter never says that a reservation, renewal or take-over first consults the embargo store and refuses with exit 2, pushing nothing.
- iss-2610310331196848The session chapter lists two ways a session ends; the relay also ends every session twelve hours after it opened.
- iss-2610310331202222The status chapter's JSON field list omits holder_ids_refused and holder_id_refused, which status --help says it carries.
- iss-2610310331213662The agents chapter says the four repo-workflow reviewer and researcher prompts carry tools and model; only two of them carry model.
- iss-2610310331215170The configuration chapter's key inventory is stale: it counts eighteen keys and nine hand-set while listing ten, and omits sessions.live, facilitator.mode and release.digest.
- iss-2610310331229293The configuration chapter says abcd's own config carries five blocks; it carries eight.
- iss-2610310331233804The configuration chapter says eight of fourteen committed configuration records carry schema_version; nine of fifteen do.
- iss-2610310331235711Several brief chapters say internal/surface holds only cli and dashboard and call the dashboard the one network listener; internal/surface/session is a second front door and listener.
- iss-2610310331241438The build sequence says remote apply turns on the forge's secret scanning; it applies the whole GitHub baseline.
- iss-2610310331251654The verification matrix's surface-discipline row omits two shipped violations: checklist show and a plain ahoy worktree list.
- iss-2610310331252620The build sequence counts four ahoy forms that write; worktree add and worktree prune also write, so six do besides install.
- iss-2610310331268828The surfaces index says the intent-auditor serves only intent; the build loop also renders its brief and checks its verdict.
- iss-2610310331276186The README's sample status board ends with a version line naming v0.13.4, though the board's last line names the running version and the release is newer.
- iss-2610310331279313The install guide says setup adds the PATH line to .zshrc for zsh and .bash_profile for bash on macOS; setup honours ZDOTDIR and edits the first of .bash_profile, .bash_login and .profile that exists.
- iss-2610310331282356The v0.14.0 upgrade guide states in present tense the menu's commands and the agents-only verbs, and both lists now omit shipped verbs (embargo, land, session, status; announce, checklist, memory, reserve).
- iss-2610310331295746The release page cites intents only, so a breaking change that comes from an issue, such as the sites no longer publishing author names in v0.16.0, appears in the changelog's breaking section but never on the release page a reader starts from.
- iss-2610310815034547The ideate protocol's adversarial leg gives reviewers no way to tell an ambition from a present-tense claim, so an idea about where a repository's product should go is killed because the product does not deliver it yet. On a 2026-10-31 run on a positioning idea (in abcd's own repository, where abcd is the product), both reviewers marked it fatal on current delivery gaps. The product thinker ruled that not yet built is never a reason to kill an ambition: the gap is the roadmap the exercise exists to find.
- iss-2610311100247143The source-ledger flip was refused only under the program name abcd
- iss-2610311224444576On 2026-10-31 nine of thirteen intent builds the product thinker chose were refused at the reservation check by one hold: iss-2610252214522207, whose found_at is the single file internal/core/surface/examples.go, holds a live reservation on origin until 2026-10-31T18:42:23Z whose footprint names dozens of paths (brief chapters 01-product, 02-constraints and 04-surfaces, commands/*.md among them) and which carries no run stage, unlike the build lanes beside it. A hold many times wider than its record's own scope, kept for hours with no lane showing progress, starves every autonomous build that touches the brief or the command pages, and nothing flags it: abcd peers lists it like any other live hold.blocks iss-2610311539091723
- iss-2610311224587853The board's Next list, which the product thinker picks build runs from, shows as ready two intents that abcd build refuses from the record alone, before any reservation is read: itd-50, whose spec spc-2609211924346308 has no ## Footprint packages line, and itd-39, whose ## Open Questions section the build counts as asking one question. The pick-order head skips such intents, but Next lists them unmarked, so a person who chooses from Next gets a refusal instead of a run and cannot tell the two kinds of ready apart.
- iss-2610311224596015itd-39's ## Open Questions section is one bullet, 'None for the product thinker. The three questions first left here are settled under Decisions (2026-10-11); …', and the fail-closed reader in internal/core/intent/questions.go counts every list item without a resolved or deferred marker as a question, so abcd build itd-39 refuses at open_questions (itd-2610091918433290, which shares spec spc-2610111627213138, reads only its own section and was refused at the reservation instead). The record says it is settled in a form the reader does not recognise.
- iss-2610311225001256abcd build itd-2610170638184486 is refused at the peers check because the worktree sota-open-intents, on branch research/sota-open-intents, holds the intent in drafts/ with its own edits, while this checkout has it in planned/. The branch's last commit is 2026-10-23 and it is not merged, so the hold is a research copy a week stale, and the refusal gives neither its age nor a way past it (merge it, or rebase it onto the planned record; removing the worktree is the person's act alone, since it deletes the copy's local tier); an unattended build cannot tell an abandoned peer from live work and is blocked indefinitely.
- iss-2610311242266907Once a security advisory's fix has shipped, its text goes public exactly as it was drafted. A draft is written while the finding is being worked, so it can carry detail that a published advisory doesn't need: source paths and line numbers, reproduction steps, local paths, hostnames or member logins. embargo publish already leaves out an advisory whose text carries a secret, a private name or another embargoed id. It does not summarise the text first, and it does not run the wider privacy checks over it.
- iss-2610311249121083The shell guard refuses git worktree remove for a worktree whose HEAD is on origin/main and whose status is clean, whenever the worktree holds ignored files: a local tier with notes in it, an empty .abcd/.work.local, or the issue allocator's lock file. It also refuses a detached HEAD that sits on origin/main. In the 31 Oct cleanup it refused all 85 merged, clean worktrees, about 7.2 GB, even though every local tier had first been archived to the machine backup store. Reclaiming them takes one guard allow per worktree from the person.
- iss-2610311339274372The owed-work reader names a pull request whose merge state is BEHIND as owed a base merge (internal/core/autonomy/owedread.go, the BEHIND case: 'is behind its base: merge it in'), and the away-mode stop hook then refuses the session's stop on it, even in a repository whose default branch is guarded by a merge queue. A queue tests every entry against the latest base itself, so a branch that is merely behind needs no merge; merging the base in moves the head, which voids the head's preflight receipt and review receipt and costs a full preflight and a fresh review pair for nothing. On 2026-10-31 PR #1291 sat BEHIND with auto-merge armed and its last required check still running, and the hook held the session on it across wakes.
- iss-2610311339293870abcd land --record-review refuses a return whose first line under ### Verdict does not begin with the verdict word (internal/core/landing/review.go reviewVerdict), so '**977fb39cd: SHIP**' is refused as 'not one a validator writes', yet land --help says only that each return names the head's first nine characters under one ### Verdict heading. A host that briefs its reviewers from the help, as happened on 2026-10-31, gets passing reviews refused and has to ask each reviewer to re-emit.
- iss-2610311406481214Under away mode the stop hook's owed-work list held Eve's stop, wake after wake, on build/run-2610311213205613-lane-1 (a drain session's build lane) and chore/drain-session-records (the drain session's own branch), neither of which this session made or may push. The reader's ownership is per working copy by design (findOwn in internal/core/autonomy/owedread.go: this copy's HEAD reflog, the branches its guard recorded creating, the lanes of live runs in its local tier, and pull requests under its reservation key; dcn-2610180936568358, dcn-2610181003463367), and both branches entered it because the drain session and this one (Eve) were both driving from the same main checkout, the drain from the start and Eve for its builds and records: the run state sits in that checkout's .abcd/.work.local/run/ and the drain's checkouts are in its reflog. The hook never says that two live sessions share the copy, so a session reads a peer's work as its own debt and can neither push it, which AGENTS.md forbids, nor stop.
- iss-2610311501473953abcd intent ready itd-39 reported the intent READY on 2026-10-31, listing scope_conditions as an advisory row ('no ## Scope Conditions section — the context claim is unrecorded'), and abcd build itd-39 then refused it at claim_sections for the same missing section. ReadyWithQuestions (internal/core/intent/ready.go) appends only the open-questions start check to the readiness verdict, so READY still does not mean the build will start, the defect iss-2610101610446956 fixed for open questions alone.
- iss-2610311514162877On 2026-10-31 abcd build itd-2610170638184486 was refused at the peers check by backup/sota-open-intents-pre-rebase, a local branch an agent made as a safety copy before rebasing research/sota-open-intents onto main; it held the intent's old drafts/ copy, while main and the rebased branch held it in planned/. The peers check reads every local branch under refs/heads/ (internal/core/peers/read.go) and cannot tell a safety copy from live work, and the guard then refused the branch's deletion (git-delete-unproven) because a rebase that squashed and resolved conflicts leaves no ancestry or patch-equivalence for it to prove, so the build stayed blocked until the person allowed the delete by hand. abcd teaches no safe form of the backup: a tag, or a ref outside refs/heads/, would have kept the copy and blocked nothing.
- iss-2610311539091723abcd reserve still accepts an issue or an intent with a hand-named footprint of any width, though dcn-2610311539024848 rules that only a build or a drain reserves such a record; one hand hold of about 35 paths on 2026-10-31, for an issue whose found_at was one file, stalled nine of thirteen chosen builds for hours. The command pages, AGENTS.md's concurrent-sessions rule and every lane brief still tell a session to reserve each path by hand.blocked by iss-2610311224444576 · blocks iss-2611011010445156
- iss-2610311544004033abcd's README parts cannot form a centred header. Each part is written as its own paragraph, so the three badges stack on three lines and cannot join a centred badge row written in HTML, and links and contents are always bulleted lists. With no Markdown level-one heading, the first absent part goes to the very top of the file. In abcd's own README, choosing all six parts put six blocks above the centred logo and title, with a second release badge, so the README was rewritten by hand and the parts turned off.
- iss-2610311604123786An issue lane whose widening backed off (abcd implement widen, exit 3) has its implement stage handed out again at the very next step, with no wait for the hold that refused it to end: a host or runner stepping the run dispatches a fresh implementer that meets the same hold, as often as it steps, spending an agent each time on a lane that should wait for another copy's hold to end. A runner's end without a receipt is refused outside the step that counts refusals, so nothing bounds the repetition either.
- iss-2610311710599351Committing a model-routing table to abcd's own repository fails five cli tests. TestDisembarkGraveyardWritesLessons, TestDisembarkGraveyardStdin, TestDisembarkPrinciplesDelegated, TestDisembarkPrinciplesStdin and TestDisembarkPressReleaseDelegated read the checkout's .abcd/config/oracle-routing.json, so the routing notice that no connection serves the economy tier lands in front of the --json document they parse. The tests pass once the file is removed, so they depend on the repository they run in rather than on their own fixtures.
- iss-2610311714054375The guard refuses to run any helper script that calls scripts/abcd.sh, as execute-string-uninspectable ('Execute-a-string wrappers are nested past the depth the guard can follow'), because abcd.sh itself nests a shell layer; bash -c around the same loop is refused the same way. On 2026-10-31 a three-line retry script under .abcd/.work.local/scratch/ was refused, though the SCRATCH rules domain tells an agent to put such helpers exactly there, so in this repository an agent can drive abcd only from an inline loop typed into each tool call.
- iss-2610311732391345The site lint's link-targets gate judges only the composed pages, so a /docs/ link the verbatim record rendering writes through the same siteHref (the glossary's loop entry links /docs/explanation/process/ from internal/core/site/explorer.go) is never checked: renaming that docs page breaks the record link with every gate passing.
- iss-2610311732460169Under facilitator.mode auto, an implement-loop lane can never arm its own pull request: the land stage commits the lane's resolved issue record after the last validation round, so no review receipt names the head it pushes, and the gate arms nothing until a second review pair is run by hand over that records-only commit and recorded with abcd land --record-review.
- iss-2610311818545897The update news section of the update command page says to run the plugin's own binary, never another abcd, for update news and then for the setup that waits. In a source checkout of abcd, AGENTS.md says every abcd invocation is scripts/abcd.sh, because the plugin binary is the last release and can disagree with the tree. Following the page on 2026-10-31, the v0.16.0 binary ran the setup that waits in abcd's own checkout and rewrote AGENTS.md and .gitignore. Its text matched origin/main this time, the local main being the one behind, but nothing in the page keeps a release older than the tree from writing its own text there.
- iss-2610312044509977abcd build has no way to stop a run after the lane in hand: once lane-1 of run-2610310228179894 landed as PR #1301, the next implement step opened lane-2 for the spec's next step before taking lane-1's done stage, so a session given one step had to stop stepping by hand and release the reservation with build --release, leaving the run parked with an empty lane-2 worktree.
- iss-2610312044511316In facilitator.mode auto the landing's merge gate waits for a review receipt naming the records commit, but the loop never mints one from its own validation: lane-1 of run-2610310228179894 passed round 4 (ruthless-reviewer SHIP, security-reviewer APPROVE at 45a7ce2c5) and the landing still held PR #1301 unarmed at its records commit 28611e181 until a fresh reviewer pair was run and recorded by hand with abcd land --record-review.
- iss-2610312044522893The checkoutDigest comment in internal/core/implement/loop/autoplan.go (about lines 181-183) says nothing outside the scratch directory is written but the tree objects write-tree stores, yet its add -A on the scratch index (about line 207) also stores a loose blob for each admitted modified or untracked file, and a configured clean filter may write objects of its own (Git LFS writes under .git/lfs/objects). The indexDigest comment is accurate: it runs only ls-files and write-tree.
- iss-2610312044536324commands/build.md (about line 281) and chapter 34 of the brief (about line 1012) say an index past 1 GiB is not read, but indexDigest reads up to 1 GiB and one byte through its LimitReader before it refuses the copy.
- iss-2610312044539836commands/build.md (about line 277), chapter 34 of the brief and the indexDigest comment say the auto-plan's checkout digest covers every index entry with its flags, but the git ls-files -t -v listing it hashes leaves out the fsmonitor-valid bit, by design, since git rewrites that bit on every status.
- iss-2610312044545639The auto-plan's checkout digest runs its git commands with no deadline: gitutil.RunWithIndex and gitutil.StreamWithIndex (internal/gitutil/index.go) and, above all, checkoutDigest's `add -A` through pickGitIndex (internal/core/implement/loop/autoplan.go about line 207, pickcommit.go about line 167), which runs the person's configured content filters. Unlike the bounded runner in internal/gitutil/bounded.go, a stalled filter or git holds the digest, and the implement step taking it, with no limit.
- iss-2610312044551391When the auto-plan's start digest cannot copy the checkout's index (a symlinked index, or one past the copy bound), the lane still runs both plan reviews before the end digest differs and hands it back (internal/core/implement/loop/autoplan.go, the start digest at about line 166), spending two reviews on a result already decided.
- iss-2610312044556915The --auto-plan long help in internal/surface/cli/build.go (about line 205) says only that a checkout that changed since the start hands the lane back, while commands/build.md says what the digest covers (HEAD, the index's entries and their flags, the files the ignore rules admit outside the local tier) and what it does not (ignored files, the git directory).
- iss-2610312044569253No test reaches indexDigest's ELOOP refusal or its SameFile check after the open (internal/core/implement/loop/autoplan.go, about lines 267 and 275): TestAnIndexTheDigestCannotCopyReadsAsChangedEveryTime reaches the Lstat branch and the copy bound, not the open's branches, because a symlink or a FIFO is refused before the open.
- iss-2610312056566760The guard refused 'A=/path/to/scripts/abcd.sh && $A capture remedy iss-N "each a payload (internal/core/guard/payload.go). Either flatten."' as script-runs-hazard on an 'rm -rf' text in that Go file, though no shell runs the file. The cause is the tokenizer's split at a '(' that follows a command's words (parenWord, internal/core/guard/tokenize.go): the text after the '(' is read as a new command, so targetsOf (internal/core/guard/script.go) resolves the repository path there and reads it as a script the command runs, and '. Either' becomes a source of a missing file. After ordinary command words bash refuses such a '(' as a syntax error, so the path is never run; the same split is also made after words such as time and coproc, where the subshell does run, so the split alone does not mark a line the shell refuses. The variable reaches it only because guessedEvalPayload (internal/core/guard/payload.go) reads quoted arguments behind an unknown program name as possible eval text, which is the correct fail-closed reading; the literal 'eval ... "(path)"' form and the unquoted spelled-program form block the same way, while the same path quoted without a '(' is allowed (reproduced with abcd guard check on 2026-10-31). It bites a remedy or message that writes a guard source path after a '('.
- iss-2610312222331947The inline form of the README contents part shows Markdown emphasis as typed. A level-two heading such as 'Why *abcd* exists' becomes a link inside an HTML block, where nothing is rendered, so the reader sees the asterisks; the block form of the same heading shows the word in italics. The plain-text step decodes character references and drops backslash escapes but keeps emphasis markers.
- iss-2610312234315875Whether abcd intent ready gates on the claim_sections start check was ruled on 2026-11-01 (dcn-2611011332291422): it gates. Before that ruling, gating it would have reversed their ruling on iss-2609091009111294, which kept the mechanism and scope-condition rows advisory, so intent ready can report READY on a record that abcd build then refuses at claim_sections, as itd-39 showed on 2026-10-31. Split from iss-2610311501473953 so its drain-buildable half carries no ruling.
- iss-2611010041545467On 2026-11-01 at 00:39 abcd implement receipt refused a build run's receipt because the run's state.json was schema version 17 and the binary that answered reads versions 1 to 16. The run had been started through the main checkout's scripts/abcd.sh, which builds and runs whatever that checkout has checked out; a peer session working in the same main checkout switched its branch to an older one in between, so the next invocation rebuilt an older binary under the running session. A session's abcd should not change because a peer switched the shared checkout, and the refusal's remedy (abcd update) does not apply to a source checkout.
- iss-2611010042046371abcd implement receipt refuses a receipt with 'N runs are in progress ... name one with --run' whenever more than one run is open in the checkout, although the receipt path it is given already sits under .abcd/.work.local/run/<run-id>/ and so names its run; on 2026-11-01 each of three concurrent runs' receipts had to be handed back a second time with --run.
- iss-2611010953085251A drain lane's land stage reads its issue's found_at from the ledger of the checkout the run lives in, while the drain judged and opened the issue from origin's default branch. When that checkout is behind origin and lacks the record, a landing that must sync with a moved main refuses at the reservation ('in no status folder of this checkout's ledger') after its review round has passed, because reserveOnLeavingLand asks runFootprint for the found_at to widen the narrowed reservation back to (internal/core/implement/loop/reservation.go). Attended, the only way past is to fast-forward the checkout; unattended, the stuck rule hands the lane back after three identical refusals or an hour at the stage and releases its reservation, discarding the validated work. Seen on 2026-11-01: run-2611010841189220 for iss-2610312044569253 stopped at landing after round 1 until the main checkout, 135 commits behind, was fast-forwarded.
- iss-2611011010338815A back-off leaves no trace: when abcd reserve or a build backs off another copy's live hold (exit 3), nothing is written that the holder or another copy can read (a build lane's widening back-off is noted only in that lane's own local run record), so neither the holder nor a person can later tell who was held back, from which paths, or whether they tried again once the hold ended. On 2026-10-31 a hand reservation of iss-2610311224444576 held eleven record files it never changed for almost four hours (23:09:38Z to 03:06:16Z); answering who that held back took a hand search of every reservation chain on origin, every local run record and origin's history, which found none, and could not rule out a refused attempt on another machine or account, since a refusal pushes nothing. Two open records touch neighbouring parts of the same remedy: iss-2610241424428420 (nothing tells a backed-off build or drain when the hold is released) and iss-2610311604123786 (a widening's back-off is re-handed with no wait); a fix here should build on them, not repeat them.
- iss-2611011010445156A hand reservation was renewed with eleven paths its work never changed: widening the hold on iss-2610311224444576 to one test file, the footprint was rebuilt by hand from a two-dot diff against a default branch that had moved, so the renewal also named a decision record and ten issue records other merged changes had written, and held them from 2026-10-31T23:09:38Z until the release at 03:06:16Z. reserve replaces the footprint wholesale with whatever paths it is given and asks nothing about them. No copy that left a trace met the extra paths in that window, by the search iss-2611011010338815 records; a refused attempt that left none cannot be ruled out.blocked by iss-2610311539091723
- iss-2611011153130169TestVulncheckInterruptedLeavesNoCopyBehind (internal/core/lint/preflightscans_test.go) is flaky: it fails with 'the interrupted scan did not end' when its SIGINT races the stub's own fork. The stub `go` writes its started marker with the builtin `:` and only then forks `sleep 30`, so a signal sent in that fork-to-exec window misses the sleep, which is orphaned holding the command-substitution pipes in scripts/preflight-scans.sh open until it ends at 30 seconds, past the test's 20-second wait. The script's interrupt path is not at fault: every slow run still exited 130 through its INT trap with the copy removed. Reproduced locally in 18 of 150 runs with no load and no race detector, each ending at about 30.0 seconds; with the stub changed to `exec sleep 30`, none of 400 runs was slow. On 2026-11-01 it dropped a records-only pull request (#1319) from the merge queue in the macOS race run (Actions run 41298480855), though nothing in that change reaches the lint package. A measurement must use the bash the test runs, which is the first on the test process's PATH, not the stub PATH's.
- iss-2611011155020210A practice run (--dry-run) of reading ingest or scribe ingest can pass where the real write refuses. The capture verbs' own checks (the ordering gate, record schema validation and the size cap) run only when the record is written, and the scribe's plan stage says so (ledgerPending, internal/core/scribe/plan.go, landing with lane 2 of run-2610312053380475). So for these two commands the practice run's validator is narrower than the write's, which falls short of itd-2610301428390406's promise that a practice run shares every check. Two smaller gaps go with it. Past the point where reading ingest records a refusal, and in launch ship's payload path, the practice run's refusal names where the refusal would be recorded, so it is not the real run's message word for word. And the tree-wide dry-run test's launch ship fixture declares no plugin archive, so the archive-pin and staged-payload branch under --dry-run never runs. The intent auditor reported all three as concerns (MET_WITH_CONCERNS) on that lane (audit rcp-997517c0f4ba).
- iss-2611011155419019abcd land announces 'merging <id>' for every issue or intent a branch's commits name in a Refs: trailer, as well as Resolves: and Delivers: (internal/core/landing/announce.go, per dcn-2610170704191129). Refs: means the change touches a record without fixing it, but the announcement reads as that record's work merging. On 2026-10-31 a peer session read a build session's records-PR announcements for Refs-only issues as competing work on those issues, and the two sessions spent a round of messages confirming nobody else was on them. A colleague reading abcd status cannot tell a fix that is merging from a record that is merely cited.
- iss-2611011331010643A build lane can start a spec step whose wait on another spec's step is written only in prose, before that step has landed. A step's needs: line takes only the same spec's step numbers (internal/core/spec/steps.go), so a dependency across specs goes in prose. spc-2610301950037469 step 2 says it waits for spc-2610301917245442's steps 1 and 3; the readiness check cannot read that. On 2026-11-01 lane 2 of run-2610312053537139 started step 2 while the parent's step 1 was still on an unmerged pull request (#1315) and its step 3 had not been built. The implementer built the hook half, could not build the verb half, and the review returned FIX FIRST. Landing would have marked the whole step landed, and step 3, which reads the verb's limits field, would have started next. A full implement and preflight cycle was spent on a step that could not be finished.
- iss-2611011332417169Under away mode the stop hook can name a wake deadline that is already past, and then no scheduled wake can release the stop. wakeDeadline (internal/core/autonomy/wake.go) takes the earlier of now plus the ceiling (the owed ceiling, or the idle ceiling when nothing is owed) and the owed set's WakeBy less lease.Skew. WakeBy comes from this copy's live reservations (owedReader.reservationItems: the renewal half-life while now is before it, else the effective expiry) and is never before now, but once now is within lease.Skew (five minutes) of it, WakeBy less the skew falls before now, so the hook names a deadline that has passed and that stays fixed for up to lease.Skew, until now reaches the half-life (and again before the expiry) or the reservation renews. On 2026-10-31 it named 18:28 GMT and kept naming it after 18:28, and on 2026-11-01 it did the same at 00:23 and 05:21; a cron set for the next minute was not counted, and the stop then fell to the unchanged-set row.
- iss-2611011343052330Go's test cache is never reused across worktrees, so every preflight runs all packages twice from scratch. A full preflight on 2026-11-01 reported 0 cached results of 133 packages. The cache keys on the test binary, and each worktree's absolute source paths change it: the same unchanged package in a second worktree re-ran, while with -trimpath it came straight from the cache. -trimpath cannot simply be switched on: nine test files locate the repository through runtime.Caller (internal/core/lint/releasereceipts_test.go, internal/core/launch/payload_completeness_test.go, internal/core/launch/scaffold/scaffold_test.go, and six in internal/surface/cli: hooks_sessionstart, hook_scripts, barerender, hooks_selfprovision, bootstrap, githook_prepush), and under -trimpath every one fails, since the path becomes the module path (open github.com/intentdriven/abcd/.github/workflows/release.yml: no such file or directory). Across the last 60 merges, about two thirds of all test time re-ran results that could not have changed.related itd-2611011325421304
- iss-2611011344205894Every change that mints or edits an ADR takes the full, gated preflight instead of the records-only path, because the ADR index .abcd/development/decisions/adrs/README.md is regenerated with it and scripts/records-only.sh treats a changed path as a test fixture when any test names its bare file name: 'full run: .abcd/development/decisions/adrs/README.md is named by a test (its file name README.md), so it is that test's fixture'. Dozens of files are named README.md and tests naming one of them do not read this one, so a records-only branch with an ADR waits at the load gate (1 to 2 hours on 2026-11-01) and runs the whole Go suite for no test it could affect.
- iss-2611011402496418A planning interview run in a plain terminal on the API-key runner ended at its first question on 2026-11-01. The interviewer wrote a sound question, but abcd's question check refused it at 39 rows against a 32-row limit, and the refusal was treated as the runner's invalid answer: with no host fallback in a terminal the interview stopped, printing 'runner: claude invalid for planning-interviewer ... the contract's validator refused its answer: the question breaks 1 rule(s): tab 1, whole tab (rows)'. The person was left with an internal message and no next step. The brief tells the role 'abcd refuses a receipt ... whose question breaks a rule below, and the interview stops', and only a refused done outcome is ever handed back for another turn. A host session's own question check shows an over-long question with a warning and has the agent redraft refused ones silently, so the terminal route is stricter than the host route for the one rule a model cannot count exactly. The product thinker ruled the same day (dcn-2611011402510346) that an interview must never stop on a question abcd's check refuses, and that anything which does end an interview tells the person in plain words what happened and what to do.
- iss-2611011737317454macOS ran out of application memory on a 128 GB, 16-core machine on 2026-11-01 at about 17:32, with only this person's sessions active, while several agent sessions drained, built and reviewed in parallel. The Force Quit dialog lists only GUI apps (Ghostty at 8.93 GB, falling to 937 MB afterwards), so the go test processes, race-enabled test binaries and agent sessions running inside the terminal never show. The machine's counters show about 155 GiB swapped out since it booted five days earlier, so this was not the first time it ran past its RAM. The system log needs admin rights to read, so the peak was not attributed to one process; a read shortly after, with 22 test processes live at a load of 57, found the test workload at about 4 GiB and the agent sessions at about 3.8 GiB, so the consumer is unproven.related itd-2611012048006057
- iss-2611011943357182The implement loop's land stage refuses a lane whose branch has moved past the loop's own records commit, and offers no path for a reviewed follow-up. On 2026-11-01, lane 2 of run-2610312053537139 passed validation round 2. The land stage then wrote its records commit (0030dea82), and a reviewer's note then had to be fixed before the change merged. That fix went on top as two commits, with its own preflight and a delta review pair (SHIP and APPROVE). implement step then refused: the branch is at 764bc6a8dcc3, not at the head 0030dea82032 the landing lands, so restore the branch to that head. Following that remedy would have thrown the reviewed fix away. The lane was pushed and its pull request (#1333) opened by hand with abcd land and gh pr create, outside the run's record. The run's landing state (body_checked, armed) no longer describes the pull request.
- iss-2611011943547454abcd guard question's text render can contradict its own findings list. Take any draft whose only findings are non-refusing structure findings, for example an --ask draft with a valid chip but no id, or a duplicate id or option value. The input composed for the hook is clean. If the mode store or the away record cannot be read as well, the text prints 'this question was checked and has no finding, but …' and, a few lines later, 'findings: 1, 0 of them refusing'. The JSON and the exit code (2) are correct, so this is the text render's wording alone. The line comes from step 2 of spc-2610301950037469 (PR #1333), in internal/surface/cli/guard_question_verb.go. It was found by that lane's delta review on 2026-11-01.
- iss-2611012047534449Once a role falls back from a runner to the host, nothing can send it back to the runner, so a lane on the API key cannot recover from one failed start. On 2026-11-01 the claude runner exited with status 1 on lane 2 of run-2610312053481114: it had no API key in its environment, and claude --bare answered 'Not logged in', which the loop recorded only as 'exited with status 1'. The loop handed the implementer to the host session. After that, --route on the lane was refused, because the step hands no role out: a re-told await starts nothing, and --route is refused with --restart. The lane cannot be discarded, because it is not held. Lane 2 of run-2611010452297194, handed to the host before the person routed agent work to the API key, is stuck the same way. The same applies to a runner that hits a rate or spending limit mid-step: switching to a second key helps only the next step, not the lane that failed. Both lanes are parked with no agent.
- iss-2611012049508108When a role routed to a runner fails, the loop records the fallback with only the runner's exit status ('2.1.316 exited with status 1', internal/core/runner/proc.go) and leaves out what the runner reported (the stored transcript keeps it, the fallback's detail does not), so the cause is invisible where a person looks: on 2026-11-01 the routed implementer of run-2611012037155265 failed because claude --bare found no API key, and claude reported 'Not logged in' as the result line of its stream-json output on stdout, with stderr empty, which only a hand run of the same command showed. The fallback then parked the lane, since a fallback is final.
- iss-2611012054262885Routing abcd's agent roles to the person's API key takes a hand-written roles block in ~/.abcd.noindex/config.json (roles.<role>.runner: "claude" for the implementer, both reviewers, the intent auditor, the drain judge and the planning interviewer) plus an API key the runner can reach, and nothing in abcd offers, explains or checks either: on 2026-11-01 the person pasted the block as given with no way to tell what it was for, and the key had to be passed by hand on each command from the login keychain. A managed repository's person should be offered the choice between the subscription, the default, and the API key, without editing JSON.
- iss-2611012054270386abcd land's review receipt needs a review pair, and outside a loop's own validate stage nothing can run that pair on the runner: a loop's records commit that is not mark-only (the self-minted receipt iss-2610311732460169 and iss-2610312044511316 propose covers only mark-only commits) and the pair for any records or docs branch are started as host subagents and billed to the subscription, so with the subscription nearly spent on 2026-11-01 every records pull request under facilitator.mode auto either spends it or waits (internal/core/landing/facilitator.go reads the receipt; no verb produces one on a runner).
- iss-2611012123291272A review receipt and a preflight receipt each name one head, so every amendment to a records branch, however small, sends both reviewers and the preflight round again in full: on 2026-11-01 one records branch took six full review rounds in an evening, most for a one-sentence fix, each round re-reading every record already approved (internal/core/landing/facilitator.go reads the receipt by head).
- iss-2611012124359297A run whose working window lapsed while its preflight waited in the load gate refuses a step that carries --route: 'refused at route: --route ... routes the ruthless-reviewer, and this step hands no role to an agent: the run's window has elapsed, so the step pauses the run'. With a zero-minute pause the person must step once without the route to reopen the window and again with it, an extra round each time a long queue outlasts a window, and a step without the route that happens to hand out a role gives it to the host for good.
- iss-2611012124381670abcd land --record-review refused two reviewers' returns whose '### Verdict' section began 'Head: 9d2749a96' and 'Verdict: SHIP': 'its verdict "Head: 9d2749a96" is not one a validator writes; nothing was written'. It accepts only the verdict word alone as the first non-empty line under the heading, which the help text does not say ('each naming the head's first nine characters under one ### Verdict heading'), so a return in an equally clear shape is refused and has to be rewritten by hand.
- iss-2611012144422634A planning interview the product thinker started at 21:41 on 2026-11-01 stopped before its first question, with its answers record written as answers: null. Its tripwire fired on refs/heads/records/api-route-lessons and refs/heads/records/planning-1101, branches two other sessions were committing to in their own worktrees. Every worktree of a checkout shares one .git, so the interview watches every branch ref, and any peer's ordinary commit anywhere in the repository ends the person's interview. The peers had to hold every git ref change for half an hour so the person could retry. With several sessions working one repository, as abcd's own development does, an interview can hardly run at all.
- iss-2611012148181861On the night of 2026-11-01 the product thinker set a per-key ceiling for the night and had work move to their second key when the first reached it, so three sessions could keep working through the night. Their ruling for the budget intent itd-2611011230226453 the same evening is one named key per session and a pause when a cap is reached. Moving to a second key at a cap is therefore practised but not ruled on as abcd behaviour, and nothing in the record says whether abcd should do it itself.
- iss-2611012202511008The claude runner kills a routed role at its default one-hour bound (internal/core/runner/runner.go, DefaultTimeout), and an implementer's work in this repository can outlast it: on 2026-11-01 the routed implementer of run-2611012100266247 committed its fix, wrote its report and, running its definition of done over the whole internal tree after the loop package alone took 1,459 seconds, was killed at 1h0m0s before writing its receipt. The kill counted as a failed start, the role fell back to the host and the lane parked, with finished, tested work stranded behind a missing receipt. The same night two more routed implementers, on itd-39 and itd-2610142145236613, were killed at the hour (22:52 and 22:53 UTC) partway through make preflight, which their briefs named as the definition of done, each with its work committed and its report written, and each fell back to the host. A killed launch reports no result and so no total_cost_usd, so all three launches' spend is missing from every tally. A receipt the host writes after such a kill also loses whatever the implementer meant to resolve beyond the issue it was handed: one killed implementer's report asked its landing to resolve a second issue, the host's receipt left it out, and an accepted receipt cannot gain a resolve, so that issue waits for a separate records change.
- iss-2611012309408370A receipt's model is copied into the run's state when the receipt verifies and is never read again, and the land stage refuses a records commit whose receipts report no model, so a receipt verified without one leaves the lane with no way to land: on 2026-11-01 a host-written receipt for run-2611012100266247 omitted the model, the lane passed three review rounds, and the landing refused; correcting the receipt file changed nothing, implement step --restart refuses a lane at land, and the remedy's fix round cannot be reached, so the model had to be written into state.json by hand (internal/core/implement/loop/land.go, assistedByTrailers).
- iss-2611020016159754TestAnAutoPlanStepRefusesASharedMainCheckoutBeforeItPlans failed in the merge queue's check (macos-latest) job (run 41358066383, the race stage over the whole module) on a merge group whose change touched records only: build_autoplan_surface_test.go:117 'the plan step backs off in a shared main checkout: exit 0'. The step it tests is meant to refuse in a main checkout that two or more live sessions started in, and it exited 0 instead. The same test passed elsewhere, so it is flaky on macOS under the race detector or depends on timing, and each failure ejects the queue's entries: PR 1337 was removed from the queue at 23:52 and waited to be queued again.
- iss-2611020305525945abcd build refused the terminal interview fix (iss-2611011402496418) at 03:05 on 2026-11-02: 'is handback under adr-2609291342092738 (severity): severity major is above the drain's (nitpick, minor); remedy: the issue is a person's'. The product thinker had directed that fix the evening before and ruled that agent work runs on the API key, but the only route for a major issue is a host session, which bills the subscription the person asked to spare. Nothing lets a person admit one issue they have decided on to the loop, so a directed major fix waits for the person or runs on the route they ruled out.
- iss-2611020719483054The away-mode stop check counts every live run's lanes as this checkout's own: with several sessions building in sibling worktrees of one repository, a session's turn end was refused more than fifty times on 2026-11-01 for lanes other sessions owned on their own branches, because the owed-work read takes every run the checkout's local tier lists rather than the runs this session drives.
- iss-2611020719494343A lane whose change raises the run state's schema rewrites the live run's state at the new version: its own preflight's load gate (implement load --wait, run through the lane's freshly built binary) renews the run's reservation and saves the run state with the lane binary's schema, after which the driver, still on the default branch's older abcd, refuses every step and receipt ('schema version 18, which a newer abcd wrote'). On 2026-11-02 the lane for iss-2611012047534449, which moves the schema from 17 to 18, did this three times to its own run (about 04:56, 05:57 and 07:15 UTC, the last in its landing preflight), and the version was set back by hand each time, no version-18 field being in use.related itd-2611031342011261
- iss-2611020720003337TestStatuslineCreatesNoDirectory (internal/surface/cli/statusline_readonly_test.go) fails on a loaded machine: its subtest 'an abcd home with no fill directory' takes the status line's 'DROPPED the merging element — facilitator.mode could not be read (git did not answer in time ...: context deadline exceeded)' stderr line for 'a skipped write was said', so a git read that times out under load fails a test about directories. It failed a landing preflight on 2026-11-02 at about 07:15 UTC.
- iss-2611021751406429A routed role killed at its bound loses three things the bound alone cannot save: time it spent waiting at the load gate counts against the bound, so a run queued behind other preflights is killed sooner than its work warrants; a killed launch reports no result and so no total_cost_usd, so its spend is missing from every tally; and a role killed after it committed its work counts as a failed start, falls back and parks the lane, stranding committed, tested work behind a missing receipt. iss-2611012202511008 bounded each role by its own timeout and scoped the implementer's definition of done; these are the parts of its remedy left over.
- iss-2611022247103872A routed implementer's receipt is refused since #1356 for a missing model: on run-2611022037190012 the claude runner launched the implementer, which committed and wrote its receipt without the model field, and the receipt check refused it (the field the landing's Assisted-by trailer names), pausing the lane until the host added the model by hand. Every routed build now stops at its receipt.
- iss-2611022247115653Review rounds on a records pull request do not converge: #1347 reached its eleventh review round on 2026-11-02, because each round re-reviews the whole diff against main and raises new findings in records the previous fix never touched, so a fix round cannot know when it is done.
- iss-2611022247128872A step loop a stopped session left in the background keeps stepping its run and launching agents on a key nobody watches, and a preflight it started is orphaned (its parent gone): on 2026-11-02 a successor found run-2611020739372478 mid-step with no way to learn from the run who was driving it, from which process, or which key its launches spent.related itd-2611041549461012
- iss-2611022247131866ahoy worktree prune keeps merged, clean worktrees it should reclaim when their notes hold the locally built bin/abcd: on 2026-11-02 about ten merged worktrees were kept because that binary is over the notes archive's 4 MiB per-file cap, though it is a build product, not a note.
- iss-2611022247147314A merge-queue drop is silent in abcd: #1347 left the queue twice on 2026-11-02, once when its merge-group macOS job was cancelled and once on a flaky test, and neither land, peers nor status said the entry had left or why; the coordinator learned it only by polling the forge and reading the run's jobs.
- iss-2611022247151670The guard refuses a read-only forge query as a merge: a script that ran gh api graphql reading a pull request's isInMergeQueue and autoMergeRequest fields after a cd was refused as merge-graphql-unread-human on 2026-11-02, though the query merges nothing.
- iss-2611022331542403TestTheForgeIsNotAskedPastItsBudget fails under load: on 2026-11-02 in #1347's merge-group macOS race run it reported 'asked []; want only the newest before the budget ran out', because a 100ms pusher budget can be spent before the first branch is asked when the runner is loaded, so the test asserts timing rather than the budget's behaviour.
- iss-2611030450356845The build's land stage ships an intent but leaves the issues the intent names in related_issues open, so the lane's own preflight then fails issue-drift (shipped_unresolved), and the loop refuses any commit after its records commit: on run-2611030127507347 (the memory floor, 2026-11-03) the lane could only be landed outside the loop, with a hand commit resolving iss-2611011737317454.
- iss-2611030450363508The build loop's validate stage passed run-2611030127507347 through two rounds on a head whose preflight then failed two lint tests (AGENTS.md past the 32768-byte readers' cap, and a raceEnabled read in init that the plain-guards scan cannot classify): neither the implementer's definition of done nor the reviewers ran the lint gates, so the failure appeared only after the records commit. AGENTS.md also stood 16 bytes under its cap on main, so any lane adding a clause trips it.
- iss-2611030744325032A loop run whose lane was landed outside the loop can never be finished: run-2611030127507347's lane merged as #1367 at 85ed321d2 after a hand landing, and implement step now refuses on every call because the branch is not at the records commit 0c466ccb1 the landing pinned, with a remedy to restore the branch, which would rewind a merged branch. Nothing else ends the run, so it keeps its lane worktree (prune keeps it as held by the run) and held its reservation until it was released by hand. iss-2610142233473049 covers the unmerged case.
- iss-2611030744332925Older build runs landed spec steps without marking them landed: on 2026-11-03 four open specs held merged steps with no landed line (spc-2610240951109420 steps 1-2 from #1145 and #1193, spc-2610161949559050 steps 1-2 from #1179 and #1187, spc-2609301811532881 steps 1-6 from #1110 and #1197, spc-2610230730269295 step 1 from #1197), so the board offered them as ready from step 1 and abcd build would have rebuilt delivered work. Found only by grepping merge messages.
- iss-2611030744340532The board lists itd-2610240823055889 as next and ready ('implement against the spec body'), though its only open spec, spc-2610242112593216, says in its summary that it holds until the product thinker rules on dcn-2610241228598485; the hold is prose, so neither the board nor abcd build can see it, and a build would run against an unruled spec.
- iss-2611030857252735TestStatuslineWritesOnlyTheFillFile/managed_by_history_registration_only (internal/surface/cli/statusline_readonly_test.go:352) failed in #1369's merge-group macOS race run 41598350207 on 2026-11-03: stdout was empty because git did not name the checkout within the status line's 300ms git budget under the race load, dropping a pull request from the queue whose change was unrelated. #1362 widened the budgets for TestStatuslineCreatesNoDirectory; this sibling still ran at the default.
- iss-2611031146244351abcd land opens no pull request for a branch made outside the build loop: it composes the body, pushes, and stops with 'no open pull request ... open it with the command, then run abcd land again'. On 2026-11-03 the coordinator opened eight pull requests that way by hand (gh pr create from the composed body, a re-read for footers, then land --record-review twice and land again to arm), in a helper script, so a CLI-only run cannot land a hand fix without a forge command of its own.
- iss-2611031146255825No abcd verb drives an intent build to done unattended: implement step takes one stage and exits, so a build of several steps needs something outside abcd to re-run it after each stage, wait out the merge queue, step again once the lane's pull request merges, and open the next lane. On 2026-11-03 the coordinator did this with a polling helper script (drive-run.sh) and timed wake-ups; drain --drive (itd-2610222215485265) covers drain lanes only, and itd-2610240933025076 starts a build but does not carry it through.related itd-2611031342011261
- iss-2611031146263490A merge-queue drop's cause is diagnosed and filed by hand: on 2026-11-03 five pull requests left the queue, three at the ci-watchdog deadline and two on timing-bound tests, and each time the coordinator read the run's failed log, told a watchdog stop from a flaky test, captured the flake, launched its fix and re-armed. itd-82's queue watch re-arms and names the dropped check, but a failing test does not become a ledger record a drain lane could fix.
- iss-2611031146278428Choosing the next work to build is done by hand: the board lists 32 ready intents, but on 2026-11-03 the first three could not be built unattended (one held on a product ruling in prose, one whose first step is a live proof needing the person's yes, one mid-build), majors are refused by the build, and a build whose footprint overlaps another copy's reservation is refused, so the coordinator read each record and chose a copy to build from by hand.
- iss-2611031148079925The /abcd:lab page sends free text with no sub-verb to the bare list: on 2026-11-03 the product thinker typed /abcd:lab with a change to try on the status line, meaning a temporary experiment to evaluate, and the page's 'with none, list the labs' rule read it as no sub-verb, so the session treated it as a request to change the product and drafted an intent instead of minting a lab.
- iss-2611031337115764A finished agent is stranded when the step that would collect it is refused: on run-2611031131030791 (2026-11-03) the routed implementer ran 1h37m, committed and wrote its receipt at 13:32, but the next implement step was refused on the run-state schema trap (iss-2611020719494343), and after the state was put right every further step asked the host to start a fresh implementer, though the receipt sat at the path the stage awaited. Only handing it in by hand with implement receipt moved the run on; an unattended run would have launched a second implementer and paid for the work twice.related itd-2611031342011261
- iss-2611031337128901The queue watch's terminal report of a dropped pull request quotes a re-arm command gh refuses non-interactively: droppedRefusal in internal/core/implement/loop/queue.go gives 'gh pr merge N --auto --match-head-commit=<sha>' with no merge method, while toggleArming builds the full command (with --merge, --squash or --rebase from the queue's rule) that watchQueue has in hand. Found as a note in #1370's landing review (2026-11-03).
- iss-2611031719581061abcd land arms a pull request whose branch carries another queued pull request's commits, and the merge queue then removes it as invalid_merge_commit: on 2026-11-03 #1376 (records-coord-1103c) carried #1375's two commits and was armed while #1375 was queued; it entered the queue at 14:46 and was removed 16 seconds later, missing the 15:00 freeze, and had to be re-armed by hand after #1375 merged.
- iss-2611031719593367Two notes from #1378's landing review (spc-2610240951109420 step 3, 2026-11-03): handedMove in internal/core/implement/loop/loop.go tells the host two different things about which model to start for a host-run review-set reviewer under tiering; and holdRequestModel in internal/core/runner/config.go vets only the route's own runner, so a launch-time fallback to another runner is not re-held against the requested model (unconfirmed).
- iss-2611031731385043record-lint's prose_citation_resolves refuses a record id whose record exists, minted, on another open pull request's branch and not yet on main: on 2026-11-03 a decision citing dcn-2611031615094092 (in #1381, queued) failed the handover PR's preflight, and the easy way past was to cite the ruling in words, which drops the id and with it the trace (the product thinker ruled ids must always be used). The forward-looking marker keeps the id, but it was written for a record not minted yet, and nothing removes it once the record reaches main, so stale markers accumulate and the next reader cannot tell a pending citation from a dead one. <!-- record-lint: forward-looking -->
- iss-2611032326573729abcd has no fixed place or command for the walled configuration directory: spc-2610230813348813 calls for a dedicated CLAUDE_CONFIG_DIR the person logs into once but names no location, and on 2026-11-03 lab lab-261103171720-c0bdccf chose ~/.abcd.noindex/claude-walled/ and a hand-written launch script pointed at the 0.16.0 plugin path; no abcd code knows that directory, so a session or verb started in a checkout cannot find, create or report the wall, and each account repeats the setup by hand. The same setup showed that the plugin ships no implementer agent limited to file and shell tools, and that a host reads a new agent file only at session start.related itd-2611040344170206
- iss-2611032327111678Nothing enforces dcn-2611031722512037's wall: a session that is not walled can start or coordinate unattended work with no refusal and no warning. On 2026-11-03 a plain claude session in a checkout, holding the person's connectors and personal memory, coordinated build lanes and a release while the person was not watching, and a second account's session was about to do the same, found only because a person asked; abcd mode autonomous, abcd build and abcd drain accept such a session as readily as a walled one.related itd-2611040344170206
- iss-2611032348317844The guard's merge rule refuses a read-only GraphQL watch whenever its own fetch of origin's main times out: it then reads facilitator.mode as human and treats any query it cannot read on the line as a possible merge, so on 2026-11-03 a slow network turned a coordinator's queue watcher off, though a plain git fetch with a longer limit succeeded at the same moment.
- iss-2611032348328608A cloud session's records are mangled: the cloud connector's setup names its OS account abcd, and the identity scanner flags the caller's account name, so record text containing abcd is redacted to [redacted-user]. #1384 fixed only the tests this breaks, by running their scans as a neutral caller; a record written in a cloud session still loses the product's own name.
- iss-2611032348355667implement step hands out an implementer (rc=0) on a run whose reservation has lapsed and whose renewal was refused, saying take other work in the same message: on 2026-11-03 run-2611031640393520 would have started an agent unreserved had its coordinating session not stopped.
- iss-2611032348360959A spec footprint naming a whole directory collides with a peer holding one file in it: run-2611031640393520's footprint has internal/core/lint, a cloud session holds internal/core/lint/prosecitations.go, and the run's renewal is refused although the lane changes none of that session's files.
- iss-2611032348373007Stopping a stage leaves no record of what it wrote, and nothing shows a lane's uncommitted work: on 2026-11-03 a coordinator stopped an implementer and recorded that it had written nothing, while its worktree held ten changed files, found only by the next session's own git status; implement status and step show nothing of them, so a resume would start a fresh implementer over them.related itd-2611041549461012
- iss-2611032348389895implement status without --run renews the reservations of every run in the checkout, which pushes to origin from a verb a reader takes as read-only, and it can start a window as a side effect: a session reading a run's state on 2026-11-03 added record lines and a push it did not expect.
- iss-2611032348394774The roles live in the account-wide config.json, so routing one test's roles to the host reroutes every stage any session in that account starts: on 2026-11-03 a walled test's backup-and-edit also changed where the release session's stages would go, and a test stopped before any stage has no rule for putting it back.
- iss-2611040337038931History rewriting is only partly prevented, against the product thinker's ruling of 2026-11-03 that abcd never rewrites history: the guard's coverage is partial, and server-side rules cover main alone.
- iss-2611040337050157abcd docs fidelity --apply is not idempotent: run twice on 2026-11-04, a replacement that begins with the sentence it replaces is matched and applied again, doubling the clause in the brief and duplicating its flag.
- iss-2611040337065203The brief lags delivery and a release cut pays for it: the v0.17.0 cut's docs review went through at least five rounds on 2026-11-04, returning 10, 14, 1 and 9 false brief sentences, nearly all in one chapter, 35-drain.md, because itd-82 shipped with a review that only had to exist at its close. Each round costs a reviewer and a fixer while every merge is held by the release reservation.
- iss-2611040337082034A review receipt binds one exact head, so a one-line fix after a review means the whole review pair again, and a preflight already running is thrown away: on 2026-11-03 and 04 the CI split went through four rounds and its preflight was stopped three times. Reviewing a small delta costs little, but the receipt has no way to say that a delta was what was read.
- iss-2611040337103775Re-reserving a record with a new footprint replaces the old footprint, with only a warning: on 2026-11-04 adding .github/workflows/ci.yml to iss-2610181757540736 dropped three directories other live work relied on, until a coordinator noticed the warning and reserved all four again.
- iss-2611040337111563implement step and land refuse to push during another copy's release, although the repository's rule is that a change ready while a peer is mid-cut is handed over as a pull request: on 2026-11-04 a walled session finished a lane during the v0.17.0 cut and had to push and open its pull request by hand.
- iss-2611040337136199A host-run reviewer's return has no model field and a receipt's model is self-reported, so nothing shows which model a stage used, although the driver asks for tier frontier: a subscription test on 2026-11-04 could not say what ran its reviewers.
- iss-2611040337158228implement receipt <path> is refused when several runs are in progress, though the path names the run, and the driver's own next: line omits --run, so following it fails.
- iss-2611040337160750After one validator's receipt, the next: line says start a fresh ruthless-reviewer agent while that agent is still out, which invites a duplicate spend.
- iss-2611040337182085A validator's brief says to write the whole return to a path, but the ruthless-reviewer and security-reviewer agents have no Write tool, so a host-run reviewer has to reply in text or write through its shell.
- iss-2611040337193723implement status keeps saying waiting for its full check, run the repository's preflight, after the receipt is minted and while the release hold is the real wait, so a person or agent is told to do what is already done.
- iss-2611040337216924Reservation renewal happens only when something calls status or step, and a preflight outlasts half a lease on a busy day, so a waiting lane can lapse: a lane's reservation lapsed during a stop on 2026-11-03 and a peer's narrow file then blocked its renewal for 90 minutes.
- iss-2611040337228910A resume does not report how far a lane's base has moved: on 2026-11-04 a lane resumed on a base seven hours old, so its pull request was behind main by more than twenty commits and its preflight judged the old base.related itd-2611041549461012
- iss-2611040337241546The Bash tool runs zsh, and abcd's shell guidance does not say so: a variable before a colon is mangled, PIPESTATUS is empty so a tail's exit is read as the command's, and an interactive rm alias hung a call for two minutes, all on 2026-11-04.
- iss-2611040337254654The Go build cache reached about 323 GB on 2026-11-03 with every entry used within two days, because many worktrees and shards each build their own variants; nothing bounds it and the disk reached 5 GiB free on 2026-11-02, which an unattended run would not survive.
- iss-261104055401362504-naming.md:14 says the bare form and the read-only sub-verbs report and that install, uninstall, connect, remote apply and credential (with --home) are the write paths. abcd ahoy worktree add writes the worktree, its start record and its local tier, and abcd ahoy worktree prune writes the notes archive and removes worktrees (their --help sentences; 01-ahoy.md:491-500).
- iss-261104055402408104-naming.md:207 calls *<DOMAIN> a leading-anchored prompt prefix. A star command anywhere after whitespace activates: abcd rules --prompt "hello *SCRATCH there" reports SCRATCH hit by *SCRATCH. parseStarCommands (internal/core/rules/rules.go:681) checks only the bytes around the token, and the row's own regex admits whitespace before the star.
- iss-261104055403673104-naming.md:207 says multi-star activates multiple domains in left-to-right order. parseStarCommands returns a set and RuleSet.Match walks domain names sorted (internal/core/rules/rules.go:618-646,681): abcd rules --prompt "*SCRATCH *COMMITTING" lists COMMITTING before SCRATCH.
- iss-261104055404498604-naming.md:219 gives LOAD's recall keywords as burners, stress runs, nohup, a load test or load average, and pegging or saturating every core, and its injection as the trust rule. abcd rules --prompt matches nothing for pegging every core or saturating every core; only peg every core and saturate every core are aliases. The row omits the recall words pgrep, preflight, go test and race run (internal/core/rules/defaults/rules.json) and the domain's fourth rule, the load gate for preflights and race runs.
- iss-2611040554051652.abcd/development/brief/04-surfaces/08-abcd.md:185-188 lists the presence line and JSON statusline as the badge, the repository, the branch and the record's counts. Under facilitator.mode auto the binary adds an element between the branch and the counts: the plain row reads `abcd-managed · <repo> · main · autonomous merging · itd N · iss N`, with key `merging` in statusline.elements. .abcd/development/brief/04-surfaces/26-mode.md:16-26 documents it; this chapter does not.
- iss-261104055406643104-surfaces/01-ahoy.md:125-126 calls the remote apply 'the one abcd verb that mutates state outside this machine' and :146 heads it 'the one outward-visible write'. Other verbs write to the remote: abcd reserve writes one commit to its origin branch, abcd announce one commit to a status branch, abcd land pushes and arms a merge, and abcd peers re-arms withdrawn merges (each verb's own help). commands/ahoy.md correctly limits the same claim to ahoy's own forms.
- iss-261104055407574804-surfaces/01-ahoy.md:46-48 says the slash command dispatches every sub-verb and mode but the identity check. commands/ahoy.md gives no dispatch for worktree, worktree add, worktree list or worktree prune: no section, nothing in its argument-hint (line 4), and its opening says five forms change something without counting worktree add or prune. The CLI ships all four (abcd ahoy worktree --help; chapter table :35-38).
- iss-261104055408913004-surfaces/01-ahoy.md:473-628 draws the user-scope tree and :630-632 says it and the prose in 05-internals/03-configuration.md are one list and must agree. The tree has no fill/ entry; the prose names it (03-configuration.md:1155) and the binary keeps the status line's context fill there (internal/core/rules/fill.go:59).
- iss-261104055409061204-surfaces/01-ahoy.md:973-986 tabulates the gap categories and has no row for sessions (internal/core/ahoy/sessions_ask.go:37) or shell-path (internal/core/ahoy/shell_path.go:29), both of which the binary declares; bare abcd ahoy reports the live brief session gap. The flag paragraph at :1220-1230 lists what the non-interactive flags pre-answer and omits --live-sessions, which appears only in the appendix (:1646).
- iss-2611040554105026.abcd/development/brief/04-surfaces/20-banlist.md:247-250 says git runs the hook the clone's hooks path selects, which abcd neither sets nor fully observes. On a yes at a terminal `abcd ahoy install` sets core.hooksPath to .githooks in the clone's .git/config and reads it back (internal/core/ahoy/commit_checks.go:44-47; .abcd/development/brief/04-surfaces/01-ahoy.md:984).
- iss-2611040554115326The build chapter lists its checks by name and says a refusal names the check (.abcd/development/brief/04-surfaces/34-build.md:40-48,134). An issue id the repository's drain rule does not take is refused at a check named `eligible` (internal/core/implement/loop/check.go:41). The key bullet describes that rule at line 44 without the name, so a reader holding the refusal cannot find the check under the name it gives.
- iss-2611040554128376.abcd/development/brief/04-surfaces/08-abcd.md:5-7, 37 and 465-466 call the board strictly read-only and say the version answer writes nothing. Where ~/.abcd.noindex exists without its marker, every command but the status line first writes ~/.abcd.noindex/.gitignore and gitignore-laid (internal/surface/cli/cli.go:7247, layHomeIgnore in internal/surface/cli/homestop.go:176; .abcd/development/brief/05-internals/03-configuration.md:1202). Nothing is written in the repository, and nothing at all when the folder is absent.
- iss-2611040554139508.abcd/development/brief/04-surfaces/08-abcd.md:286-320 enumerates what `abcd peers --json` adds and does not name the top-level `ceiling` object (internal/surface/cli/peers.go:72, internal/core/claim/ceiling.go:51), which is emitted when the reader's identity is known. commands/peers.md:120 documents its fields; .abcd/development/brief/04-surfaces/37-reserve.md describes the cap only as behaviour.
- iss-261104055414921404-surfaces/01-ahoy.md:41 and :1478-1481 say bare /abcd:ahoy mutates nothing, and :79, :1457 and :1526-1528 say the same of the dry run and doctor. Where ~/.abcd.noindex exists and holds no marker, the binary writes .gitignore and gitignore-laid into it before any command runs (layHomeIgnore, internal/surface/cli/homestop.go), so bare ahoy, --dry-run, doctor, --providers and credential each leave those two files. An absent home is not created. 05-internals/03-configuration.md describes the laying once but not that a read-only verb does it.
- iss-261104055415381904-surfaces/01-ahoy.md:908-917 lists the person-only questions as the abcd download, the shell settings, the commit checks, the status line, the commit identity and each tool, asked in that order. internal/core/ahoy/person_only.go:89-93 lists the live brief session question ahead of all of them, and a --yes install reports it as a step that needs the person. The chapter's prose never mentions this question.
- iss-261104055416865404-surfaces/01-ahoy.md:1431-1437 enumerates what bare abcd ahoy prints: folder kind, plugin root, root SHA, install mode, vintage, staleness, superseded root, citation baseline, gaps, guard health and banlist. The board also prints a statusline: row and a provider: row; the chapter mentions the provider only as an optional gap at :139-140.
- iss-2611040554179196.abcd/development/brief/04-surfaces/20-banlist.md:11-12 calls bare invocation and listing strictly read-only. Where ~/.abcd.noindex exists without its marker, the command first writes ~/.abcd.noindex/.gitignore and gitignore-laid (internal/surface/cli/homestop.go:176; .abcd/development/brief/05-internals/03-configuration.md:1202). Nothing is written when the folder is absent.
- iss-2611040554189675.abcd/development/brief/04-surfaces/20-banlist.md:222-223 says `abcd ahoy` lays down the guard artefacts. Bare `abcd ahoy` mutates nothing (.abcd/development/brief/04-surfaces/01-ahoy.md:41); `abcd ahoy install` wrote .githooks/pre-commit, .githooks/pre-merge-commit and .gitattributes in a test repository.
- iss-261104055420878706-capture.md:296 says every refusal of a ledger verb's own input exits 2, naming a malformed id and a flag value naming nothing, on promoting among others, and leaves exit 1 to a fault. abcd capture promote exits 1 on capture promote bad, on capture promote <iss-N> --intent itd-9 (not in the intent store, nothing stamped), and on a second promote of a promoted issue (06-capture.md:549 lists that as a refusal). A malformed id exits 2 on resolve and defer, and an unknown iss-N exits 2 on promote.
- iss-261104055421373006-capture.md:296 says a flag value outside its shape exits 2 on the capture write, and 06-capture.md:143 says a lapse instant that is given must be an RFC 3339 instant. abcd capture "<text>" --remedy r --lapsed-at bad is refused with malformed frontmatter: lapsed_at is not an RFC 3339 instant, and exits 1. A bad --severity and a --found-at path that does not exist exit 2.
- iss-2611040554221246.abcd/development/brief/04-surfaces/24-decide.md:21 says decisions outnumber ADRs about six to one. The tree holds 925 dcn-* records under .abcd/work/decisions/ and 123 ADR files under .abcd/development/decisions/adrs/, README excluded, about 7.5 to one.
- iss-2611040554222004The checklist chapter says each item carries the references it is about and an optional credential named by kind, scope and expiry (.abcd/development/brief/04-surfaces/40-checklist.md:35), and commands/checklist.md:77-78 says an item needing a credential names it that way. The schema validates and the list renders owner_refs and credential (internal/core/checklist/checklist.go:138-139), but `abcd checklist add` has only --next-look, --promise and --waits-on, `set` has only --state, and no non-test code assigns either field. Neither can reach an item through a shipped write.
- iss-261104055423993904-surfaces/02-disembark.md:306 says model_reported is read from the payload's own model field. Every lifeboat payload decodes with unknown fields refused (:175), so adding model to a press-release, principles, review or lessons payload exits 2 with a malformed-JSON refusal, and no agent prompt's shape declares it. The receipt on a disembark ingest therefore always reads model reported not reported.
- iss-261104055424611504-surfaces/02-disembark.md:310-311 says that with no table accepted and no override the step asks for host-decides on the harness and nothing is printed. A delegated abcd disembark press-release run in that state prints route: press-release-composer asked tier host-decides, used harness, model reported not reported on the text render; only the stderr fallback line is absent. Line 302 of the same paragraph says the receipt is a route: line in the text.
- iss-2611040554256499.abcd/development/brief/04-surfaces/30-inbox.md:30-32 says a waiting file this abcd cannot read is listed as unreadable, never dropped, and that a file that is not a report says so. The list reads only names matching fileNameRe (internal/core/report/inbox.go:89, 373). A file named notes.md in the inbox is absent from `abcd inbox`, its tally and its unreadable rows; only a report-shaped name is listed as unreadable.
- iss-2611040554271612.abcd/development/brief/04-surfaces/30-inbox.md:148-150 defines exit 1 only as a failure after the capture is written, naming the capture. With an inbox directory the account cannot read, `abcd inbox` and `abcd inbox show <id>` exit 1 with a cannot-read-the-inbox message, also in the JSON envelope, and no capture exists or is named.
- iss-261104055428306305-intent.md:698-700 says that with no table accepted and no override the step asks for host-decides on the harness and nothing is printed. With no table, abcd intent consistency prints a routing: line naming host-decides, decided by none, via harness, and abcd intent audit renders the same line when it writes a request (internal/surface/cli/cli.go:3616, route.go:269). Only the stderr fallback line is absent.
- iss-2611040554288936The lab chapter says the harvest of a halted lab leads with its gate finding (.abcd/development/brief/04-surfaces/31-lab.md:165), and `abcd lab harvest --help` says its gate findings come first (internal/surface/cli/lab.go:216). Gate findings sort first only within a section (internal/core/lab/harvest.go:285-286). A gate finding is open, so it sits in section 4, and any worked finding in section 3 precedes it; only a one-line halted note appears earlier, in section 2.
- iss-2611040554295339The lab chapter and `abcd lab harvest --help` say every product finding is listed with the capture line that files it (.abcd/development/brief/04-surfaces/31-lab.md:124). The line built at internal/core/lab/harvest.go:135 has no --remedy, and `abcd capture` refuses it with exit 2. harvest.md says the flag must be added before the command runs; the chapter, the help and the verb's terminal listing do not.
- iss-2611040554308925The lab chapter's exit codes say exit 1 covers a gate that refused (the preflight, the sweep, the harvest's citation check) or a halted lab refusing a probe, 'with the artefact rendered and the finding recorded' (.abcd/development/brief/04-surfaces/31-lab.md:175-176). That holds for the preflight and the sweep only. The harvest's citation refusal writes nothing, as lines 169-171 of the same chapter say, and sets no halt; `lab record` on a halted lab writes nothing and names the standing finding.
- iss-2611040554318883The lab chapter says the matrix plan is built from the declaration and the machine's configuration alone (.abcd/development/brief/04-surfaces/31-lab.md:34), and `abcd lab matrix --help` enumerates its exit 2 refusals. The verb also refuses, exit 2, a lab with no passing preflight (internal/core/lab/procedure.go:58-60, reached from internal/core/matrix/consent.go:126). Neither text names that refusal.
- iss-2611040554321461The lab chapter says every path is written in tilde form (.abcd/development/brief/04-surfaces/31-lab.md:180). The matrix plan's 'to start it' line and its JSON approve_with embed the declaration argument unredacted (internal/surface/cli/lab_matrix.go:90), so a declaration under the home directory given by absolute path is printed with that absolute path. The refusal paths of the same verb do redact it.
- iss-2611040554340976The land chapter says the JSON carries `pushed` when the push sent a commit (.abcd/development/brief/04-surfaces/38-land.md:299). push() sets res.Pushed = res.Head on every successful push before it reads the porcelain result (internal/core/landing/land.go:882), so a no-op push whose step note says origin already held the branch and the push changed nothing (land.go:885) carries `pushed` as well.
- iss-261104055435408404-launch.md:996-997 says that with no table accepted and no override the step asks for host-decides on the harness and nothing is printed. With no table, abcd launch ship --dry-run --changelog-json <file> prints a route: line (asked tier host-decides, used harness), and 04-launch.md:983-985 says a ready emit prints a routing: line. Only the stderr fallback line is absent.
- iss-2611040554357485The land chapter says the composed pull-request body carries the commits' Refs:, Resolves: and Delivers: lines once each (.abcd/development/brief/04-surfaces/38-land.md:143). The composer keeps only Resolves: or Refs: lines naming iss-N ids alone and Delivers: lines naming itd-N ids alone (internal/core/landing/prbody.go:46-47,82), and leaves merge commits out (prbody.go:62). `Refs: spc-9 step 3`, the chapter's own example at line 69, is dropped, as are `Refs: itd-N` and `Refs: #12`.
- iss-261104055436275507-library.md:141 says an agent never runs the flip and, since the binary cannot tell a person from an agent, that the rule lives in the command pages. The shell guard also refuses it: entry abcd-source-ledger-flip (internal/core/guard/personacts.go:57), taught by abcd rules SHELL and named at commands/library.md:219.
- iss-2611040554372807.abcd/development/brief/04-surfaces/16-lint.md:87-92 says four surfaces judge the harness-leak class and that `abcd lint outbound` is the only one judging text before it is public. scanner.CheckOutbound also runs before text goes public at internal/core/guard/forge.go:523, internal/core/landing/prbody.go:115, internal/core/claim/prepare.go:426, internal/core/claim/withdrawforge.go:541 and internal/core/release/ingest.go:560, and internal/core/implement/loop/land.go:785 scrubs a pull request's text before posting.
- iss-2611040554385570.abcd/development/brief/04-surfaces/16-lint.md:130-132 says each finding carries a `file`. Finding.File is omitempty (internal/core/repolint/repolint.go:70) and a site-gates finding with no source span has none (internal/core/repolint/rule_site.go:83). commands/lint.md:39 states this exception; the chapter does not.
- iss-261104055439346005-intent.md:508 says an intent cannot be planned without an Acceptance Criteria section carrying at least one Given-When-Then bullet, and that everything in planned/ and shipped/ has therefore passed it. hasAcceptanceCriteria (internal/core/intent/intent.go:163) counts top-level -/* bullets only: a draft whose whole section is one plain bullet with no Given, When or Then plans with exit 0.
- iss-261104055441886505-intent.md:511 and :525 say an intent in superseded/ with kind_at_supersession: bundle-member carries bundle: null and bundle_at_supersession: <bundle-id>. intents/superseded/itd-20-top-level-abcd-dispatcher.md has kind_at_supersession: bundle-member, keeps bundle: spc-83-operator-surfaces and has no bundle_at_supersession.
- iss-2611040554426316The land chapter says mergeGate replaces ruling AM1, citing 34-build.md (.abcd/development/brief/04-surfaces/38-land.md:154). 34-build.md does not name AM1, and this line is the only occurrence under .abcd/development/brief, so the citation leads a reader to nothing. The ruling is recorded in .abcd/work/decisions/dcn-2609300000000025-the-implement-loop-arms-auto-merge-only.md.
- iss-261104055443391504-launch.md:300 says each gate row carries a tier, 04-launch.md:385 says two rows report without one (citation baseline, semantic receipts), and lines 305-368 list the secret scan, merge hold and installability smoke as hard-fail gates. abcd launch --dry-run --json gives no tier on five rows: secret+pii-scan, installability-smoke, merge-hold, citation-baseline and semantic-receipts (internal/core/launch/dryrun.go:153,165; internal/core/launch/mergehold.go:112).
- iss-2611040554435804.abcd/development/brief/04-surfaces/16-lint.md:160 describes privacy-hygiene as flagging absolute local paths on any tracked text line, with only the line waiver as an exemption. The rule also exempts a home path whose username segment is a registry persona other than this machine's own user (internal/core/repolint/rule_privacy.go:409, isPersonaHomeSegment), and accepts in a code comment that another person's home under such a name goes unflagged. The chapter states neither.
- iss-2611040554443311The session chapter's blueprint section names two files, render.yaml and .abcd/relay/Dockerfile (.abcd/development/brief/04-surfaces/37-session.md:118-129), and its page section relies on .abcd/relay/relays.json (line 153) without saying what writes it. `abcd session blueprint --relay-origin` and `abcd session setup --relay-origin` also write relays.json, and `abcd session setup` writes .abcd/relay/github-app.json. Those writes are stated only in the verb's help and commands/session.md.
- iss-2611040554457784The session chapter says the blueprint refuses outside a checkout abcd manages and for a release that publishes no checksum for the linux/amd64 binary (.abcd/development/brief/04-surfaces/37-session.md:127-129). It also refuses a release older than a floor, naming firstSessionRelease (internal/core/session/blueprint.go:99, refusal at :466), and a checkout whose origin names no repository on github.com. The chapter states neither. The floor is itself stale: its comment says the cut that first ships the verb sets it, yet it reads v0.17.0 while the changelog's 0.16.0 section (CHANGELOG.md:85) already describes the session page, so the refusal can direct a person to a release that does not exist.
- iss-2611040554460352The session chapter says the page's content-security policy loads scripts and styles from the page's own origin only (.abcd/development/brief/04-surfaces/37-session.md:145-147). internal/surface/session/web/index.html:6 declares style-src 'self' 'unsafe-inline', so inline styles are admitted as well; only script-src is 'self' alone.
- iss-2611040554479009.abcd/development/brief/04-surfaces/22-site.md:160-166 says every repository gets the same seven pages and the pages block cannot add one, and .abcd/development/brief/04-surfaces/22-site.md:249-254 ends its written list with nothing else, nowhere else. A build also writes contributors/, references/, record/decision-log/, record/development/ and record/foundations/. PageNames (internal/core/site/pages.go:37) has seven names, with no switch for contributors or references, and the decision pages exist only under record.decisions. Lines 246-248 mention contributors and references only as inputs.
- iss-2611040554494843.abcd/development/brief/04-surfaces/22-site.md:256-261 says one input reaches past the durable record, the issue-ledger switch, and .abcd/development/brief/04-surfaces/22-site.md:340-348 enumerates the record export without decisions. record.decisions (internal/core/site/manifest.go:313, set in .abcd/site.json) publishes .abcd/work/decisions/ as a decision log and a page per record, and record.json carries a `decisions` key. Its only brief mention is .abcd/development/brief/05-internals/10-site.md:105. Bare `abcd site` reports only the issue ledger.
- iss-2611040554507299.abcd/development/brief/04-surfaces/22-site.md:114-117 and 154-156 describe setup as writing the site's settings and workflow, say the build and gate refuse settings of the other shape, and say abcd's composed site is not a project site. Where .abcd/site.json is a composition, `site setup --project` writes .abcd/project-site.json and .github/workflows/project-site.yml beside it, as this tree carries, and `abcd site build --project` reads that file first (internal/core/site/project.go:168-180). The chapter names neither file.
- iss-2611040554512469.abcd/development/brief/04-surfaces/22-site.md:96-99 describes the remote stages' confirmation with no case for a site already live, and --replace-existing appears only in the flag appendix at .abcd/development/brief/04-surfaces/22-site.md:397. `site setup --help` says that flag publishes over a site the host already serves without asking, and that --yes without it refuses when such a site exists. commands/site.md:284 and docs/reference/cli/commands.md:5746 carry this; the chapter's prose does not.
- iss-2611040554515542.abcd/development/brief/04-surfaces/21-update.md:26-30 names the launch preview and the release cut as the other commands reaching the release origin, and commands/update.md:18 calls --fetch-baseline the one other flag that does. `abcd session blueprint` and `abcd session setup` also read a release's checksums.txt from that origin (internal/surface/cli/session.go:70, 534, 798; .abcd/development/brief/04-surfaces/37-session.md:123).
- iss-2611040554531297.abcd/development/brief/04-surfaces/21-update.md:189-192 says the salvage that discards its output is run by the per-prompt, per-command and pre-compaction hooks. hooks/post-tool-use.sh, matched to the question tool, and hooks/permission-request.sh run the same `bootstrap.sh --unseen` (hooks/hooks.json). .abcd/development/brief/05-internals/03-configuration.md:1833-1836 counts five events.
- iss-261104055455620705-internals/03-configuration.md:3-5 says installing asks four questions and :49-50 lists visibility, the docs target, the oracle backend and the deep scan. internal/core/ahoy/prompt_help.go:136 keeps the backend question off while only one choice has an adapter, recording host-delegated with a note; 05-internals/01-agents.md and commands/ahoy.md say the same. --oracle-backend still sets the value.
- iss-261104055456960205-internals/03-configuration.md:574-578 calls the interview's settings one key, interview.list, and :9-10 and :669 speak of that key alone. internal/core/layered/interview.go:23,34 also reads interview.redrafts, how many times a refused question is redrafted, the repository's to set and refused from the machine layer. No file under .abcd/development/brief/ names it.
- iss-261104055457604505-internals/03-configuration.md:853 cites (implement/loop, WorktreeStoreRel) for where a build lane's worktree is created. No Go file under internal/ or cmd/ defines WorktreeStoreRel. The path itself is right, built through internal/abcdhome.
- iss-261104055457642805-internals/03-configuration.md:700 says no run seam ships, so nothing drains today. abcd intent audit --owed ships and its help says it lists or drains owed fidelity reviews; 05-internals/01-agents.md:153-154 says it drains the owed set. What is staged is automatic draining at the seam's iteration boundary.
- iss-261104055459186005-internals/03-configuration.md:1491-1513 gives the prompt router's --json envelope as text, session_title, injected, recalled, active and error. abcd hook prompt-router --json also returns fill and bracket, neither in the table nor the example. The table calls recalled the ids of memory notes (:1481 similarly), while the verb's help says it names notes and pages, a page as page:<filename>.
- iss-261104055500213205-internals/03-configuration.md:1883-1893 lists the families under development/. The directory also holds agents/ (the roster and prompt-version log, 05-internals/01-agents.md:72), releases/ (04-surfaces/04-launch.md:113) and retrospectives/ (04-surfaces/09-reflect.md:190). The list names none of them.
- iss-261104055500554605-internals/03-configuration.md:1292-1302 and the shared-work row at :1310 list what .abcd/ and .abcd/work/ hold. The tree also holds .abcd/relay/ (github-app.json, written by abcd session setup, and the blueprint's files per 04-surfaces/37-session.md:118-121), .abcd/work/publish-surface.txt (the intake runbook's fence) and .abcd/work/brief-review-flags.json (internal/core/lint/briefflags.go). The chapter names none of them.
- iss-261104055502163705-prompt-quality.md:120-124 says the entries that state no delta anywhere are the five prompts hardened on 2026-08-19 and one cold-reading bump. In .abcd/development/agents/CHANGELOG.md, cold-reading-widening 0.2.0 states none, cold-reading-entailment 0.1.3 and cold-reading-detection 0.1.4 only point at widening's entry, and the renames intent-auditor 0.1.1 and lifeboat-reviewer 0.1.1 state none in the entry or its section preamble.
- iss-261104055503903406-delivery/01-build-sequence.md:55-56 says abcd ahoy install carries its configuration as flags rather than a wizard. Install runs a question flow: 04-surfaces/01-ahoy.md:905-917 and commands/ahoy.md 'The setup flow' describe its plan screen and questions, --answers answers it from a file, and a --yes run ends partial, sending the commit checks, identity, routing table and drain rule to a terminal run; none of those has a flag.
- iss-261104055503957506-delivery/01-build-sequence.md:20-22 says every capability after the first milestone is a native default behind an already-wired interface with an optional external adapter beside it. The same chapter says at :33 that the scanner is the one capability seam standing and at :41-47 that the oracle, history, spec and run seams are planned, with history and spec shipping as core packages with no adapter interface behind them. internal/adapter has gitleaks, hosting, openaiapi, repoprompt, scanner and tailscale only.
- iss-261104055505547706-delivery/01-build-sequence.md:92 says a vendor memory harvest is an opt-in, read-only source over the memory substrate, unmarked, though the chapter marks unbuilt items as design targets (:111, :129, :134). No Go source reads memory.harvest and no verb or flag offers one; 05-internals/03-configuration.md:684 and :1323 list it as staged. The shipping abcd lab harvest is unrelated.
- iss-261104055506016506-delivery/01-build-sequence.md:157-159 says the disembark pack reads the source, synthesises the lifeboat and runs the host-delegated audit. abcd disembark pack prints the destination, file count, manifest hash and voyage line and writes no review. The audit is abcd disembark review, which an operator runs afterwards with the lifeboat-reviewer's output (commands/disembark.md:240-250).
- iss-261104055506918906-delivery/01-build-sequence.md:109 says native, CLI, API and MCP adapters are opt-in for an operator who wants abcd to reach a model directly, unmarked. 05-internals/01-agents.md:190-204 says three ship: the OpenAI-compatible provider API, a model CLI runner, and RepoPrompt over MCP for a build lane's reviews alone. No native adapter exists, and --oracle-backend records a value that routes nothing (internal/core/ahoy/prompt_help.go:124).
- iss-261104055508304806-delivery/02-verification-matrix.md:26 says a second install at the same version gives a transparent re-confirm of visibility. A second abcd ahoy install prints nothing about visibility and no non-test source under internal/core/ahoy contains such a step; the already_up_to_date headline (install_summary.go:425) does not mention it either. The matrix's preamble says rows without (staged) describe the binary today.
- iss-261104055509559706-delivery/02-verification-matrix.md:28 says that on a private-to-public flip the user is shown the resulting tracked-versus-ignored list. The gitignore does change, but abcd ahoy install --visibility public prints only that it kept abcd's private files out of git and the visibility change; --details adds the files written, and the --json result has no field for such a list.
- iss-261104055509795106-delivery/02-verification-matrix.md:39 says a re-run over an abcd-produced destination confirms, then regenerates in place. Nothing confirms: abcd disembark pack has no confirmation flag, internal/core/lifeboat/pack.go has no confirmation step, and a re-run with stdin closed exits 0 at once. The re-run also discards what later steps wrote into the lifeboat: press-release.json, press-release.md and review/ were gone after a re-pack, and neither 04-surfaces/02-disembark.md nor commands/disembark.md warns of it. The row's refusals of a non-empty foreign directory and a malformed provenance file hold.
- iss-261104055511050806-delivery/02-verification-matrix.md:48 says include and exclude are resolved from the bundler's own rules and, as staged, that the launch core reads no per-repo allow-file. internal/core/launch/includes.go:14 reads .abcd/config/launch-payload.json, and 04-surfaces/04-launch.md:508-510 calls that list the only mechanism that can put a path into the release artefact. Only the structural deny of .abcd/ is the bundler's own, and the file cannot override that.
- iss-261104055512021406-delivery/02-verification-matrix.md:63 says abcd capture "<text>" writes an issue and reports the id, slug and severity. That form is refused with exit 2 because --remedy is required, and nothing is captured. With --remedy, the text output gives id, status and path, and the --json result carries id, slug, path, status, uncommitted, no_location, match and ledger; neither reports the severity.
- iss-261104055512735006-delivery/02-verification-matrix.md:57 says bare abcd intent shows intents grouped by state with the next actions to take. It prints one line of counts per state, a specs count, any intent-to-spec link lines and two fixed routing lines saying where to file new work. It lists no intent by state and names no next action for one.
- iss-261104055514266006-delivery/02-verification-matrix.md:98 says a renewal, take-over and release are each one child commit and nothing is ever deleted or forced. abcd reserve --sweep --apply deletes spent reservation branches, .github/workflows/reservation-sweep.yml runs it on a schedule, and 04-surfaces/37-reserve.md:58-71 documents that as the verb's fourth form. No matrix row mentions the sweep.
- iss-2611040555153652The librarian glossary term says an agent runs it with `abcd library pack`, in the present tense (.abcd/development/brief/glossary/core/librarian.md:17). The binary registers no such command: it is refused as unknown, and the sub-commands are add, ask, cite-check, declassify, ingest, init, ledger, lint and sync-banlist. The backing intent itd-2610141646126492 is a draft, and the term's status: draft records term maturity, not that the verb is unbuilt.
- iss-2611040555168794The skills chapter says a skill added without adding the skills directory to the payload's include list passes the record gate and is missing from the release (.abcd/development/brief/05-internals/08-skills.md:120-124). TestBundleShipsEveryPluginSurface (internal/core/launch/payload_completeness_test.go:40) fails on a skills/ directory that is neither in the includes nor in surfaceExcludeReasons, and it runs in `go test ./...`, so in preflight and CI. Run against a copy holding skills/foo/SKILL.md with the includes unchanged, it failed. Such a skill cannot land by the normal route.
- iss-2611040555175524The launch chapter says the light tier fails a file present in the tree but excluded from the payload (.abcd/development/brief/04-surfaces/04-launch.md:438), and it counts the convention register, the command, agent, skill and hook paths a plugin is expected to carry, in the declared surface (lines 423-424). conventionEntries lists only what the payload tree already holds (internal/core/launch/installsurface.go:349), so a page reached by convention but outside the includes yields no entry and no finding. Only a path declared explicitly, by a plugin.json key or a hook command, gives the missing-path finding (internal/core/launch/smoke.go:123-127, internal/core/launch/smoke_test.go:47,53).
- iss-2611040555180432The embargo chapter says the check reads, over a commit range, messages and added lines (.abcd/development/brief/04-surfaces/37-embargo.md:86-87), and `abcd embargo check --help` says the same. The check also scans the names of files a commit adds, reporting 'a file name the commit adds' (internal/core/embargo/check.go:316). commands/embargo.md:175 states this; the chapter and the help do not.
- iss-261104055519518504-surfaces/03-embark.md:17 says what ships is the unpack and the probe. abcd embark also ships lessons (abcd embark --help), which the chapter's own table at :41 and bullet at :57 record as shipped.
- iss-261104055520385304-surfaces/03-embark.md:143-146 says both operands are refused when reached through a symlink inside a checkout and that outside every checkout the path is taken as given. Only a symlinked ancestor is taken as given there: a lifeboat or target named directly by a symlink outside any checkout exits 2 with 'is not a directory'. internal/core/lifeboat/operand.go separates the leaf-only IsRealDir gate from the ancestor proof.
- iss-2611040555212928.abcd/development/brief/04-surfaces/17-guard.md:997-998 gives `rm -rf "$DIR"/*` with DIR unset as a target an allow does not see. `abcd guard check` blocks it, exit 1, under the bundled entry rm-unguarded-variable-path (internal/core/guard/defaults/guard.json:126; commands/guard.md:1082), and likewise the `$DIR/*`, `"${DIR}"/*` and `"$DIR"/x` spellings. The chapter never names the entry.
- iss-2611040555220611.abcd/development/brief/04-surfaces/17-guard.md:809 and 1019-1024 say an allow does not see what a variable carries from an earlier command, with `p=$(pgrep make); kill $p` as the example, and call whether to read it an open ruling. A variable assigned on the same line is read and blocked: that example, a process-substitution path handed to bash, a command held in a variable and run through eval or sh -c, and pkill as a variable's value, each exit 1. Only a value set before the line stays allowed. commands/guard.md:683 documents this.
- iss-2611040555239973.abcd/development/brief/04-surfaces/17-guard.md:1013-1014 says an allow does not see a pid list a kill reads through a file or from a `ps | grep` chain. `ps aux | grep make | xargs kill`, the awk and `kill $(...)` forms and `pgrep make > p; kill $(cat p)` all exit 1 under kill-by-search. commands/guard.md:992 states that a filtered ps listing is a search.
- iss-2611040555249487.abcd/development/brief/04-surfaces/17-guard.md:1034-1036 calls the check's own help the fuller statement of the list, with a worked example for each. `abcd guard check --help` is the shorter list and lacks the chapter's symlink `..`, `~user`, relative `..` and variable carry-in items. It also lists `--$VAR` and a variable as the program among what an allow does not see, yet `git push --$VAR origin main` and `$GIT push --force` both exit 1, as .abcd/development/brief/04-surfaces/17-guard.md:803 says. The fuller statement in the tree is commands/guard.md.
- iss-2611040555254496.abcd/development/brief/04-surfaces/17-guard.md:508-509 says `.abcd/guard.json` must declare schema_version 1 or the guard refuses to run at all. That holds for the check, exit 2. On the hook the repository's overrides are dropped with a notice and the bundled hazards still decide, so a force push is still denied, as .abcd/development/brief/04-surfaces/17-guard.md:492-496 describes.
- iss-2611040555271283.abcd/development/brief/04-surfaces/19-identity.md:103-105 says a surface whose candidate files are all absent is skipped rather than reported. `abcd lint identity` prints each such surface with the state absent, and its JSON lists it with status `absent`. Only bare `abcd lint` leaves it out, and it counts as no drift.
- iss-2611040555277268.abcd/development/brief/04-surfaces/11-history.md:147-149 says --out is refused through a symlink at any level inside a checkout and that outside every checkout the path is the operator's own. A symlink as the last component of --out is refused outside a checkout too, exit 1, reporting that --out is not an existing directory (internal/surface/cli/history_reconstruct.go:118, fsutil.IsRealDir uses Lstat). A symlinked parent outside a checkout is followed, as the chapter says.
- iss-2611040555295193.abcd/development/brief/04-surfaces/19-identity.md:121-122 says the identity-positioning rule is gated on a committed registry. The gate tests presence on disk (internal/core/repolint/rule_positioning.go:42): with `.abcd/positioning.json` untracked, bare `abcd lint` still ran the rule and reported under it. .abcd/development/brief/04-surfaces/16-lint.md:162 states the presence gate correctly, and the comment at internal/core/repolint/rule_positioning.go:40 repeats the chapter's wording.
- iss-2611040555309558.abcd/development/brief/04-surfaces/27-implement.md:265-266 says that without its wait flag the check exits 0 on every status and never refuses. That holds for statuses, but `abcd implement load` with no flag exits 2, naming --site's values preflight and eval-harness. The chapter mentions `--site` at lines 139 and 163 and in its appendix at line 720, without saying it is needed or what it takes; commands/implement.md:915 gives both.
- iss-2611040555313250.abcd/development/brief/04-surfaces/27-implement.md:117 and following list the conditions a second session's refusal line names. A second session setting the window's mode is refused with condition `second_session_sets_no_mode` (internal/core/implement/session.go:341), which no chapter or command page names. .abcd/development/brief/04-surfaces/27-implement.md:88 states the rule without the condition.
- iss-2611040555321903The memory chapter gives exit 1 for 'a machine file the read refuses' with no scoping to a sub-verb (.abcd/development/brief/04-surfaces/37-memory.md:97), and commands/memory.md:125-126 repeats it. Only `memory add` and `memory remove` exit 1 on such a file. Bare `abcd memory` and `abcd memory list` exit 0, name the file as unreadable and report no notes from it.
- iss-2611040555330992The memory chapter gives exit 2 for a refusal by the gate (.abcd/development/brief/04-surfaces/37-memory.md:98), its gate section lists a degraded scanner and an unreadable private-names store among the refusals, and commands/memory.md:125 says every refusal exits 2. Both of those refuse the note, write nothing and exit 1, because only memnote.GateError and the named field and record errors map to 2 (internal/surface/cli/memory.go:143-147). A banlist match and a scanner span do exit 2.
- iss-2611040555347290.abcd/development/brief/04-surfaces/26-mode.md:97-103 says every refusal of these verbs exits 2 with nothing written and that ending the mode refuses only with no checkout, no home or no root commit. With HOME set to a directory that does not exist, `abcd mode autonomous` and `abcd mode queue <step>` exit 1 with an open error, and `abcd mode back` exits 0, printing both that the record was closed without the store's lock and that there is nothing to end, though no record exists.
- iss-2611040555367558.abcd/development/brief/04-surfaces/23-reading.md:40-46 and the refusals it lists do not include this case. The reported refusal on the changelog no longer fires on this tree, whose CHANGELOG.md:30 was reworded, but the cause stands: with a code span holding an opening `<h1>` restored at that line and committed, `abcd reading assemble` exits 2 at detection, entailment and widening, dry run included. It reads from the tag to the end of the file as one raw-HTML heading title (rawHTMLHeading, internal/core/reading/project.go:1032-1035) and quotes about 597 KB of the file in the refusal. A code span renders as text, so no heading exists. Every changelog line or included document naming that tag in backticks stops all readings until the text is reworded.
- iss-2611040555379758.abcd/development/brief/04-surfaces/23-reading.md:364-381 describes the dispatch form and its refusals with no size limit. ReadParked reads the bundle under reading.MaxFileBytes, 4 MiB (internal/core/reading/parked.go:68; internal/core/reading/assemble.go:298; called first at internal/surface/cli/reading.go:758), and assembly writes bundles with no such cap. On this tree a detection bundle of 7.5 MB and a widening bundle of 7.5 MB exceed it, so `reading ingest --dispatch` exits 2 with a bare file-exceeds-size-cap message before any provider is contacted, and the documented harness-route refusal is not what prints for such a run. An entailment bundle of 2.3 MB is under the cap.
- iss-2611040555387360Bare `abcd reading` prints `exclusion rows: 40, asserted into every manifest` (internal/surface/cli/reading.go:439). Manifests carry 30 at detection, 28 at entailment and 31 at widening; the others bind to particular positions, such as comparative (comparativeExclusions, internal/core/reading/include.go:788). So 40 is the table's size. .abcd/development/brief/04-surfaces/23-reading.md:103 says only that the floor rides in every manifest, which holds.
- iss-2611040555394037.abcd/development/brief/04-surfaces/09-reflect.md:53-54 and 71-72 say `abcd reflect <release-tag>` renders each intent's honoured, diverged and missing gap counts, plus verdict and gap distributions and the dates of this tag and the previous one. The text render (internal/surface/cli/reflect.go:341, 368) shows the acceptance rollup per intent and a metrics line of shipped, audited, unaudited and this tag's date. The --json form carries the gaps, the rollup and, where there is a previous tag, its date (internal/core/reflect/seed.go:102-105).
- iss-2611040555404486.abcd/development/brief/04-surfaces/29-report.md:118 says the bare `/abcd` board carries the count as its `inbox:` row. Bare `abcd` and `abcd --format markdown` draw no such row with a report waiting; `abcd --view facilitator` does, and --json carries the `inbox` object. commands/abcd.md:135-137 has the same gap.
- iss-2611040555429917The reserve chapter's Exits section enumerates what exits 3 and puts every other refusal and failure at exit 2 (.abcd/development/brief/04-surfaces/37-reserve.md:945). The one-release-at-a-time back-off described at line 560 is not listed, and reserving a release while another release is being cut exits 3 (internal/core/claim/withdrawact.go:1351, internal/surface/cli/reserve.go:538-539), including when the same person and copy hold the other release.
- iss-2611040555430199The scribe chapter says ingest proves the parked context and then runs its checks (.abcd/development/brief/04-surfaces/32-scribe.md:79), and its Disclosed limits name no size limit. `scribe ingest` reads the context under reading.MaxFileBytes, 4 MiB (internal/core/scribe/ingest.go:408), while `scribe assemble` writes it with no cap (internal/core/scribe/assemble.go:392). Over this repository's ledger of 4,797 records assemble exits 0 and parks a context of about 9.46 MB, and every ingest of it, --dry-run included, exits 2 with 'reading the context: fsutil: file exceeds size cap'. The scribe cannot land a record in a repository with a ledger this size, and the refusal comes only after a session has transcribed against that context.
- iss-2611040555444858README.md:59 and :64 link abcd's development record and principles at its GitHub Pages address, which answers 404 until the project site is set up with abcd site setup; a test holds the address on purpose, and the older address still answers.
- iss-2611040555455335abcd build --auto-plan is new since v0.16.0 and plans a draft with no person present, but the v0.16.1 changelog carries no line for it, because no record in the cut covers it; only a fix to it appears.
- iss-2611040555462905The prompt hook shrinks injected rules, notes and pages as a session's context fills, a behaviour change with no line in the v0.16.1 changelog, because no record in the cut covers it.
- iss-2611040555482208Validation rounds run two reviewers per code-review role by default, which affects agent spend, with no line in the v0.16.1 changelog, because no record in the cut covers it.
- iss-2611040555499163The question.* limits and abcd guard question are new since v0.16.0, and default rows rose from 24 to 32, with no line in the v0.16.1 changelog, because no record in the cut covers them.
- iss-2611040555506702interview.redrafts is named in the v0.16.1 changelog but documented on no page under docs/ or commands/; only agents/planning-interviewer.md mentions it.
- iss-2611040712338963Parallel stages share one session scratchpad with nothing to keep them apart: on 2026-11-04 a release-gate checker reused names another checker was using, committing and installing into that checker's test repository for three minutes, so findings from that window had to be rechecked.
- iss-2611040712342157A release gate's hand-run checkers can silently leave items unchecked: on 2026-11-04 a brief saying group N was read as 0-based by some and 1-based by others, so two groups checked a neighbour's items and 14 of 50 items had no checker; only a coverage check against the plan showed it. Nothing in the procedure requires that check before a receipt is written.
- iss-2611040712354406The release composer can write text that breaks a later verb: the v0.16.1 changelog's first draft carried an HTML heading tag in a code span, which reading assemble read as a raw heading to the end of the file and refused at three positions, and neither the ingest nor the docs gate noticed. The reader's bug is captured separately; the gate between the composer and the commit runs no such consumer.
- iss-2611040712366155abcd library ledger with no flag exits 2 on a real corpus with a message about an invalid record, because the bare form appends, and it does not point at --list; a published advisory tells people to run that bare form to review flips.
- iss-2611040712376827Docs fixes can break a test pinning brief wording that their own check did not include: internal/core/capture's test pins invariant 19, and a fix stage running only the surface, fidelity and lint packages did not reach it, so the failure appeared at preflight after both release gates had passed.
- iss-2611040712378570abcd implement load with no --site exits 2 and says the value given is not repeated here, when no value was given.
- iss-2611040712384537land --record-review refuses a return with no ### Verdict heading, but nothing tells a reviewer so when the prompt asks for a verdict line, and a reviewer's verdict on the line after its head line is unambiguous: two reviews on 2026-11-04 had to be reformatted by hand.
- iss-2611040712399867A fixed test budget can hide behind an earlier test warming something up: TestAPreflightPastItsBoundIsKilledWithItsGroup's two-second bound passed for months because another test ran make first, and failed every time once the macOS suite was sharded, since a cold make on a fresh runner goes through xcrun. Sharding is likely to surface more of these.
- iss-2611041015338189The shell guard's bundled registry refused a force push but not the other commands that rewrite published history or remove the means of recovering from a rewrite. git filter-repo, git filter-branch, git update-ref, git replace, git reflog expire, git gc --prune=now, git push --mirror, git send-pack --force, git fast-import --force and a gh api PATCH of a ref with force=true all ran unchallenged.
- iss-2611041016350835The release workflow's verify job ran go test with no -timeout, so a package past go's 10-minute default failed the job with no test failing, after the merge queue had passed the same tree under a longer limit: on 2026-11-04 internal/core/implement/loop stopped the v0.16.1 release at 600 seconds, before the tag. The scaffolded release workflow carries the same step.
- iss-2611041104094416The identity scanner flags every word-bounded occurrence of the caller's account name, and abcd's cloud setup names its account abcd, so record text holding the product's name read back as [redacted-user] and launch renders hard-failed on a clean tree in a cloud session.
- iss-2611041115564940The shell guard's check on its one-shot allow store refuses a harmless command when that store's directory name appears anywhere in its line: on 2026-11-04 a git add and a mv of an issue record whose generated slug happened to hold those words, and a read-only grep beside a pipe, were each refused as a write to the store.
- iss-2611041115574607The release workflow's budget test checks each go test step alone, not cumulatively, so a scaffolded repository's Test step plus a hung race package can pass it while its 15-minute job is cancelled with no goroutine dump; and the verify job has no watchdog, so a late race package in abcd's own profile can pass the job's limit the same way.
- iss-2611041338455722Trimming the Go build cache by age does not bound it: on 2026-11-03 the cache reached 323 GB with every entry used within two days, so a prune's trim frees nothing on a machine that busy, and the load gate still stops work on a full disk.
- iss-2611042224527148The release path runs no macOS suite, though the product thinker ruled that each release cut runs its own before releasing, whatever the nightly said. With macOS out of the merge queue, a macOS-only regression merged after a nightly run could be tagged and published on Linux checks alone, since every job in release.yml and auto-release.yml runs on ubuntu and a red nightly stops nothing.
- iss-2611042320121086The guard reads some forge calls that touch no ref as a PATCH on a ref. Since the history hazards landed in #1394, gh api -X PATCH on repos/$O/$R/properties/values with --input is refused by gh-api-ref-input, because forgeOtherRoutes does not list that route, so the variable path can still be a ref; and a -p "$P" value reads as a possible ref path, because the hazards' value_flags omit -p and --preview. Spelling the path or the flag out avoids both.
- iss-2611042320130590The pty and drain signal tests fail when the test process was started from one that ignores SIGINT: a cloud session reported it on 2026-11-04. A child inherits the ignored disposition, which these tests do not set back.
- iss-2611042320135958internal/surface/dashboard's TestServerInheritsOnlyWhatItNeeds failed once under load with a broken pipe, then passed, in a cloud session's preflight on 2026-11-04: the fake server reports its environment and exits, and when it exits before start has handed it its configuration, start's refusal appears to name the failed write instead of the report the test reads.
- iss-2611042320148804abcd land's stacked-branch check runs only before it makes a fresh arming: #1398's stackedOn sits in the arming branch of internal/core/landing/land.go, so it guards neither the 30-minute toggle that re-arms an arming land already made nor the build loop's own land stage (toggleArming in internal/core/implement/loop/queue.go), as the session that wrote it reported. iss-2611031719581061 holds the fresh-arming case.
- iss-2611042320157632A coordinator that asks a question through the host's question tool stops all its own progress until the person answers, its wakeups and re-arming included: on 2026-11-04 that left one idle for over an hour while its sub-agents ran on.
- iss-2611050035192370Nothing reads a failed scheduled run of ci.yml: the nightly macOS suite and the nightly Linux checks can stay red on the default branch with no session told, and since the release path now runs its own macOS suite the first anyone hears of a macOS regression can be a cut that stops. The alert is not small enough to add beside the gate: the prompt's STATUS block is read from disk alone and promises never to touch the network, so the cache needs a refresh outside the prompt, or the alert stays silent in any session where nobody ran the verb; the workflow's name is abcd's own, while abcd status serves every managed repository; and the verb's JSON, its command page, its brief chapter and the generated reference all change with it.
- iss-2611050136321099A narrow run reads a whole waiter's age as how long it has been overdue, not how long a slot has been free for it, so a waiter that queued for forty minutes is overdue the moment a preflight exits, and narrow runs stand aside for the minute or so it takes to open; a bounded cost, since one wait spends at most five minutes standing aside
- iss-2611050535437225abcd land withdraws the arming before a push that moves an armed pull request's head, and arms the new head only where the merge gate does; the committed pre-push hook refuses a fast-forward it reads as moving that head.
- iss-2611050753557564A terminal drive ends its run at a limit resetting past eight hours and after eight hours of outage or no movement, so an unattended run stops at a limit whose reset lies past eight hours.
- iss-2611050754187531Releases are numbered vMAJOR.MINOR.PATCH, derived from each record's impact. The product thinker asks whether a calendar-based scheme, for example vYYYY.MM.DD.x.y, would serve better now that releases are planned to a weekly rhythm.
- iss-2611050819312152A walled stage's shell finds no cache of a toolchain other than Go's: its home is emptied at each launch and only Go's caches are named, so a repository built with rustup, cargo, npm or the like downloads or fails in every stage, though abcd serves any repository's product.
- iss-2611050840142097TestConcurrentFailedIngestsOfOneReceiptFileOneIssue (internal/core/capture/auditowed_test.go) failed on a macOS shard with 'could not acquire mint lock within 5s', and its queue entry was dropped with no defect behind it. Four concurrent ingests contend for the intent store's mint lock, whose wait is a fixed 5 seconds (mintLockTimeout in internal/core/intent/create.go), and on a loaded runner a holder can outlast it. The wait is the production default, so a real ingest on a loaded machine can lose the same race.
- iss-2611050840151381A host review can stay unlisted in the launch ledger. ListHostRole (internal/core/implement/loop/drive.go:171) writes the placeholder only after DriveReview returns, at the end of the step that handed the role out (internal/surface/cli/build.go:1317). A DriveReview that returns the run's busy lock skips it, a step killed between the two never reaches it, and a later step reads the await with handed false, so nothing lists the role afterwards and the run's listing shows fewer agents than it had.
- iss-2611050840164467An auto-plan review on a role routed to a runner goes unlisted in the launch ledger. Drive keeps an auto-plan run's reviews on the host by dropping its runner configuration (internal/core/implement/loop/drive.go:109), but ListHostRole (drive.go:172) still asks the configured route, finds a runner rather than the host and writes no placeholder, so the host agent that runs the review has no line.
- iss-2611050840333155A go test started outside the load gate adds load that only a waiter can see. The gate names such runs by pid on its own waiting line (iss-2610241130157455) and the LOAD rules teach gating them, but nothing shows them when no waiter is there to print that line, and nothing tells a session or a sub-agent at the moment it starts one, so the one-minute load rises with no cause on record.
- iss-2611050840338995A running drain's own order is fixed: category, then severity, then its tie-breaks (orderEligible in internal/core/capture/eligible.go), and its flags can only hold an issue back (--skip), so it cannot be told which eligible issue to take first. The route a person has today is to build one issue themselves with `abcd build <iss-N>` (internal/surface/cli/build.go:102), under the same drain rule. Inside a running drain, an issue a person or a release cut wants sooner waits behind every eligible issue ahead of it.
- iss-2611050840341934A major record captured mid-cycle refuses the next release cut (GuardFindings), while a drain under the baseline rule takes only nitpick and minor, so on a scheduled cut with no one present one such record holds the release. The ways past it, a fix, a wontfix or abcd capture defer, are each a judgement no unattended stage is given. dcn-2611031615094092 settled this for one experiment only, ruling that a refusal would wait for the product thinker and that a daily digest would list what waited for them. For scheduled cuts beyond that experiment, nothing says who is to make the judgement.
- iss-2611050840353717A long unattended run on one machine has nothing that restarts it after the machine reboots, and full-disk encryption can hold the machine at its login screen until someone signs in, so an update or a power cut ends the run and nothing says so. The restart path (itd-2611041549461012) begins with the next session's resume; nothing starts that session.
- iss-2611050840360484Nothing watches machine health for a long unattended drive: memory pressure, a growing system daemon or load can climb for hours while stages keep starting. The load gate reads load and memory before a gated run opens and not during it (the Makefile's preflight recipe and the race gate in its preflight-stages recipe; itd-2611012048006057 added the memory floor), and a drive's agent stages between gated runs read nothing, so a stage starts whatever the machine reads and a slow climb is never named.
- iss-2611051719379115`abcd land` runs the mention check only on a body it composes, and never reads the body of a pull request that already exists (`PRStateQuery`, `internal/core/landing/land.go`). So a body written by hand that names a record without a `Refs:` or `Resolves:` line fails the resolution gate within about a minute of the pull request opening, and a later land run names the `attribution` check as held without saying why. This happened on #1408 on 5 November.
- iss-2611051719381143An armed pull request whose required check failed before it reached the queue stays armed and blocked. `abcd land` names the failed check only when it is run again, and the status board never does, so nothing says so between land runs and a queue watch sees an empty queue either way. This is the part before the queue. A drop from the queue is iss-2611022247147314, and retrying a drop that is not the pull request's own fault is iss-2610110401224302.
- iss-2611051719396028A status store that cannot be written, from a full disk or a changed mode, means a due prompt starts no refresh and says nothing, so a kept green can stay silent for up to 48 hours.
- iss-2611051719413677Test reuse's classifier does not follow a program name held in a local variable, so a test that starts a program that way can replay locally until the hosted run. The classifier is a best-effort read of test source, and the hosted run reuses nothing.
- iss-2611051719429185Test reuse's wording still says a release cut reuses nothing, though that is now a person's option: the `-fresh` flag text (`cmd/check-tests/main.go:48`), the run text (`internal/testreuse/run.go:171`) and a lint test (`internal/core/lint/testreuse_test.go:64`).
- iss-2611051719433203A sub-agent's shell call can stall for hours while the agent still reads as running, with nothing that says so; on 5 November one build lane sat for over five hours and was noticed only by reading its worktree. The agents here are the host's, which abcd does not see, so no drain lane can take this and it needs a person's reading of where the watch belongs.
- iss-2611051719447823A first signal during the login check of `abcd drain --drive` still starts the proof's launch: the signal marks a soft stop, and nothing reads it between the check and the launch. The drive is not on the default branch yet, so this record carries no location.
- iss-2611051720178630`abcd reserve --admit` can say a pull request stays withdrawn when inspect had just found it armed, if the re-read fails between two reads in one act.
- iss-2611051720198342A delta past a git output cap is refused when the delta review is recorded, without saying that it needs a full pair, so a retry can never succeed.
- iss-2611051727550516Test reuse has no test for a stage that loses the check directory's lock on retake after passing the race gate (`internal/testreuse/run.go`), so that path can change unwatched.
- iss-2611051821551531A drive's lane parks at its pull request where facilitator.mode is auto: the merge gate arms only a head a review receipt names, and only the land verb records one, so an unattended drive pushes every lane and leaves it open, holding its reservation until the reservation cap stops the run.
- iss-2611052230553388The warning for an agent session running without the wall is one line on stderr, which nothing keeps: in an unattended run the agent sees it and a person sees it only if the agent passes it on, so a person returning has no way to learn it fired.
- iss-2611052230565049A terminal drive given an end date with `--until` renews what it holds through every wait, so a subscription limit lasting days keeps its issue reserved for the whole wait with nothing happening on it, and refuses any peer's work whose paths overlap. With no end date the same wait is bounded at eight hours, after which the run ends and lets the lane go.
- iss-2611052230577572abcd drain's --max help says the default is all, but a terminal drive's cap is eight lanes, so a person reading only the help for a long run would not raise it and the run would end after eight.
- iss-2611060603321598The ingest's bijection lets a changelog line cite only records in the cut, so a surface that ships under a still-planned intent has no line of its own. abcd drain --drive shipped in v0.16.2 with its intent planned, and could only be introduced inside the line of the --until issue.
- iss-2611060809000628.abcd/development/brief/02-constraints/04-naming.md:56-61 lists the surfaces exempt from the maritime convention and says they are registered there so the exemption is on the record. `agents` is not on the list and is named nowhere else in the chapter as a verb, though the binary registers `abcd agents` (.abcd/development/release/surface.json) and .abcd/development/brief/04-surfaces/41-agents.md describes it.
- iss-2611060809005398`.abcd/development/brief/02-constraints/04-naming.md:14`: The naming row's list of ahoy write paths omits the worktree and shared-folder sub-verbs that write. Three more ahoy sub-verbs write, by their own help sentences: `abcd ahoy worktree add` writes the worktree, its start record and its local tier; `abcd ahoy worktree prune` writes the notes archive and removes the worktree and its branch; `abcd ahoy shared-folder <folder>` writes the choice.
- iss-2611060809013416`04-surfaces/README.md:191` says every visible verb and sub-verb carries the one sentence, and line 214 says a test walks every visible command. `abcd help`, `abcd completion` and its shell sub-commands are visible, carry the framework's own text, and are exempted by name at `internal/surface/cli/sentences_test.go:84-90`. The section states no exemption, though line 265 does for the separate bare-render test.
- iss-2611060809025632The rules verb section at .abcd/development/brief/04-surfaces/README.md:284-310 lists the bare, `<DOMAIN>` and `--prompt` forms and the diagnostics. `abcd rules` also registers `--fill`, which sets the context bracket `--prompt` shows and is refused at exit 2 without `--prompt` or outside 0 to 100. No chapter under .abcd/development/brief names it; commands/ahoy.md:1745 and docs/reference/cli/commands.md do.
- iss-2611060809036916`.abcd/development/brief/04-surfaces/41-agents.md:60-61` says the status line's row and an unattended run's summary are "the spec's remaining steps", and the only spec the chapter names (line 4) is spc-2611041701500441, which is in `.abcd/development/specs/closed/`. Those steps moved to the open remainder spc-2611050023402644, which the chapter does not name.
- iss-2611060809045160`.abcd/development/brief/04-surfaces/01-ahoy.md:34` lists `abcd ahoy shared-folder` as shipped, and the chapter says nothing else about it beyond the generated appendix (:1587, :1671). What the verb is for, what it writes and what `--person` means are stated only in `commands/ahoy.md:1475` and in the verb's help; `.abcd/development/brief/04-surfaces/17-guard.md:207` and `.abcd/development/brief/04-surfaces/27-implement.md:697` mention the folder in passing.
- iss-2611060809053025`.abcd/development/brief/04-surfaces/01-ahoy.md:47`: The chapter says the slash command dispatches every ahoy sub-verb, and the command page gives no dispatch for worktree. commands/ahoy.md has an argument hint of install, uninstall, doctor, --dry-run, --remote, remote apply, --providers, connect and credential, and no worktree section (grep finds none), so `ahoy worktree` is not dispatched. commands/ahoy.md:1485-1487 says choosing a shared folder is the person's own act, which the guard refuses to an agent: the page hands over the line rather than dispatching it.
- iss-2611060809067992.abcd/development/brief/04-surfaces/01-ahoy.md:631 says its inventory of abcd's home folder and the one in 05-internals/03-configuration.md are one list. Neither names `agents/` (internal/core/runner/ledger.go:49), `profiles/` (internal/core/runner/profile.go:50), or `shared-folder.json`, `stop.json` and `stop-log.jsonl` (internal/core/runstop/runstop.go:44-54), all of which the binary keeps there. The missing `fill/` entry is held by iss-2611040554089130.
- iss-2611060809074048`04-surfaces/01-ahoy.md:1017` says the plugin page relays the README pair from the `readme` view the dry run carries, its `readme_tool` calls holding the questions. `abcd ahoy --dry-run` carries `readme` and no `readme_tool`; `abcd ahoy --json` carries `readme_tool` and `sessions_tool` (`internal/surface/cli/cli.go:4150-4160`), and `commands/ahoy.md:928-932` relays from that. Line 1439 lists the same JSON as the envelope plus vintage and staleness, naming neither field.
- iss-2611060809080524.abcd/development/brief/04-surfaces/01-ahoy.md:1473-1475 calls uninstall then install a tested round-trip invariant: zero actionable gaps, and state byte-identical to a fresh install save for the setup date. `TestUninstallInstallRoundTrip` (internal/core/ahoy/idempotency_test.go:179) checks only that the marker block is gone, `.abcd/config.json` survives and the re-install status is clean. It compares no bytes and asks for no gap count.
- iss-2611060809092034`04-surfaces/34-build.md:295` says the state is schema version 20, and line 383 says an earlier version is written back at version 20 by its next mutation. `internal/core/implement/loop/state.go:281` declares `SchemaVersion = 21`, and state.go:285 keeps 20 as read and never written. Version 21 added a round's `resolves_shown` and a landing's `gate_unread_since` (state.go:271-276), which no brief chapter names.
- iss-2611060809105666.abcd/development/brief/04-surfaces/34-build.md:533 says a route override is refused beside a release, a discard or a restart, which hand no role out. internal/surface/cli/build.go:1224-1232 refuses it only beside `--release` and `--discard`: a `--restart` takes the route and starts the restarted role on it at once. `abcd implement step --help` and the chapter's own later sentence on a restart with a route in force say the same.
- iss-2611060809106010`.abcd/development/brief/04-surfaces/34-build.md:594-597` says a runner that is absent, refuses, fails, runs past its time, answers unparsably or writes a receipt the verifier refuses records a fallback naming the route that runs the role and hands the host the await; line 532 likewise says the role falls back. The binary pauses the lane instead: `pauseAwait` in `internal/core/implement/loop/runner_pause.go:609` sets the fallback's route to `none`, the run record says the lane is paused rather than handed to the host, and `abcd implement step --help` agrees, as does the chapter's own line 552. Only a review route still falls back to the host (`internal/core/implement/loop/validate.go:1116`).
- iss-2611060809113118`04-surfaces/36-dashboard.md:3` calls the dashboard one of abcd's two network listeners, the other being the brief session relay, and `04-surfaces/37-session.md:14`, `06-delivery/02-verification-matrix.md:25` and `05-internals/03-configuration.md:1914` count the same two. Session set-up opens a third: `LoopbackListener` (`internal/surface/session/appsetup.go:90`, called at `internal/surface/cli/session.go:821`) listens on a loopback port for the forge's answer to the app manifest. The session chapter does not describe it, and the listener boundary test admits two packages rather than two listeners.
- iss-2611060809127037`.abcd/development/brief/04-surfaces/24-decide.md:97` says the plain render of an ADR mint names "the same four values" as the JSON form and the status. The JSON form quoted at lines 93-94 carries five values: `id`, `slug`, `title`, `date` and `path`. The plain render prints the id, title, date, record path and status, with no slug line of its own.
- iss-2611060809131583`.abcd/development/brief/04-surfaces/02-disembark.md:212-215` says an opt-in oracle adapter runs the lifeboat review when wired. No adapter can: the same chapter says at :313 that no lifeboat agent is sent to a provider, and `abcd disembark review` routed to a provider is refused at exit 2 (`internal/surface/cli/cli.go:1316`, `internal/surface/cli/dispatch.go:96`, `internal/surface/cli/dispatch.go:217`).
- iss-2611060809141088`04-surfaces/27-implement.md:63` says every sub-verb refuses outside a checkout or in a repository with no commit, with two exceptions, the load check and the report given a log file. `abcd implement stop` is a third: its `RunE` (`internal/surface/cli/implement_stop.go:198-213`) reads the caller, takes the stop home and sets or lifts the stop, and resolves no checkout.
- iss-2611060809158052`04-surfaces/05-intent.md:154` says the ten disciplines written since itd-190 carry `## The gate`, `## Fit` and `## Staging`. Nine do. `.abcd/development/intents/disciplines/itd-190-the-claim-recording-gradient-an-intent-s.md` has `## The rule`, `## The gate` and `## Staging` and no `## Fit`.
- iss-2611060809166862.abcd/development/brief/04-surfaces/05-intent.md:297-298 says every change appends a date, from-kind, to-kind and reason to `reclassification_history`, and line 89 gives the shape as `{ date, from, to, reason }`. `--reason` is required only with `--kind superseded` (internal/core/intent/reclassify.go:194-198), so `abcd intent reclassify <itd-N> --kind bundle-member --bundle <name>` exits 0 and writes an entry with no `reason` key.
- iss-2611060809172280`04-surfaces/38-land.md:352` lists the steps in the JSON as `origin` when it reports a stale default, `gate`, `announce`, `push` and `enqueue`, or `land` alone. `internal/core/landing/withdraw.go:237,272,276,292` adds a further step named `withdraw`, with status `left` or `done`. Lines 98-103 of the chapter describe the act but the list does not name its step.
- iss-2611060809182848The enqueue step at .abcd/development/brief/04-surfaces/38-land.md:106 says the pull request is armed where the merge gate allows it and names no other hold. internal/core/landing/stacked.go also defers the arming where a merge queue gates the default branch and the branch shares a commit not on it with another queued or armed pull request, and the step then stops naming it. `abcd land --help` documents this; the chapter does not.
- iss-2611060809191251.abcd/development/brief/04-surfaces/04-launch.md:413 says the gate suite does not carry a deeper opt-in secret scan. It does: gitleaks, opted into by `.abcd/config/gitleaks.json` and registered at cmd/abcd/main.go:24, joins the scan, and armed with no binary installed it is a hard fail, as lines 55-58 of the same chapter and 02-constraints/02-dependencies.md:61-68 say.
- iss-2611060809192132`.abcd/development/brief/04-surfaces/04-launch.md:48` says the gate's inputs are the ledger, the anchor tag and the version location, kind-independent, so the cut runs unchanged for every kind, and lines 25-30 name a release path for a repository that ships no plugin. The cut also needs `.abcd/development/release/surface.json` in the anchor tag and at HEAD (`internal/core/changelog/guard.go:103`, `:184`), equal to abcd's own compiled command tree plus the repository's manifests (`internal/surface/cli/surface.go:38`). Only `cmd/abcd-gen-surface` in abcd's own tree creates that file: `abcd ahoy install` does not lay it, and the cut only refreshes one already there (`refreshSurfaceSnapshot`, `internal/surface/cli/ship.go:187`), after the guard has passed. A repository declaring `binary`, with a tag and a shipped intent, is refused under `surface-guard` by `abcd launch --dry-run`, and the stale-snapshot remedy names `go generate ./internal/surface/cli`, a package that repository does not have.
- iss-2611060809203137`.abcd/development/brief/04-surfaces/04-launch.md:659` gives four routes out of the unfixed-findings refusal, 'in the order the refusal states them'. The refusal (`unfixedReason`, `internal/core/changelog/findings.go:538`) states three: fix and resolve, `abcd capture wontfix`, and the deferral pair. Re-grading the record is not in its text.
- iss-2611060809210526`.abcd/development/brief/04-surfaces/23-reading.md:282` says one refusal after the identity point is deliberately unrecorded, the prose citation. `refuseARerun`, called at `internal/core/reading/ingest.go:614` after the identity is proven, also refuses and writes no refusal record, because a run that already has an outcome must not have it overwritten.
- iss-2611060809220159`04-surfaces/09-reflect.md:67` says the seed lists the planned intents whose `target_release` names the release and which did not ship. `unshippedTargets` (`internal/core/reflect/seed.go:200`) also adds any still-planned intent named in a target-move note of the release's changelog section (`changelog.IsTargetMoveNote`), whatever its `target_release` says, and those intents enter the warning and the `unshipped_targets` refusal. The chapter does not name this second source, which is the answer the ruling on iss-2610262032250865 chose.
- iss-2611060809234702`.abcd/development/brief/04-surfaces/37-reserve.md:11-12` says a person sees reservations on the board (bare `abcd`) and on a record's page. The record's page holds. The bare view does not: `product` in `internal/core/board/board.go:271` reads only a row's title, lane and next-up mark, so it prints no reservation. The only rendering is `rowTag` (`internal/core/board/board.go:435`), reached through `statusRow` on the full board that `abcd --view facilitator` prints, and those rows are Now and Next intents, so a reservation on an issue appears on no board view.
- iss-2611060809247857`.abcd/development/brief/04-surfaces/37-reserve.md:81` says the holder-id mint judges each folder, so that abcd's home folder writable by another account refuses before anything is minted or pushed. For a folder this account owns, every command first takes the group and other bits off it (`narrowHome`, `internal/surface/cli/homestop.go:60`; `NarrowToOwner`, `internal/fsutil/home.go:837`), so `mintHolderID` (`internal/core/claim/holderid.go:408`) never sees it exposed and no refusal follows. The refusal is left only for a folder another account owns.
- iss-2611060809250949`04-surfaces/37-reserve.md:623-628` lists an `Abcd-Withdrawn` entry's state as one of eleven values. The closed vocabulary `WithdrawalStates` (`internal/core/claim/withdraw.go:105`) has a twelfth, `standing` (withdraw.go:101), for an arming by another account at a head the merge gate does not arm. Line 775 of the same chapter says that state is recorded.
- iss-2611060809264429The exit list at .abcd/development/brief/04-surfaces/37-reserve.md:961-964 gives exit 3 when another person's reservation is live or the same person's other copy holds it and no take-over was asked for. That holds for a reservation, not for `--release`: internal/core/claim/remote.go:682-690 refuses a release of another person's or another copy's reservation as `ErrRefused`, exit 2. A run from a sibling worktree of the holder gave exit 3 for `abcd reserve <id>` and exit 2 for `abcd reserve <id> --release`.
- iss-2611060809268698`.abcd/development/brief/04-surfaces/37-session.md:234` lists the exit codes of the session verbs as 0, 1 and 2. `abcd session start`, `abcd session blueprint` and `abcd session setup` also exit 130 when the live brief session question is stopped with Ctrl-C at a terminal (`internal/surface/cli/session.go:224`, `:485`, `:730`; `internal/surface/cli/setup_interview.go:489`). The ahoy and reflect chapters name this exit for their own questions.
- iss-2611060809277124`.abcd/development/brief/04-surfaces/22-site.md:160-161` counts the timeline among the pages every repository gets and the `pages` block switches off. No timeline page or route exists: `internal/core/site/explorer.go:533-536` renders it as a folded panel on the `/record/` dashboard, labelled 'Genealogy' (`site-src/ui.json:40`), and `pages.timeline` removes only that panel. The comment at `internal/core/site/timeline.go:3` still names `/record/timeline/`.
- iss-2611060809286890`.abcd/development/brief/04-surfaces/21-update.md:26`: The update chapter names the launch preview and the cut as the other commands reaching the release origin, and session set-up and install reach it too. Other verbs reach the release origin. `abcd session blueprint` and `abcd session setup` for the cloud fetch checksums.txt from the release page (internal/core/session/blueprint.go:82,495; internal/surface/cli/session.go:76 update.NewReleaseAssets(sessionReleaseOrigin); `session blueprint --help`: 'The checksum is read from the release page when the files are written (the one network read this verb makes'; `session setup --help`: 'for the cloud it reads the release's checksums'). `abcd ahoy install` downloads the release binary when abcd is not on PATH (internal/core/ahoy/abcd_download.go; internal/surface/cli/update.go:42 update.NewGitHubUpdater().FetchVerified).
- iss-2611060809294152.abcd/development/brief/05-internals/03-configuration.md:59 says twenty-two keys plus a `meta` block. Lines 8 and 236 of the same chapter say twenty-three, and the JSON sample at lines 94-198 holds twenty-three keys outside `meta`.
- iss-2611060809301279`.abcd/development/brief/05-internals/03-configuration.md:241` says this repository's config carries nine blocks and lists them. `.abcd/config.json` carries ten: also `status`. The following sentence names only `facilitator` and `release` as set by hand, while :90-92 of the same chapter says `status.scheduled_workflow` is hand-set too.
- iss-2611060809312249.abcd/development/brief/05-internals/03-configuration.md:1553 says SHELL's injected block costs about 2k tokens for the bundled registry. `*SHELL` through `abcd hook prompt-router --json` in a repository with no `.abcd/guard.json` injects 33,320 bytes, about 8,000 tokens at four bytes a token, in 63 rules. internal/core/guard/defaults/guard.json holds 60 entries; the other three rules name entries defined in code.
- iss-2611060809322689`.abcd/development/brief/05-internals/03-configuration.md:1587` says `GRILL` lands at about 1,100 tokens. On the built binary, `*GRILL` through `abcd hook prompt-router --json` injects 6,533 bytes of text, about 1,600 tokens at four bytes a token.
- iss-2611060809335201`.abcd/development/brief/05-internals/05-prompt-quality.md:81-82` says the layer-B harness lands with the first Pass-A agent's spec, the point at which a second agent exists to generalise the runner over. Eighteen prompts already ship under `agents/`, as the same section counts at lines 74-75, and no Pass-A agent has shipped (`.abcd/development/brief/05-internals/01-agents.md:76-88`), so the reason given for the timing no longer holds.
- iss-2611060809343029`.abcd/development/brief/05-internals/05-prompt-quality.md:101` says research files do not exist for any shipped agent. `.abcd/development/research/prompting/agents/intent-fidelity-reviewer.md` is research for the shipped intent auditor (`.abcd/development/research/prompting/agents/README.md:44`), and :151-155 of the same chapter says it is stranded under the old name, so that no shipped prompt has a research file it can find.
- iss-2611060809346884.abcd/development/brief/06-delivery/01-build-sequence.md:62 says six further forms of `ahoy` write: `uninstall`, `remote apply`, `connect`, `credential --home`, `worktree add` and `worktree prune`. `abcd ahoy shared-folder <folder>` is a seventh: it writes `shared-folder.json` in abcd's home folder (internal/core/runstop/runstop.go:344-360), and .abcd/development/brief/04-surfaces/01-ahoy.md:34 lists it as shipped.
- iss-2611060809354261`.abcd/development/brief/06-delivery/02-verification-matrix.md:26`: The verification matrix's ahoy idempotency row quotes wording and a visibility re-confirm the binary does not produce. The binary cannot print that wording: 'already up to date' occurs under internal/core/ahoy and internal/surface/cli only in a code comment (internal/core/ahoy/ahoy.go:282). The line is `abcd is already set up here; nothing changed.` (internal/core/ahoy/setup_report.go:32), and commands/ahoy.md says a fully set-up repository is reported in that one line with nothing written, so no visibility re-confirm appears.
- iss-2611060809360063`.abcd/development/brief/06-delivery/02-verification-matrix.md:29` says a missing opt-in scanner backend falls back to the native scan, never a hard failure on absence. A repository that armed `gitleaks` in `.abcd/config/gitleaks.json` and lacks the binary fails closed: `internal/adapter/gitleaks/gitleaks.go:19-25` returns `ErrConfiguredNotFound`, carried as a coverage gap on which a release refuses (`internal/core/launch/dryrun.go:321`), and only a write path proceeds on the native scanner and names the gap. `.abcd/development/brief/04-surfaces/01-ahoy.md:980` already calls `gitleaks` required where the repository armed it.
- iss-2611060809373895`.abcd/development/brief/06-delivery/02-verification-matrix.md:63`: The verification matrix says a capture reports its severity, and it does not. Severity is not reported. Text output is 'captured iss-… (open) — <path>'. A `--severity major --json` run returned id, slug, path, status, uncommitted, no_location, match and ledger, with no severity field.
- iss-2611060809386735`06-delivery/02-verification-matrix.md:64` says `abcd capture resolve` moves the issue with its resolution and timestamp populated, and line 65 says the same of `abcd capture wontfix` with its reason. Neither writes a time. A resolved record carries `resolution:` and `impact:`, a declined one `wontfix_reason:`, and the only time in either is the id's own mint stamp; `internal/core/capture/workflow.go` reads no clock in the transition.
- iss-2611060809397681The capture wontfix row at .abcd/development/brief/06-delivery/02-verification-matrix.md:65 says `abcd capture wontfix` moves the issue with the reason and timestamp populated. The moved record carries `wontfix_reason` and a Grounds section and no date or time field, and neither internal/core/capture nor internal/core/issueschema defines one for a wontfix.
- iss-2611060809405161`.abcd/development/brief/04-surfaces/README.md:301` documents `abcd rules --prompt`, in the only brief section the verb has, and does not name `--fill <percent-used>`, which sets the context bracket that form shows. `abcd rules --help` registers the flag, and `docs/reference/cli/commands.md:5645` is its only documented home.
- iss-2611060809419595`.abcd/development/brief/05-internals/03-configuration.md:150` says the `force_refresh_every_n` counter only re-injects always-relevant domains. At the backstop `Inject` clears the whole ledger and the recalled ledger, so every domain the prompt matches comes back, and `RuleSet.Match` (`internal/core/rules/rules.go:648`) injects nothing the prompt does not name or hit, so a domain that never recall-matches is not injected at all. The comments at `internal/core/rules/inject.go:56`, `internal/core/rules/inject.go:147` and `internal/core/rules/inject.go:455` carry the same wording.
- iss-2611060809422351`.abcd/development/brief/05-internals/03-configuration.md:1629`: The prompt router's documented `--json` envelope and stderr contract omit fields and a line the binary emits. The envelope also carries fill, bracket and system_message (internal/surface/cli/cli.go:1737-1752; run output included "fill":{"source":"unknown",...} and "bracket":"unknown"), none in the table. recalled also holds page keys (run: "page:fact_eng_repo-page.md"). stderr also carries a once-a-session line when the fill is unknown (run: 'abcd rules: how full this session is, is unknown ...').
- iss-2611060809424276`05-internals/03-configuration.md:1602` says the prompt hook's stdout is the domains block, a `## MEMORY` block of notes, then the status block and nothing else, zero bytes with nothing to show, and that the prompt owing the session its name is the one JSON exception. Three parts differ. The `## MEMORY` block also carries memory pages, as `abcd hook --help` says. A `## AWAY` block follows the status block while the away record holds (`internal/surface/cli/cli.go:2006`). And while that record holds, or once it lapsed with something unread, stdout is one JSON object with `systemMessage` on prompts that owe no name and match nothing (`internal/surface/cli/hook_away.go:177-203`). Line 1629 repeats the same contents for the envelope's `text`.
- iss-2611060809438042`.abcd/development/brief/05-internals/07-memory.md:193` says the hook queries the `index.md` of both memory scopes and that on a recall-keyword collision across scopes the narrower scope wins, repo overriding user. `index.md` is never read (`internal/core/memory/recallpages.go:27`, `:61`). A machine page is dropped only when a repo page has the identical filename (`pageItems`, `internal/core/recall/pages.go:22`), so a repo page and a machine page with different filenames and the same `recall:` word are both recalled for one prompt.
- iss-2611060809443412`.abcd/development/brief/05-internals/07-memory.md:185-189` gives three brackets. `internal/core/rules/brackets.go:79-85` has four: an unknown row applies when no source gives the fill and sends pages as one line each. MODERATE sends the top-ranked pages in full up to 8 KiB and the rest as one line each. DEPLETED's lines come from each page's own summary, not `index.md` (`internal/core/memory/recallpages.go:26-27`, `internal/core/recall/pages.go:2`), which also makes :193's query of `index.md` wrong. MODERATE and DEPLETED also shrink the rules to a heading and first rule, which the chapter never says.
- iss-2611060809453708`04-surfaces/11-history.md:250` says what the session-start hook prints on its output stream is one fixed sentence and a count. Stdout also carries the `## AWAY` block (`internal/surface/cli/cli.go:2166`), the inbox greeting (cli.go:2323), the update-news line, a second constant line when commit checks are off (cli.go:2381) and the checklist (`internal/surface/cli/hook_checklist.go:39-44`). `04-surfaces/29-report.md:109` and `04-surfaces/40-checklist.md:71-75` describe some of these, so the chapters disagree. The reason the sentence gives holds for each: none of them carries text from a tracked file.
- iss-2611060809467300The hook row at .abcd/development/brief/04-surfaces/README.md:280 cites 26-mode.md as the home of `stop` and `stop-failure`. That chapter names neither event, the stop check nor API errors. What `abcd hook stop --help` states (a turn's end blocked while work is owed and naming the next item, allowed only with a session cron firing in time, a last message ending on a question blocked once, the host's cap on consecutive continuations) is described nowhere in the brief; 02-constraints/03-invariants.md:165-177 covers only the check's forge read, and 01-ahoy.md:840 only how its shim resolves.
- iss-2611060809475573`.abcd/development/brief/04-surfaces/35-drain.md:654-655` says the cap is set when a drain begins and a different cap named while it runs is refused, and `.abcd/development/brief/04-surfaces/35-drain.md:943` repeats the refusal. That holds for the bare verb and for a drive over a drain that already has a cap. A drive over a live drain with no cap gives it one: `internal/surface/cli/drain_drive.go:327` refuses a differing `--max` only when the drain's cap is above zero, and `internal/surface/cli/drain_drive.go:391` calls `loop.CapDrainInProgress` (`internal/core/implement/loop/terminal.go:1855`), which stores the lanes already opened plus `--max`, or plus the default of eight. The help at `internal/surface/cli/drain.go:235-236` repeats the chapter's sentence.
- iss-2611060809486452`35-drain.md:942` lists the cap refusals and line 12 says the cap bounds the lanes a drain opens, but the chapter never says that `abcd drain --max 0` is accepted and opens every lane. The run prints `cap: none (--max not given: all)` although the flag was given, and writes `"max": 0`. The refusal of `--max -1` at `internal/core/implement/loop/drain.go:369` asks for a whole number of lanes, 1 or more, which excludes the 0 it accepts, and `abcd build next` refuses `--max 0` (`internal/surface/cli/build.go:430`).
- iss-2611060809492476`.abcd/development/brief/04-surfaces/35-drain.md:759-760` says a route of the judge to opencode is skipped with a diagnostic and the judge stays on the host, with no exception for the drive, and `commands/drain.md:384-385` says the same. Under `--drive` that route refuses the start: `drivePreconditions` returns the refusal at `internal/surface/cli/drain_drive.go:246-247`, and `abcd drain --help` lists it. The skip holds for the bare verb only.
- iss-2611060809502312The drive section of `35-drain.md` (lines 193-340) states the walls, a credential variable and a start from an agent's session as refusals, and its appendix leaves exit codes to the prose. It never states the default cap of eight lanes (`driveDefaultCap`, against no cap on the bare verb); `--yes` and the refusal with no terminal to ask at; exit 3 for a second drive and for a drive stopped, stopped short or holding an issue back, exit 2 for a failed check, exit 130 for the second signal; the refusals for an agent runner not enabled or not admitted and for a role pinned to the host; or the `--until` forms (a date read as the end of that day, or an RFC 3339 instant) and the refusal of a time already past. `abcd drain --help` and `commands/drain.md` state each.
- iss-2611060809502482`.abcd/development/brief/04-surfaces/37-embargo.md:88-91` says the check refuses the store's location on this machine, and `abcd embargo check --help` and `commands/embargo.md:144` say the same. `buildDenySet` returns at `internal/core/embargo/check.go:735` when nothing is under embargo, before it adds the store's path, so a text naming the path passes while the stores hold no unpublished advisory.
- iss-2611060809519550`37-embargo.md:17` says the section below lists the acts the command page hands the person. The section at lines 132-134 omits one that `commands/embargo.md:309` lists: putting back any record details they redacted to land a fix, once the advisory is published. Restoring each record into the public ledger, which the section does name, is a separate item on the page.
- iss-2611060809529676`.abcd/development/brief/04-surfaces/03-embark.md:213-214` says embark carries the pass-B exemption through as the first line of both reports. The first line of the `embark probe` report is its heading, `embark probe: <name> (lifeboat verified)` (`internal/core/lifeboat/embark_render.go:25`), and the exemption follows it. Only `embark from` opens with the exemption.
- iss-2611060809535371`03-embark.md:141` says verification refuses a symlink or an oversize file anywhere inside the lifeboat. The size cap applies only to files the manifest hashes (`internal/core/lifeboat/embark.go:218`): an 18 MiB `review/big.bin` in the excluded layer passes `abcd embark probe` with exit 0, while a symlink there and an oversize hashed file are refused. The comment at `internal/core/lifeboat/embark.go:184` carries the same wording.
- iss-2611060809546274The packing-history example at `03-embark.md:329` shows `"dest": "../abcd-lifeboat"`. Packing with a relative destination records the resolved absolute path, so the example shows a value the field does not hold.
- iss-2611060809557633`.abcd/development/brief/04-surfaces/03-embark.md:135-136` says embark writes the record families plus the marker block. An embark that writes an issue also leaves `.abcd/work/issues/.iss-alloc.lock` in the target, from the ledger lock taken at `internal/core/lifeboat/embark.go:157`. `.abcd/development/brief/04-surfaces/03-embark.md:121` names the lock but not the file, and in a fresh target the file shows as untracked, so a plain `git add` of the result commits it.
- iss-2611060809563011`03-embark.md:165` gives the marker block's outcomes by `docs.target` and does not list an unreadable `.abcd/config.json`, which skips the block with the note `could not be read, so abcd's block was not planted; fix that file and run embark again` (`markerSkipUnreadable`, `internal/core/lifeboat/embark.go:578`). The chapter also does not say this differs from an unknown value, which reads as no choice and goes to `AGENTS.md`.
- iss-2611060809571307`.abcd/development/brief/04-surfaces/03-embark.md:74-76` describes the scores as handed back in a file, read as a regular file and never through a link. `--scores -` also reads standard input, capped at the same bound (`internal/surface/cli/embark_lessons.go:147-148`). The flag's help says so; the chapter and `commands/embark.md` do not.
- iss-2611060809582940Beyond `iss-2610230851446558`, which records the blocking exit while the old `.abcd` folder stands: `17-guard.md:455`, with lines 54-58 and 75-77, gives the hook's exits as 0 and 1, and line 456 speaks of the binary's three statuses without defining the third on the hook. `abcd guard hook` itself exits 2 here (`internal/surface/cli/homestop.go`), and only the rename command passes (`admitsRename`). With the plugin binary also absent, `hooks/pre-tool-use.sh` exits 2 even for the rename, so the rename that clears the stop has to be run outside the agent.
- iss-2611060809597822`.abcd/development/brief/04-surfaces/17-guard.md:459-460` says the shim's `UNGUARDED` warning names shell commands or questions through the host's question tool. `hooks/pre-tool-use.sh:4` has a third wording for the host's file-writing tools, `file writes through the host's own tools run UNGUARDED`.
- iss-2611060810004413`17-guard.md:483` says a file those tools write is judged only by where it lands in a shared main checkout, and anywhere else is written unchecked. `abcd guard hook` also denies a Write to a stop file or the shared-folder setting wherever it lands (`Write into the stop`, `internal/surface/cli/hook_occupancy.go:178`), and with `ABCD_STAGE_WRITES` set it denies a Write outside the stage and a Write to `Makefile` (`internal/surface/cli/hook_occupancy.go:156`).
- iss-2611060810012471`17-guard.md:1038` lists a pid list a kill reads through a variable or a file, or from a `ps | grep` chain, as unseen. `iss-2611040555239973` and `iss-2611040555220611` record the forms that block as `kill-by-search`. They do not record what stays true: `kill $(cat pidfile)` and a bare `kill $p` still allow, so removing the clause outright would leave the chapter implying those are seen. `p=$(ps aux | grep foo); kill $p` also blocks.
- iss-2611060810014724`17-guard.md:335` says a question without abcd's chip, while the mode names somebody, is held to the field limits and marked open. The header rule always refuses it: any header outside the chip grammar is a refusing finding (`internal/core/question/check.go:190`), so `""`, `Q1`, `Pick` and `Pick me` were all denied and no marker was written. Lines 302-305 of the same chapter already describe this refusal.
- iss-2611060810026397`.abcd/development/brief/04-surfaces/17-guard.md:1044`: The chapter lists same-line carried values as unseen and calls the matter an open ruling, but they block and the ruling is made. All block when the value is assigned on the line (`X='rm -rf /'; eval "$X"`, `P=pkill; $P make`). The ruling is made: internal/core/guard/carried.go cites it, and iss-2609281134544802 is in .abcd/work/issues/resolved/.
- iss-2611060810039095`17-guard.md:765` says the delete entries only warn, and refuse in a repository. Outside any repository `git branch -D x` also blocks as `git-delete-unproven`, exit 1, with the reason `the directory the command runs in is not a git checkout abcd can read` (`internal/core/sweep/deleteproof.go:159`); `git worktree remove x` and `git push origin --delete x` do the same.
- iss-2611060810040824`.abcd/development/brief/04-surfaces/17-guard.md:593-757` describes one bare launch, in which writes outside the working tree are judged by the protected set alone (`.abcd/development/brief/04-surfaces/17-guard.md:668`), and `commands/guard.md:424` says the same. A drive's stage launches walled, with hooks on and no `--bare` (`internal/core/runner/claude.go:190`), and the approver takes `--stage-home`, `--protect` and `--declared` (`internal/surface/cli/guard_approve.go:167`), which bound its writes and refuse a further agent. On a stage the hook denies a call it cannot judge (`internal/surface/cli/hook_occupancy.go:109`), against the chapter's fail-open account at `.abcd/development/brief/04-surfaces/17-guard.md:455-459`. `.abcd/development/brief/04-surfaces/35-drain.md:288-316` describes these walls; the guard chapter has only the three flags in its appendix, with no pointer to them.
- iss-2611060810055166`.abcd/development/brief/04-surfaces/11-history.md:55-58` describes capture as idempotent on the content hash, session id and source labels together: identical content is a no-op and a different session writes a new record. Capture also supersedes (`resolveSupersession`, `internal/core/history/history.go:391`). A body that extends a stored record of the same session, agent and labels deletes that record and the result carries a `superseded` field, and a body that is a prefix of a stored one is a no-op despite its different hash. Neither the chapter nor `commands/history.md` says this, or that a capture can remove a stored record.
- iss-2611060810065301`11-history.md:186` says every history verb reaches the store through one resolve seam, which creates the store chain and moves a legacy corpus. `abcd history staged --all-repos` (`internal/surface/cli/history.go:215`) and `abcd history discard --pending` (`internal/surface/cli/history.go:526`) skip it: on fresh homes each left the home directory empty, while `abcd history list` created the chain.
- iss-2611060810072511`.abcd/development/brief/04-surfaces/11-history.md:208-210` says a pending transcript the session start cannot place stays pending and unredacted until a later start can place it or an operator discards it, and `.abcd/development/brief/04-surfaces/11-history.md:95` describes draining only as redacting and storing staged transcripts. `abcd history drain` also places pending transcripts first (`placePendingNotices`, `internal/surface/cli/history.go:392`), so one can be filed and stored with no session start. `commands/history.md:66` states this; the chapter does not.
- iss-2611060810088225`11-history.md:242` lists among the session-start notices one for a repo last set up under a different version. No such notice is in the session-start body of `internal/surface/cli/cli.go`, where `meta.setup_version` appears only in the comment at line 2352. The nearest behaviour is the constant after-update line (`internal/surface/cli/update_news.go:140`), printed only when something is pending. The list also omits notices that do exist: git giving no root commit, hooks git does not run, the harness settings notice and the unseen-update notice.
- iss-2611060810092646`.abcd/development/brief/04-surfaces/11-history.md:267-268` says the prompt-router entrypoint drains one entry and at most half a megabyte per prompt. `DrainBudget.exhausted` returns false when no entry has been attempted (`internal/core/history/staging.go:194`), so the first entry is redacted and stored whole at any size. The code comment gives the reason: otherwise a transcript over the bound would never leave the disk. The chapter states the bound with no such exception.
- iss-2611060810104650`11-history.md:290` says each staged transcript's sidecar holds its session and lineage, so nothing is ever encoded in the filename. Staged names encode the capture time and the key, `<timestamp>-<key>.raw` (`stagedFilename`, `internal/core/history/staging.go:290`), and `stagedLockKey` (`internal/core/history/staging.go:443`) derives the agent or session key from that name without reading the sidecar. Pending transcripts are named `<session-id>.raw` (`pendingPaths`, `internal/core/history/pending.go:107`).
- iss-2611060810115703`18-ideate.md:203`, with line 198, says a run with a second research store below the checkout root succeeds against the checkout's own store and names the stray one. That holds only with `--public`, and line 96 makes private the default. A run with no store flag from such a subdirectory writes the verdict to the private ideas store and nothing to the checkout's, yet its stderr still says `this verb addressed the checkout's research store` (`internal/surface/cli/ideate.go:146`), beside `stored: private` on stdout.
- iss-2611060810119096`.abcd/development/brief/04-surfaces/18-ideate.md:163-166` lists where an unresolved record id refuses the verdict: a claim or its primary source, a grill note, a kill attempt, a reviewer's label or sources, the ruling, a rejected alternative, an origin source or the reframing. A reviewer's `implies_building` entries are checked too (`citationPlaces`, `internal/core/ideate/record.go:1151`), and `commands/ideate.md` does not name them either. The field is meant to name gaps, so a composer reading the list would not expect the refusal.
- iss-2611060810127057`.abcd/development/brief/04-surfaces/19-identity.md:92-94` says comparison folds line wrapping, so a tagline wrapped across two lines is not drift. The comparison sees only what the locator captured, and the fallback locators for `README.md` and `AGENTS.md` (`internal/core/positioning/config.go:120` and `internal/core/positioning/config.go:143`) capture one line. A plain paragraph wrapped across two lines under the top heading is reported `drifted` in both files, showing only its first line, and `abcd identity render` proposes replacing that line with the whole tagline while keeping the second, which would duplicate its text. The claim holds only for the multi-line locators: a `<p>` strapline and the paragraph after the abcd marker block.
- iss-2611060810137326The v0.16.2 changelog's stop line gives bare `abcd implement resume` as the way to find a run id, while the changelog's line on the restart intent reads as if that verb had not shipped: its intent stays planned because the listing lacks part of its criterion, and `--run` goes unnamed.
- iss-2611060810148228`abcd agents` is new since v0.16.1 and read-only, with no line in the v0.16.2 changelog, because no record in the cut covers it.
- iss-2611060823132319A stop removed by an age cleaner on Linux reads as no stop, so new runs can open as well as a run it had not halted, and a halted run's refusal says the stop has lifted though no one lifted it. The v0.16.2 changelog names the run it had not halted and not the new runs.
- adr-1Three-layer mental model (brief / intent / spec)2026-05-04related adr-11 · related adr-2 · related adr-26 · related adr-2609212115255771 · related adr-35 · related adr-5 · related adr-9
- adr-2Three intent kinds (standalone / bundle-member / discipline)2026-05-07related adr-1 · related adr-11 · related adr-3 · related adr-51 · related itd-1 · related itd-34 · related itd-37 · related itd-5
- adr-3Directory location is the source of truth for lifecycle state2026-05-07related adr-2 · related adr-26 · related adr-30 · related adr-32 · related adr-34 · related adr-5 · related itd-34
- adr-5Brief is the current state; no version label, no archive directory2026-05-08related adr-1 · related adr-19 · related adr-2610290238168123 · related adr-3 · related adr-30 · related adr-32 · related adr-35 · related adr-40 · related adr-9
- adr-7`/abcd:intent grill` — One Sub-verb with Two Inseparable Phases2026-05-11related itd-27
- adr-9Phase as a product-reflection layer between brief and intent2026-05-16related adr-1 · related adr-10 · related adr-11 · related adr-2609212115255771 · related adr-2609292012006845 · related adr-33 · related adr-34 · related adr-40 · related adr-5 · superseded by adr-2609212115255771
- adr-10The phase negotiator — a Socratic agent that proposes phases and grounds every trade-off2026-05-16related adr-11 · related adr-9 · related itd-41
- adr-11One canonical word for a specced block of work — spec2026-05-18related adr-1 · related adr-10 · related adr-2 · related adr-26 · related adr-9 · related itd-43
- adr-12`.work/issues.md` stays the live operational ledger; the structured per-issue store is deferred until the native spec layer schedules the migration (historical)2026-06-06related adr-26 · related itd-4 · related itd-46 · superseded by adr-32
- adr-13Durable memory writes — single-writer, atomic-rename crash model2026-06-09related adr-25 · related itd-36
- adr-19The plugin version lives ONLY in the released artifact; the working tree stays unversioned, and the version location is chosen by a schema-validated decision, not hard-coded2026-07-01related adr-20 · related adr-2609231048308186 · related adr-28 · related adr-31 · related adr-37 · related adr-5 · related itd-2611011151475128 · related itd-67
- adr-20The two release manifests stay version-consistent by an anti-drift checker over a pinned path list; the source view stays unversioned; `--allow-dirty` must never bypass it2026-07-03related adr-19 · related adr-2609231048308186 · related adr-28 · related adr-31 · related adr-37 · related itd-69
- adr-21Rebuild abcd as a Go binary2026-07-06related adr-22 · related adr-23 · related adr-2611011813195749
- adr-22Bundled dependencies become pluggable adapters over a native default2026-07-06related adr-21 · related adr-23 · related adr-24 · related adr-25 · related adr-26 · related adr-2609090717039680 · related adr-2609091248201071 · related adr-2611011813195749 · related adr-27 · related adr-29 · related adr-38 · related itd-2609292108373494 · related itd-2609292109005937 · related itd-2609292109214516 · related itd-63 · supersedes itd-47 · supersedes adr-14 not in the tree · supersedes adr-15 not in the tree · supersedes adr-17 not in the tree
- adr-23A transport-agnostic Go core behind thin front doors2026-07-06related adr-21 · related adr-22 · related adr-25 · related adr-26 · related adr-38 · related adr-39
- adr-24the companion harness is a peer integrated via conventions and MCP, not a code dependency2026-07-06related adr-22 · related adr-26 · related adr-39
- adr-25The LLM is host-delegated by default; oracles are opt-in adapters2026-07-06related adr-13 · related adr-22 · related adr-23 · related adr-2609221009491186 · related adr-2609221017021499 · related adr-2609291342092738 · related adr-2609300107513982 · related adr-2610091150447054 · related adr-2610141646525117 · related adr-2610161733400551 · related adr-2610222222326104 · related adr-27 · related adr-35 · related adr-39 · related adr-40 · related adr-42 · related itd-17 · related itd-2609170822093401 · related itd-80 · related itd-82 · supersedes adr-8 not in the tree
- adr-26A native minimal spec layer with the companion harness `ccpm` as the primary deeper backend2026-07-06related adr-1 · related adr-11 · related adr-12 · related adr-22 · related adr-23 · related adr-24 · related adr-2609151513118583 · related adr-3 · related adr-32 · related itd-43 · related itd-57 · related itd-80 · supersedes itd-49
- adr-27The autonomous run is a pluggable seam, not a Ralph port2026-07-06related adr-22 · related adr-25 · related adr-2609291342092738 · related itd-51 · related itd-57 · related itd-58 · related itd-59 · related itd-80 · related itd-82 · supersedes adr-16 not in the tree
- adr-28One repository, a curated release artifact — no dev→public mirror2026-07-06related adr-19 · related adr-20 · related adr-2609231048308186 · related adr-31 · related adr-33 · related adr-35 · related adr-37 · related adr-47 · related itd-36 · related itd-65 · related itd-66 · related itd-67 · related itd-72 · supersedes adr-18 not in the tree
- adr-29A native local redacted transcript corpus2026-07-06related adr-22 · related adr-2609090636172016 · related adr-2609090717039680 · related adr-2609091248201071 · related adr-35 · related itd-2609090559376002 · related itd-2609091718566731 · related itd-2609091718595846 · related itd-59 · related itd-89 · superseded by adr-2609090717039680
- adr-30Design-record information architecture — flat artefact-type folders2026-07-06related adr-2609021016270132 · related adr-2609231028044006 · related adr-3 · related adr-32 · related adr-41 · related adr-47 · related adr-5 · related adr-51
- adr-31The release version is derived from the intents in it, never authored2026-07-07related adr-19 · related adr-20 · related adr-2609151513118583 · related adr-28 · related adr-33 · related adr-37 · related itd-73
- adr-32The issue ledger is working-tier data, not authored record2026-07-08related adr-26 · related adr-3 · related adr-30 · related adr-47 · related adr-5 · related itd-36 · related itd-4 · supersedes adr-12
- adr-33Launch phase ownership is tiered; the phase index is the sole ownership source2026-07-08related adr-28 · related adr-31 · related adr-34 · related adr-35 · related adr-9 · related itd-65 · related itd-66 · related itd-70 · related itd-72 · related itd-73
- adr-34Intent lifecycle and phase scheduling are orthogonal axes2026-07-08related adr-3 · related adr-33 · related adr-9 · related itd-43 · related itd-7
- adr-35The lifeboat is a coverage experiment — read-only, out-of-tree, and proven before it is packed (supersedes adr-4)2026-07-14related adr-1 · related adr-25 · related adr-2609091014087993 · related adr-2609091248200336 · related adr-28 · related adr-29 · related adr-33 · related adr-36 · related adr-5 · related itd-11 · related itd-2 · related itd-21 · related itd-88 · related itd-90 · supersedes adr-4 not in the tree
- adr-36Coverage blanks are a fillable lifecycle — authored is not extracted, and the interview is its own step2026-07-15related adr-35 · related adr-50 · related itd-86 · related itd-88 · related itd-90
- adr-37Releases are changelog-driven — rolling `[Unreleased]` is the release decision, and automation tags exactly that commit2026-07-17related adr-19 · related adr-20 · related adr-2610281718537125 · related adr-28 · related adr-31 · related adr-47 · related adr-48 · related adr-52 · related itd-73 · related itd-93 · supersedes itd-72
- adr-38Implicit checks are disk-only — the network answers only an explicit ask2026-08-15related adr-22 · related adr-23 · related adr-2609151706587280 · related adr-2610031352212697 · related adr-2610032150581128 · related adr-2610150729333337 · related adr-2610181003541997 · related adr-2610241022541063 · related adr-2610241057124151 · related adr-2610241101463288 · related adr-46 · related adr-48 · related adr-52 · related itd-105 · related itd-108 · related itd-111
- adr-39Host-tier policy — MCP floor, reference host, open-source default2026-08-16related adr-23 · related adr-24 · related adr-25 · related adr-2610120937435856 · related itd-2 · related itd-22
- adr-40Review, audit, lint, and gate are four buckets, separated by what each compares2026-08-16related adr-25 · related adr-2609231028044006 · related adr-5 · related adr-9 · related itd-109 · related itd-16 · related itd-2610090831227812 · related itd-48 · related itd-53 · related itd-83 · related itd-85 · related itd-94 · related itd-97 · related itd-99
- adr-41Documents and ledgers never leave the user tier; a public citation requires both gates2026-08-16related adr-2610141646523373 · related adr-2610141646525117 · related adr-2610142116480836 · related adr-2610300908239458 · related adr-30 · related adr-43 · related adr-50 · related itd-126 · related itd-127 · related itd-74 · related itd-76
- adr-42The guard's parse layer is a mistake filter, not a security boundary — matching is two-tier, and completeness is abandoned as a goal2026-08-18related adr-25 · related adr-2610091150447054 · related adr-2610161621415708 · related adr-2610240850193281 · related adr-2611011813190527 · related itd-103 · related itd-2610161621364075
- adr-43Contributions are inbound = outbound MIT, and the trust boundary is the organisation's role ladder2026-08-19related adr-2610281718537125 · related adr-41 · related adr-44 · related adr-53 · related itd-92
- adr-44abcd never mutates a remote uninvited, and identity derives from caller-local facts2026-08-19related adr-2610120558328615 · related adr-2610120937435856 · related adr-2610161940004937 · related adr-43 · related adr-45 · related itd-92
- adr-45Record ids are timestamp-numeric, capture-stable, and never allocated by looking at the maximum2026-08-20related adr-2609151138420062 · related adr-2609212115255771 · related adr-2610110925465593 · related adr-2610301638558260 · related adr-44 · related itd-114 · related itd-129
- adr-46Persisting the hook binary never weakens the verification posture — every promotion re-verifies, and SessionEnd performs no network work2026-08-21related adr-2609151706587280 · related adr-38 · related itd-105 · related itd-132 · superseded by adr-2609151706587280
- adr-47abcdev.app is rendered from this repository alone2026-08-22related adr-2609301720596683 · related adr-2610091010387033 · related adr-2610141949110653 · related adr-2610142147242544 · related adr-2610291037481588 · related adr-28 · related adr-30 · related adr-32 · related adr-37 · related adr-48 · related itd-135 · related itd-136 · related itd-137 · related itd-138 · related itd-139 · related itd-140 · related itd-2610091010348892 · related itd-2610142145236613
- adr-48The website deploys on release, not on merge2026-08-22related adr-2610091010387033 · related adr-2610142147242544 · related adr-37 · related adr-38 · related adr-47 · related itd-135 · related itd-136 · related itd-137 · related itd-138 · related itd-2610142145236613
- adr-49Terminal emission discipline — decoration only on interactive TTYs, machine streams undecorated, untrusted text always sanitised2026-08-22related itd-112 · related itd-2610030810350727 · related itd-2610030810370060 · related itd-2610031214560142 · related itd-2610031215002409
- adr-50Framing traces never enter the record, and automated reviewers never read them2026-08-22related adr-2609021016288378 · related adr-36 · related adr-41 · related adr-55 · related itd-142 · related itd-143
- adr-51An intent can declare its mechanism claim and its scope conditions2026-08-22related adr-2 · related adr-30 · related adr-55 · related itd-142
- adr-52The semantic gate sits on the wrong side of the tag2026-08-23related adr-2610281718537125 · related adr-37 · related adr-38
- adr-53Audience is expressed by placement, never by a prose register2026-08-28related adr-2610030814023326 · related adr-43 · related adr-54 · related itd-141 · related itd-2611011151475128
- adr-54Punctuation enforcement stays mechanical-only2026-08-28related adr-53 · supersedes itd-141
- adr-55The construal stands in the record; its history does not2026-08-28related adr-2609021016272867 · related adr-2609021016275803 · related adr-2609021016288378 · related adr-50 · related adr-51 · related adr-58 · related itd-142 · related itd-143 · related itd-86
- adr-2609151528057131abcd owns the product thinker's surface2026-08-29related adr-2609151528057260 · related itd-167
- adr-2609151528057260Three roles, who each artefact addresses, and when the loop stops2026-08-29related adr-2609151528057131 · related adr-2610150603484802
- adr-56An exclusion control asserts only what it can prove2026-08-30related adr-2609021016270132 · related adr-2609021016272867 · related adr-2609021016275803 · related adr-2609021016286571 · related adr-2609090717039680 · related adr-2609091248201071 · related adr-58 · related itd-183 · related itd-194 · related itd-2609151516525843
- adr-57Grounds accumulate as an append-only section, in one shared form2026-08-30related itd-179
- adr-58A reading is commissioned about something, so the invocation takes a scope2026-08-31related adr-2609021016272867 · related adr-2609021016286571 · related adr-55 · related adr-56 · related itd-183 · related itd-184 · related itd-199 · superseded by adr-2609021016286571
- adr-2609021016270132The principles family is a declared record store whose entries carry typed claims, and it is read cold by statement and never by citation2026-09-02related adr-30 · related adr-56 · related itd-177 · related itd-181 · related itd-2609020625405170
- adr-2609021016272867The comparative reading receives one widening run's candidates, a positional exception to the prior-run exhaust, with the run derived from the record and no operand added2026-09-02related adr-2609021016286571 · related adr-55 · related adr-56 · related adr-58 · related itd-183 · related itd-186 · related itd-199 · related itd-2609020625407419
- adr-2609021016275803No session holds both a reading and the ledger, and a per-run context stamp is how the record shows it2026-09-02related adr-55 · related adr-56 · related itd-183 · related itd-188 · related itd-2609020625402599
- adr-2609021016286571The invocation is a position and a target state, and the committed preset for the position supplies the rest2026-09-02related adr-2609021016272867 · related adr-56 · related adr-58 · related itd-183 · related itd-184 · related itd-199 · related itd-2609021003095168 · supersedes adr-58
- adr-2609021016288378A reframe occasioned by a reading is a committed pointer to an event whose content stays local, and the frame it fingerprints is the framing as it presently stands, which adr-55 enumerates as three committed surfaces2026-09-02related adr-50 · related adr-55 · related itd-143 · related itd-2609020625402518
- adr-2609090636172016Sub-agent transcript lineage is carried by explicit record fields, not a composite session id2026-09-09related adr-29 · related itd-2609090559376002
- adr-2609090717039680The transcript corpus is a sibling store that creates itself, and the per-repo location is an opt-in pull2026-09-09related adr-22 · related adr-2609091014087993 · related adr-2609091248200336 · related adr-2609091248201071 · related adr-29 · related adr-56 · superseded by adr-2609091248201071 · supersedes adr-29
- adr-2609091014087993A tool never creates directories in user-owned project space; agent and session scratch is machine-scoped2026-09-09related adr-2609090717039680 · related adr-2609091248200336 · related adr-35 · related itd-118 · related itd-2609091014076309 · superseded by adr-2609091248200336
- adr-2609091248200336A tool never creates directories in user-owned project space; the store's location binds now and its verbs bind when the store ships2026-09-09related adr-2609090717039680 · related adr-2609091014087993 · related adr-2609091248201071 · related adr-2610030720195401 · related adr-2610030814023326 · related adr-2610031352212697 · related adr-2610031751065746 · related adr-2610032150581128 · related adr-2610050711287503 · related adr-35 · related itd-118 · related itd-148 · related itd-2609091014076309 · related itd-2609091034175565 · related itd-2610161621364075 · superseded by adr-2610031751065746 · supersedes adr-2609091014087993
- adr-2609091248201071The transcript corpus is a sibling store that creates itself through the canonical directory primitive2026-09-09related adr-22 · related adr-2609090717039680 · related adr-2609091248200336 · related adr-2610031751066232 · related adr-29 · related adr-56 · related itd-2609091014076309 · superseded by adr-2610031751066232 · supersedes adr-2609090717039680
- adr-2609151138420062The decisions log is a folder of minted records, not one appended file2026-09-15related adr-45 · related itd-2609151138388536 · superseded by adr-2610110925465593
- adr-2609151513118583An intent owns one or more specs, and it ships when its last spec closes2026-09-15related adr-26 · related adr-31 · related itd-80
- adr-2609151706587280The cache reaches PATH only through a home-scoped attestation the environment cannot write2026-09-15related adr-2610241057124151 · related adr-38 · related adr-46 · related itd-105 · related itd-132 · supersedes adr-46
- adr-2609212115255771Phases and milestones are retired: sequencing is dependencies rendered as status, the checkpoint is the derived release2026-09-21related adr-1 · related adr-2609292012006845 · related adr-45 · related adr-9 · related itd-146 · related itd-24 · related itd-2609061543533170 · related itd-2609211913453478 · related itd-2609212103565953 · related itd-2609212103568351 · related itd-2609212103572513 · related itd-2609212113220149 · related itd-2609212130136102 · related itd-2609212130146198 · related itd-2609212137116617 · related itd-2609212137128014 · related itd-2609212137129937 · related itd-2609231013154443 · related itd-34 · related itd-78 · superseded by adr-2609292012006845 · supersedes adr-9
- adr-2609221009491186A provider adapter serves only the models it lists, under a vendor denylist no listing overrides; everything else runs on the host2026-09-22related adr-25 · related adr-2609221017021499 · related adr-2609300107513982 · related itd-2609081951381895 · related itd-2609170822093401 · related itd-2609201916056194 · related itd-2609221009495079 · related itd-2609221656361680 · related itd-2609221656373558 · related itd-2609301918174237 · related itd-6 · superseded by adr-2609300107513982
- adr-2609221017021499Every external credential abcd holds is named in configuration and kept in one store the person chose; never the harness, never the repository2026-09-22related adr-25 · related adr-2609221009491186 · related itd-2609061543533170 · related itd-2609081951381895 · related itd-2609221017023290 · related itd-63
- adr-2609231028044006Shape claims in the brief's surface chapters are derived, never hand-authored2026-09-23related adr-2610290238168123 · related adr-30 · related adr-40 · related itd-147 · superseded by adr-2610290238168123
- adr-2609231048308186The catalog pins the latest release's plugin archive2026-09-23related adr-19 · related adr-20 · related adr-28 · related itd-108 · related itd-67
- adr-2609291342092738A drain takes an issue alone only when its fields say it needs no decision2026-09-29related adr-25 · related adr-27 · related itd-2609201916151817 · related itd-82
- adr-2609292012006845Now, Next and Later list an intent in a lane under Now only; phases stay retired2026-09-29related adr-2609212115255771 · related adr-9 · related itd-2609211913453478 · related itd-2609212103565953 · related itd-2609212103568351 · related itd-2609212103572513 · supersedes adr-2609212115255771
- adr-2609292116133348A dependency bump inside the bound is re-authored as the owner and only pushed by an App2026-09-29related itd-2609221842494980 · related itd-2609301020001595
- adr-2609300107513982A provider adapter's allowlist alone decides which models it serves, and abcd bundles no vendor denylist2026-09-30related adr-25 · related adr-2609221009491186 · related itd-2609081951381895 · related itd-2609170822093401 · related itd-2609221009495079 · related itd-2609301918174237 · related itd-6 · supersedes adr-2609221009491186
- adr-2609300821558671A reading finding is matched against the record when it is stored, reversing itd-180's warm-work-only rule2026-09-30related itd-180 · related itd-2609212137116617 · related itd-2609291923559186
- adr-2609301720596683abcd adds a missing site label to an existing ui.json and never rewrites one2026-09-30related adr-47 · related itd-2609212103568351 · related itd-2609212103572513
- adr-2610030720195401abcd keeps its own folders out of desktop indexing only by changing those folders, never the computer's search settings2026-10-03related adr-2609091248200336 · related adr-2610031751065746 · related adr-2610031751066232 · related adr-2610050711287503 · related itd-2610030720038073
- adr-2610030814023326AGENTS.md is the one conventions file abcd writes; it never writes a host-specific copy2026-10-03related adr-2609091248200336 · related adr-53 · related itd-22 · related itd-2610030814013772 · related itd-3
- adr-2610031352212697Claims are branches on the shared remote; nothing kept on one computer is the register; claim text is data2026-10-03related adr-2609091248200336 · related adr-2610120937435856 · related adr-2610150729333337 · related adr-2610161940004937 · related adr-38 · related itd-2609091034175565 · related itd-2609150819440345 · related itd-2609151838312703 · related itd-2609221656373558 · related itd-2610031259176838
- adr-2610031751065746The worktree store lives under the renamed home, `~/.abcd.noindex/worktrees/<root-sha>/<name>/`, and the rest of its rule is unchanged2026-10-03related adr-2609091248200336 · related adr-2610030720195401 · related adr-2610031751066232 · related adr-2610120558328615 · related adr-2611011153058085 · related itd-2609091014076309 · related itd-2610030720038073 · related itd-2611011151475128 · supersedes adr-2609091248200336
- adr-2610031751066232The transcript store is spelled under the renamed home, `~/.abcd.noindex/transcripts/<root-sha>/`, and the rest of its decision is unchanged2026-10-03related adr-2609091248201071 · related adr-2610030720195401 · related adr-2610031751065746 · related itd-2610030720038073 · supersedes adr-2609091248201071
- adr-2610032150581128abcd is reachable on a network only through the dashboard, only while the person runs it, and only for people the person lets in2026-10-03related adr-2609091248200336 · related adr-2610091016270711 · related adr-2610161400542916 · related adr-38 · related itd-2610032150577708 · related itd-2610032150580455 · related itd-2610040740108331 · related itd-2610040740122709 · related itd-2610040740135705 · related itd-2610091016262335
- adr-2610050711287503abcd reaches the harness's user settings only for the status line, with consent2026-10-05related adr-2609091248200336 · related adr-2610030720195401 · related adr-2610241022330872 · related itd-200
- adr-2610091010387033abcdev.app may render public abcd-managed repositories other than abcd2026-10-09related adr-47 · related adr-48 · related itd-135 · related itd-2610052000411162 · related itd-2610091010348892
- adr-2610091016270711Who may change an abcd-managed project's design on abcdesign.app, and how a change lands2026-10-09related adr-2610032150581128 · related adr-2610141949110653 · related adr-2610142147242544 · related adr-2610161400542916 · related itd-2610040740122709 · related itd-2610040740135705 · related itd-2610052000411162 · related itd-2610091016262335
- adr-2610091150447054The guard reads a script the command names before it judges the command2026-10-09related adr-25 · related adr-2611011813190527 · related adr-42 · related itd-103
- adr-2610091918443997What may enter abcd's memory notes without the person's yes, and how a note reaches the record2026-10-09related adr-2610141646523373 · related adr-2610141646525117 · related itd-2610091918433290 · related itd-2610111655362931 · related itd-3 · related itd-39
- adr-2610110925465593Decisions are one flat file each and the single log is retired2026-10-11related adr-45 · related itd-2609151138388536 · supersedes adr-2609151138420062
- adr-2610120558328615A private advisory's record never enters the public ledger, its store is never committed, and nothing public carries an advisory id or hint2026-10-12related adr-2610031751065746 · related adr-44 · related itd-149 · related itd-2610112239022766
- adr-2610120937435856A cloud session's unchecked work goes only to a declared work-in-progress prefix that never reaches the default branch2026-10-12related adr-2610031352212697 · related adr-2611011231015519 · related adr-2611011327164895 · related adr-39 · related adr-44 · related itd-2609091034175565 · related itd-2610120738075547
- adr-2610140859394097abcd's home ignores itself once, and credentials never sit in a working tree2026-10-14related itd-2610140858048004
- adr-2610141646523373Ingested pages are private by default and reach the project only by a person's promotion2026-10-14related adr-2610091918443997 · related adr-2610141646525117 · related adr-2610142116480836 · related adr-41 · related itd-2610141646467500 · related itd-36
- adr-2610141646525117The librarian treats unknown rights as all rights reserved, files privately first, and admits only named ratings2026-10-14related adr-25 · related adr-2610091918443997 · related adr-2610141646523373 · related adr-2610142116480836 · related adr-2610300908239458 · related adr-41 · related itd-164 · related itd-2610141646126492 · related itd-2610141646452213 · related itd-2610141646456128 · related itd-2610142116477426
- adr-2610141949110653The brief session's browser editor ships as a vendored bundle the binary embeds2026-10-14related adr-2610091016270711 · related adr-2610161400542916 · related adr-47 · related itd-2610091016262335
- adr-2610142116480836Ideate verdicts are private or public by the person's choice, and an idea's source is named publicly only when it graduates2026-10-14related adr-2610141646523373 · related adr-2610141646525117 · related adr-2610300908239458 · related adr-41 · related itd-2610141646452213 · related itd-2610141646454347 · related itd-2610141646456128 · superseded by adr-2610300908239458
- adr-2610142147242544abcd's record is built onto its own GitHub Pages, and abcdev.app becomes abcd's documentation site2026-10-14related adr-2610091016270711 · related adr-47 · related adr-48 · related itd-2610091010348892 · related itd-2610142145236613 · related itd-2611011151475128
- adr-2610150603484802A fresh install's facilitator is a person until the repository says auto2026-10-15related adr-2609151528057260 · related adr-2610240850193281 · related itd-2610150602547271 · related itd-97
- adr-2610150729333337A status branch moves without a preflight receipt2026-10-15related adr-2610031352212697 · related adr-38 · related itd-2609091034175565 · related itd-2609151838312703
- adr-2610161400542916The brief session page asks nobody for a relay address or a token, and a local session signs in by GitHub's device flow2026-10-16related adr-2610032150581128 · related adr-2610091016270711 · related adr-2610141949110653 · related itd-2610091016262335
- adr-2610161621415708Unattended runs abcd launches execute inside an OS sandbox2026-10-16related adr-2611011813190527 · related adr-42 · related itd-2610161621364075
- adr-2610161733400551A reviewer or judge in a model-matrix run is told nothing about which model wrote the copy it judges2026-10-16related adr-25 · related itd-2610161733316518
- adr-2610161940004937Spent reservation branches are deleted only by one GitHub App the ruleset names2026-10-16related adr-2610031352212697 · related adr-44 · related itd-118 · related itd-2609091034175565
- adr-2610181003541997The away mode's stop check reads the forge once, as its documented meaning2026-10-18related adr-2611050740453233 · related adr-38 · related itd-2610180912189125
- adr-2610222026262980Coordination between headless agents is bounded by deadlines, fenced by the claim's tip, version-checked, and done under each session's own credential2026-10-22related adr-2610222026265719 · related itd-2609091034175565 · related itd-2609151838312703 · related itd-2610170634394993
- adr-2610222026265719A session's checklist names a credential by its kind, scope and expiry, never its value or anything that retrieves it2026-10-22related adr-2610222026262980 · related itd-2610170634394993 · related itd-2610170638184486 · related itd-2610180912189125
- adr-2610222222326104abcd drives agents with no host session only on the person's own invocation, on the person's own account behind a wall, and hands back what it cannot finish2026-10-22related adr-25 · related adr-2610310235000654 · related adr-2611011231015519 · related itd-2609201916056194 · related itd-2609201916151817 · related itd-2610161016401115 · related itd-2610222215485265
- adr-2610240850193281A human-set autonomy grant permits, separately from the agent-written waiting-on badge2026-10-24related adr-2610150603484802 · related adr-2611011327164895 · related adr-2611050740453233 · related adr-42 · related itd-2610150602547271 · related itd-2610161621364075 · related itd-2610170638184486 · related itd-2610180912189125 · related itd-2610240850336695 · related itd-2610241015120503 · related itd-97
- adr-2610241022330872Setup edits the shell settings to put abcd's folder on the PATH, on a yes2026-10-24related adr-2610050711287503 · related itd-2610240823055889 · related itd-2610240919030303
- adr-2610241022541063Each person's commit identity lives on their own machine, not in the repository2026-10-24related adr-38 · related itd-131 · related itd-178 · related itd-2610240918547728
- adr-2610241057124151abcd installs the tools it needs from downloads pinned in its own release2026-10-24related adr-2609151706587280 · related adr-2611011813195749 · related adr-38 · related itd-2610240918594138
- adr-2610241101463288Setup asks short questions and lists its defaults on one plan2026-10-24related adr-38 · related itd-2610240823055889
- adr-2610281718537125A release publishes with no approval step2026-10-28related adr-37 · related adr-43 · related adr-52
- adr-2610290238168123The brief states the design and why; each command's page states what abcd does, once, and is the copy checked against the code2026-10-29related adr-2609231028044006 · related adr-5 · related itd-147 · related itd-2610290239150589 · related itd-60 · supersedes adr-2609231028044006
- adr-2610291037481588The contributors page counts people and names none2026-10-29related adr-47 · related itd-136
- adr-2610300908239458Ideate verdicts are private unless the person says public2026-10-30related adr-2610141646525117 · related adr-2610142116480836 · related adr-41 · related itd-2610141646452213 · related itd-2610141646454347 · related itd-2610141646456128 · supersedes adr-2610142116480836
- adr-2610301638558260A published refusal code is never renamed or reused2026-10-30related adr-45 · related itd-2610301346085246 · related itd-2610301428378830
- adr-2610310235000654An unattended plan stands in for the sign-off only on a recorded, reviewed, unchanged draft2026-10-31related adr-2610222222326104 · related itd-2609201916151817
- adr-2611011153058085A re-render never discards hand-written text unasked2026-11-01related adr-2610031751065746 · related itd-102 · related itd-2610031348087517 · related itd-2611011151475128 · related itd-2611011151512956 · related itd-2611011239589823
- adr-2611011231015519The launches abcd makes spend a person's money only within the budget they set, past it only through named residuals2026-11-01related adr-2610120937435856 · related adr-2610222222326104 · related itd-2610161733316518 · related itd-2611011230226453
- adr-2611011327164895A self-attested result is labelled as such, and only the person switches it on, by an act abcd's own verbs refuse to its agents2026-11-01related adr-2610120937435856 · related adr-2610240850193281 · related itd-2610261025516272 · related itd-2611011325428560
- adr-2611011332427073abcd resolves every layered setting by one precedence rule2026-11-01related itd-2611011333366788
- adr-2611011813190527A repository declares a sequence's shape but never a widening flag2026-11-01related adr-2610091150447054 · related adr-2610161621415708 · related adr-42 · related itd-2611011813162141
- adr-2611011813195749abcd never runs a foreign executable under its own name, and no code that writes records is loaded at run time2026-11-01related adr-21 · related adr-22 · related adr-2610241057124151 · related itd-113 · related itd-62
- adr-2611050740453233A stop is recorded state a person sets, and one shared folder is the exception to the owner-only store2026-11-05related adr-2610181003541997 · related adr-2610240850193281 · related itd-2611041549461012 · related itd-2611041549471712