Rank 3 on the docket. RuntimeConfig carries 32 boolean fields and nothing in
the repository stated that set, distinguished a capability flag from a posture
flag from a deployment knob, or recorded what evidence would flip any of them.
Two independent counts of the same set differed by eleven — the assessment said
"seventeen capability flags," N-7 measured 28 default-off plus 4 default-on —
and neither was wrong about what it looked at. They counted different things
because nothing declared what the set was.
R-3 (ruled A — incomplete flag set). accrue_realized_knowledge joins
CONTINUOUS_LIFE_CONFIG_FLAGS. Step D consolidates the realized facts Step B
writes, and the daemon forced the consumer without the producer: a continuous
life consolidating an empty set, which the mastery framework calls "garbage at
high speed." It shipped that way for six weeks.
The decisive evidence was in the code, not the documents. BOTH flags' comment
blocks in core/config.py already described the corrected profile —
accrue_realized_knowledge says "the production L10 process enables it alongside
persist_session_state", consolidate_determinations says "...alongside
accrue_realized_knowledge + persist_session_state". Three records (two
docstrings and the 07-25 verification doc) agreed with each other and disagreed
with four lines of code. Dormancy was a coherent ruling and would have cost
correcting three records that were RIGHT about the design; incompleteness cost
one line.
So the planned "N-6 docstring correction" deliverable DISSOLVED rather than
shipping: adding the flag made both docstrings true. Recorded explicitly,
because a PR that quietly ships less than it promised is the same divergence
class this arc exists to close.
R-4 (ruled A) — docs/specs/flag_register.md. All 32 booleans with class,
governing ADR or an honest "none", recorded rationale, and what evidence would
flip it. The classification is the load-bearing half and is stated as a
taxonomy rather than a label:
CAPABILITY — what CORE can do; engineering may flip it on named evidence
POSTURE — what CORE serves or refuses AS TRUE; the wrong=0 boundary,
ruling-only
DEPLOYMENT — cost, lifecycle, process shape; per-deployment
estimation_enabled and composed_surface are both "= False" and are not the same
kind of thing. Nothing said so before.
Profiles are declared as the UNIT of decision (R-4's mechanism): one-shot/eval
and continuous-life. The absence of a SERVING profile is stated deliberately —
the four POSTURE serving flags each ride their own license, and grouping them
before the ledger is sealed would license by association, the outcome R-8
exists to prevent.
tests/test_flag_register.py, on the gate. BIDIRECTIONAL, because either
direction alone would have passed through both failures it exists to prevent:
a flag added to config.py and not registered fails; a register row outliving
its flag fails. The counts the register's prose states (32 / 4 ON) are pinned,
since a stale count is how this register came to be needed. Four sabotages
observed red — new unregistered flag, deleted row, orphaned row, and a flag
silently flipped ON, the last caught by two independent pins.
THREE FINDINGS THE ITEM DID NOT ANTICIPATE, all from measuring rather than
reading.
1. Accumulated permissiveness, not just hesitancy. Of the four default-ON
flags, ONE has a governing ADR (deduction_serving_enabled / ADR-0256) and
TWO have no recorded reason of any kind — allow_cross_language_recall and
use_salience carry no comment block, no ADR, no criterion. In an
architecture built on earned licenses, two permanently-on capability flags
with no recorded decision is G-8's question inverted. Registered and
deliberately NOT fixed: writing a rationale after the fact would invent a
decision nobody made, which is worse than recording the absence.
2. A hollow gate inside the governance pin itself.
test_default_on_flag_is_not_governed_by_a_proposed_adr is parameterized over
(default-ON flag x cited ADR), so the three uncited ON flags contribute ZERO
cases — it covered exactly one flag. Its non-vacuity guard asserted only
that SOME flag cites an ADR, which default-off flags satisfy in abundance.
One reformatted comment away from zero coverage with everything green: the
failure state indistinguishable from the success state, inside the module
written to prevent exactly that. Guard tightened to require a non-empty
parametrization, and observed red by stripping ADR-0256's citation.
3. The daemon's own tests ran on no gate. R-3 changes what the always-on
process does every beat, and tests/test_l10_always_on_daemon.py was in no
curated suite — so this behaviour change would have shipped guarded solely
by tests no gate invokes, which is the hollow-gate pattern landing on the
exact file covering the change. Promoted to smoke WITH the change it guards.
Measured +9.4s, +4.3% of smoke — paid deliberately, not estimated. Removed
from full_only_baseline.txt in the same edit (both-directions ratchet; the
baseline shrank 747 -> 746).
Red before green throughout: the assertion cfg.accrue_realized_knowledge is
True was added to the daemon test and OBSERVED FAILING before the flag existed.
H-8(c) closed by AMENDING the correction note rather than deleting it, and the
amendment is the more useful artifact. PR-1's note said the 07-25 document's
claim was false; R-3 then made that claim TRUE, so the correction note itself
went stale — in the direction nobody guards, a correction made wrong by its own
subject being fixed. Both notes now carry the commit window they apply to. A
dated correction survives its subject changing; an undated "this is false" does
not.
Also delivered, from the 2026-07-28 external-assessment triage: §5, the
declared-table index. Eight single-source-of-truth tables and the pin that makes
each true. A reader's aid, explicitly NOT a central contracts.toml — that would
add a fifth copy needing agreement with four generators and put four different
authorities in one merge surface.
Handed forward to PR-11: the 5000-beat soak recorded in
evals/l10_always_on/contract.md (2026-07-19) predates this change and therefore
describes a configuration that NO LONGER SHIPS. PR-11's re-run is the first soak
of the corrected profile, and Step B feeding Step D is exactly what a long
horizon stresses.
Closes G-6, G-8, H-6, H-8(c), H-8(d) — and H-8 in full. Wave 4's F-6 half-gate
is lifted; the Track C half is untouched.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wcw2pnMBwyvmNyQg4uPEt4
42 KiB
The Hindrance Audit
Assessor: Fable 5 (Phase 4) · Verified at: 8927c563 (2026-07-27)
Discipline: A hindrance is something present that works against the goal — a wrong solution for its underlying problem, a responsibility lodged in the wrong owner, a trade-off tuned instead of dissolved, or a record that misleads the next reasoner. Every entry carries evidence, a fitness verdict from the schema vocabulary, a proposed better home, and its deciding authority. Per standing rule: settled rulings are constraints — an entry may flag a ratified decision only on evidence, only for ruling, never as a unilateral recommendation to reverse. This audit decides nothing.
Ranked by leverage (cognitive/structural load removed ÷ effort), per the AGENTS.md protocol — not by ease.
Amended: 2026-07-27 at ed06dd64 (Opus 5, Phase 6) · re-verified 2026-07-28 at 797ebad5 (H-12's ten-file delta re-measured and unchanged; H-8d's wording corrected on re-verification — see the entry). H-12 added (the two smoke gates have diverged). H-8 gains a fourth instance, located inside the source rather than the documents. H-1 gains a note: its exposure is already pinned. Derivations in 50-execution-plan.md §0.
Amended again: 2026-07-28 at 8f0ccfe3 (Fable 5, external-assessment triage). Two external first-principles assessments were verified against code line-by-line; two of their observations survived and are entered as H-13 and H-14, H-8 gains a fifth instance (e), and six of their proposals were examined and cleared (see the closing section). Every rejected proposal failed on evidence one file-read away from its claims — the third recurrence of the N-1 scan-artifact class.
H-1 · License evidence counted on an independence assumption replay violates
Verdict: wrong-solution (the counting basis, not the gating) · Layers: M5
Evidence: Wilson lower-bound licensing (θ_SERVE=0.99, ADR-0175 lineage) assumes independent trials; a replay of the same sealed case is one trial observed again, not a new one. Measured consequence recorded in the prior arc: 21 of 25 ratified bands fall short of their floor when replays are deduplicated.
Why it hinders: the entire earned-license architecture — CORE's mechanism for deserving to serve — rests on the evidence count. An overstated count grants licenses the evidence doesn't support, which is precisely the failure the mechanism exists to prevent. The gate is right; the arithmetic feeding it is not.
Better home: distinct-evidence counting at the seal boundary (count distinct cases; a replay refreshes, never increments), declared in the ledger schema the way ADR-0263 Rule 5 declares absence policy — in the table, not the call site.
Note (Phase 6): the exposure is already pinned in-repo. tests/test_volume_honesty.py (ADR-0264 R9, in the local smoke gate) pins "21 of 25 bands do not clear θ_SERVE on distinct evidence" in both directions, measured 2026-07-25 at 6ada6f7a with every band at 720 committed decisions, and its own comment calls the inventory "an EXPOSURE INVENTORY, not an approved baseline." The audit source is docs/research/distinct-evidence-audit-2026-07-25.md. The open work is therefore applying the shortfall, not discovering it — and that pin moves in the same PR.
Authority: ADR amendment (0175/0263 lineage) + a re-count of the 25 bands, authorized by R-13. The re-count may demote licenses; that is the mechanism working.
H-2 · Decoration in the runtime constructor — objects built and never read
Verdict: decoration (fails the sabotage test) · Layers: M6/M3
Evidence: DriveGradientMap constructed at chat/runtime.py:716, read nowhere. InhibitionMask/InhibitionOperator exported by core/physics/__init__.py, constructed on no path. Deleting either changes no output.
Why it hinders: dead structure is not neutral — it is testimony. Both objects tell every reader that drive mapping and inhibition masking are live, and Phase 1 of this very assessment initially believed them. Decoration is how architecture lies without anyone lying.
Better home: deletion (mastery algorithm step 2: the best part is no part), with their intents preserved where they belong — drive in the CR-2 design (G-4), the mask's disposition in the CR-1 ADR (G-14). If a future mechanism needs them, re-adding a deleted class is cheap; un-believing a phantom is not.
Authority: mechanical PR + one line each in the CR-1/CR-2 decisions.
H-3 · The typed refusal is constructed, then discarded at the public boundary
Verdict: strained — truth built and unserved · Layers: M4
Evidence: InnerLoopExhaustion carries reason, region, and per-step rejected-attempt evidence; respond()/arespond() convert it to "" for the str contract, so a refusing turn serves the empty string with refusal_reason == "". The plumbing to materialise (CognitiveTurnResult.refusal_reason, compute_trace_hash fold) already landed; runtime_contracts.md names it a residual awaiting a future ADR.
Why it hinders: the honesty machinery is the product. A system whose refusals are richer than its answers, serving its refusals as nothing, undersells its own thesis on every hard turn.
Better home: materialise into ChatResponse.refusal_reason (and a minimal honest surface), per the contract's own anticipation.
Authority: small ADR — the chain already reserved the seam.
H-4 · Composer-arm precedence is ordered branches above a declarative resolver
Verdict: strained — a solved pattern not yet extended · Layers: M4
Evidence: core/cognition/surface_resolution.py (494 lines) resolves the pipeline seam by declared precedence, self-documenting, with an in-code falsifiable contract for its own regression. Upstream, the composer arms (deduction :1834, curriculum :1850, pack/narrative/example/relation :1871–:1936, determination, estimate, gate, hedge) remain ordered branches across chat/runtime.py, in a different package with a different owner — nothing structurally prevents arm N+1 from bypassing the resolver's disciplines.
Why it hinders: prospectively — each new serving capability adds an arm ahead of any declared order. With only deduction ON, the live complexity is modest; the time to dissolve the pattern is before the next three arms, not after.
Better home: extend the resolver's declared-precedence pattern upstream to arm selection — the Third Door here is half-built and proven to fit this codebase.
Authority: refactor ADR; low-risk while one arm is live.
H-5 · Underived constants at the semantic center of generation
Verdict: strained — Pillar I violation with an in-repo counterexample · Layers: M3/CR-1
Evidence: salience_top_k=16, inhibition_threshold=0.3 gate every token walk's candidate set; no recorded derivation exists for either. The contrast is instructive and in-repo: admissibility_margin δ=0.4 was derived from the minimum observed margin of a characterization corpus (0.456), declared falsifiable, and survived a 20-case stratified attempt — the standard exists two config lines away.
Why it hinders: "thresholds tuned for good-enough" at the exact point where the system decides what it may consider. Also the self-narrowing budget feedback (stream.py:637) — a real cognitive property nobody has named or justified.
Better home: the CR-1 ADR (G-14) with an empirical derivation in the δ=0.4 style.
Authority: ADR + a small characterization run.
H-6 · The half-forced flag pair gating the lived learning loop
Verdict: misplaced responsibility — a set decision made one flag at a time · Layers: M6/M5
Evidence: F-6 (05-phase3-findings.md): the daemon forces the consolidator, not the accruer; the loop's writer and its consumer are gated independently, and only the consumer is on.
Why it hinders: flags that must be coherent as a set are owned nowhere as a set. CONTINUOUS_LIFE_CONFIG_FLAGS is the right pattern (a named, documented flag profile) applied to the wrong subset.
Better home: the flag-default register (G-8) with named profiles (one-shot / eval / continuous-life), each profile ruled as a unit.
Authority: ruling on the accrual flag + the register PR.
RESOLVED 2026-07-28 (R-3 + R-4, PR-5) — relocated to its better home, exactly as specified. docs/specs/flag_register.md §4 declares profiles as the unit of decision: one-shot/eval (the RuntimeConfig() defaults — and the register states why that is a real reason rather than hesitancy: a fresh runtime per invocation must not pay for resume, accrual, or snapshotting it does not use) and continuous-life (CONTINUOUS_LIFE_CONFIG_FLAGS, now the coherent four rather than the incoherent three). The misplaced responsibility this entry named — "flags that must be coherent as a set are owned nowhere as a set" — is discharged by making the set the declared unit.
One profile is deliberately absent and the register says so: there is no serving profile. The four POSTURE serving flags are ruled individually because each rides its own license, and grouping them before the ledger is sealed would license by association — which is the outcome R-8 exists to prevent.
H-7 · The production ingest boundary lacks the trust contract its sibling has
Verdict: strained — the standard exists and stops one layer short · Layers: M2
Evidence: formation declares six boundaries — content-addressed in/out, no floats in hashed payloads, no pickle, an audit record per rejection. ingest/gate.py, facing untrusted user text in production, has the versor gate and the AGENTS.md trust-boundary defaults, but no comparable declared table.
Why it hinders: asymmetric rigor invites the assumption that the un-tabled boundary is the less important one; it is the opposite.
Better home: an M2 trust-boundary table in runtime_contracts.md, formation-style; hardening PRs only where the table exposes real deltas.
Authority: documentation first; evidence decides whether code follows.
Status (2026-07-28): CLOSED — table written, and the measurement reframes the entry. docs/specs/runtime_contracts.md §"M2 trust-boundary table" measures ingest/gate.py against all six of formation's declared boundaries at edf6c2a4. The result is not "five of six missing":
| Already met | no floats in hashed payloads (_stable_digest hashes strings only); no pickle anywhere under ingest/ |
| Category differences — closed, not owed | content-addressing, self-sealing, and the source allow-list all presuppose a persisted artifact with citations. Formation validates artifacts it will store; the gate transforms text it will not. Writing these as obligations would have manufactured three gaps and sent someone to close them |
| REAL DELTA (one) | no audit record per rejection. The gate refuses with typed exceptions and records nothing about what it refused |
The surviving delta is not a containment hole — refusal is fail-closed and nothing unvalidated crosses. It costs forensics, and it is the same failure class as H-11: a guard that works correctly and leaves no trace of having worked. It also has a downstream consumer worth naming — a widening program (G-3) must be able to ask "what shapes is the boundary refusing, and how often?", which today it cannot. Hardening is a separate PR per this entry's own authority.
H-8 · The record contradicts the code at three load-bearing points
Verdict: wrong-solution as record-keeping — divergence that reasoners inherit · Layers: governance
Evidence: (a) ADR-0146 rejects the daemon shape and places "cross-process file locking, daemon synchronization, and signal handling" out of scope; chat/always_on_daemon.py ships all three (fcntl.flock single-instance lock, SIGINT/SIGTERM, load-time identity guard) and is unowned. (b) ADR-0252's headline "34 organs" has no reproducible basis (18 resolve_promotable_* entry organs at the ratification commit and at ed06dd64; ~32 modules). (c) architecture-assessment-verification-2026-07-25.md asserts accrual "is enabled by the production L10 process"; the flag set says otherwise. (d) — added Phase 6, and it is inside the code. core/config.py's docstring for accrue_realized_knowledge states "the production L10 process enables it alongside persist_session_state", and the docstring for consolidate_determinations states the same about "accrue_realized_knowledge + persist_session_state". CONTINUOUS_LIFE_CONFIG_FLAGS (chat/always_on_daemon.py:45-49) forces persist_session_state, consolidate_determinations, strict_identity_continuity, and not accrue_realized_knowledge — so the first docstring is false outright, and the second is false in its "alongside accrue_realized_knowledge" clause. (Stated precisely on the 07-28 re-verification: an earlier draft of this entry said the flag set "contains neither claim's subject," which is wrong — it does contain consolidate_determinations. The false clause, in both docstrings, is the one naming the accrual flag as co-enabled. A third comment, on persist_session_state:283, makes the same shape of claim and is true.)
Why it hinders: demonstrated, not hypothetical — this assessment's own Phase 0 inherited a stale-record error, and the 2026-07-25 doc (itself a corrective document) introduced one. Every divergence is a future wrong analysis. Instance (d) is the sharpest: it is one layer below the documents, where a reader checking the code against the docs would stop and believe.
(e) — added 2026-07-28 (external-assessment triage), and it is inside the code again. core/cognition/inductive_closure.py's docstring rule "Cycle: if path would revisit a node, skip" (:106) describes a check the implementation does not perform — it checks a == c and known-triple membership only (:189-193), which is sufficient: the fixed point is monotone over a finite triple set, so no path-based check is needed for termination, and adding one would refuse sound transitive derivations (a witness path that revisits a node still proves a true fact). Separately, path records only (a, b, c) even for derivations whose chain is longer (:198), so the provenance serialized into operator_invocation is incomplete for multi-step derivations. The remedy splits: the docstring correction is mechanical and belongs with the amendment batch; extending path to full provenance changes operator_invocation bytes and therefore trace_hash, so it is held to the trace-change bar and must not land silently.
Better home: five amendments — ADR-0146 addendum owning the daemon (drafted in 50-rulings.md R-12a); ADR-0252 basis footnote (drafted, R-12b); a correction note on the 07-25 doc; the two docstrings corrected or the flag added, per R-3; and the inductive-closure docstring correction (e), mechanical.
Status (2026-07-28): (a) CLOSED · (b) CLOSED · (e) CORRECTED · (c)+(d) open on R-3.
(a) and (b) closed by R-12, executed 2026-07-28. ADR-0146 gained an addendum owning the daemon: the Shape-A rejection stands as reasoning, the supervision infrastructure it said would be required was subsequently built, and the "What is NOT in Scope" concurrency bullet is superseded for the daemon path only — with an inline pointer at the stale bullet itself, because H-8's mechanism is precisely that readers do not scroll to the end. ADR-0252 gained the basis footnote at the first use of "34". Every claim in both was re-verified at ca5e614e before writing rather than copied from the packet: 18 resolve_promotable_* organs, 0 outside generate/derivation/, exactly 32 modules; the daemon's lock, signals and identity guard all present with line references; the daemon's landing date confirmed as 18e25580, 2026-06-14.
Two errors caught in the amendment text before it landed, recorded because this entry is about records being wrong: the draft cited §9 for a sentence that is in §8, and misquoted it as "the existing reader" when the ADR says "the existing 34-organ reader." Both were found by re-reading the amendment against the source it quotes. Writing a misquote into a ratified document while amending it for accuracy would have been this entry's own failure, committed inside its own fix.
Also caught, and it is the reason the date is trustworthy: the container's clone was shallow (168 commits, roots grafted at 2026-07-19), so git log reported the daemon as first appearing on 2026-07-20 — the shallow boundary, not a fact. The packet's 2026-06-14 was unverifiable either way until the clone was deepened to 2340 commits. A date that cannot be re-derived is testimony; it is now evidence, and cited by SHA rather than by date alone.
(e) CORRECTED. expand_relation_closure's docstring now states that termination is structural (monotone growth over a finite triple set) and that no path-revisit check is performed and none should be — one would refuse sound transitive derivations. It also records that path is the witnessing step rather than full ancestry, and that extending it would move operator_invocation and trace_hash, so it is deliberately not done.
(c) and (d) CLOSED 2026-07-28 by R-3's execution in PR-5 — and they closed the opposite way round from how this entry framed them.
The entry assumed the records were wrong and would be corrected. They were not. Both core/config.py docstrings and the 07-25 verification doc described the intended profile accurately; the code was missing one flag. Adding accrue_realized_knowledge to CONTINUOUS_LIFE_CONFIG_FLAGS made all three statements true, so (d) closed with zero docstring edits. That is what "incomplete flag set" means as a ruling, and it is why R-3 A was correct: dormancy would have required correcting three records that were right about the design.
(c) closed by amending the correction note rather than deleting it — and the amendment is the more useful artifact. PR-1's note said the document's claim was false. R-3 then made that claim true, so the correction note itself went stale, in the direction nobody guards: a correction made wrong by its own subject being fixed. Both notes now carry the commit window they apply to. A dated correction survives its subject changing; an undated "this is false" does not — recorded in the document itself, since this entry is precisely about records that stop being true.
H-8 is now fully discharged: (a) and (b) by R-12, (c) and (d) by R-3/PR-5, (e) by the inductive-closure docstring correction. Authority: docs PRs + ruling signatures (R-12 — discharged; R-3 — discharged).
H-9 · Dead instruments still standing as if live
Verdict: superseded-in-place (unratified) · Layers: MV/governance
Evidence: docs/gaps.md — 26/26 closed, no entry from any 2026-06+ arc; substrate-liveness-ratchet — v5, stale since ~2026-05-24, all OPEN items L10-chained; ~130 analysis docs with no aggregator. The system map — the best macro artifact — is local, gitignored, 48 days stale, and was wrong precisely where the project moved fastest; its phantom "L12" stratum exists nowhere else.
Why it hinders: an instrument that looks authoritative converts "I should check" into "I already checked." Phase 0's error was this mechanism operating on this assessment.
Better home: this register supersedes docs/gaps.md (marked historical); the ratchet's 7 OPEN items migrate here (G-5 absorbs their L10 dependency); the map stays a regeneratable local index per D5, with "L12" dropped; the assessment directory becomes the standing ruled record, verified_at-stamped.
Authority: ruling (one PR).
Status (2026-07-28): CLOSED — R-7 ruled A; PR-3 landed. docs/gaps.md and the substrate-liveness ratchet both carry historical banners naming this entry's own mechanism as the reason. The ratchet's seven OPEN items (W-003/005/007/008/009/017/018, all L10-chained) migrated into G-5 with their dependency chains. L12 had no in-repo generator — the map is local and gitignored — so the phantom is recorded as ruled rather than deleted, which is the honest form.
H-10 · The demotion that mispriced the paradigm experiment
Verdict: strained framing — a correct ruling casting an incorrect shadow · Layers: M3/governance
Evidence: GSM8K was demoted to diagnostic (correct — the flags-and-benchmarks reasoning stands). The §5 SME experiment lives in GSM8K's neighborhood (holdout_dev/v1, math structures), so it inherited the demotion's priority — but its verdict governs the comprehension paradigm for everything, per ADR-0252's own §4 conformance bar.
Why it hinders: the highest-leverage open item in the project (G-1) has been priced as math-lane housekeeping.
Better home: none needed — G-1's execution is the fix; this entry exists so the mispricing mechanism is named and not repeated.
Status (2026-07-28): confirmed and discharged. G-1 ran to a recorded NO-GO in hours, not an arc (docs/research/sme-experiment-verdict-797ebad5.md) — which is the mispricing demonstrated rather than asserted. The entry also understated itself: the experiment had already been run twice and returned GO both times, and both results sat unmerged on rnd/ branches while the highest-leverage item in the project was recorded as unstarted. The demotion's shadow fell not only on the priority but on the retrieval of work already done.
Authority: already covered by G-1's ruling.
H-11 · A silent-failure pinhole inside a typed layer
Verdict: strained (small, cheap, principled) · Layers: M3
Evidence: _accrue_in_turn's broad guard converts any exception in the read→realize→determine chain into a no-op accrual with no telemetry (F-10). Defensible as a backstop; invisible as a signal — in the one layer whose constitution is "failures are typed, never silent" (INV-34).
Better home: count the swallow (a telemetry field on IdleTickResult/turn accrual), not a behavior change.
Authority: mechanical PR.
Status (2026-07-28): CLOSED — PR-9 landed, across all three instances.
chat/runtime.py::_accrue_in_turn—_accrual_swallows/_last_accrual_error, read viaaccrual_swallow_telemetry()._last_turn_accrualstill becomesNone, so_maybe_surface_determinationreturns byte-identically: additive by construction, and pinned as such.core/cognition/pipeline.pylogos authority —logos_erroronCognitiveTurnResult. An emptylogos_decision_kindpreviously meant either "not consulted" or "raised"; those are now distinguishable.- The OOV geometric probe —
probe_error,neighbor_scan_errors, andgraph_anti_unify_error. This block exists to price the anti-unification roadmap, and a crashed probe used to serialize identically to one that ran and found nothing.
Every guard stays deliberately broad. Narrowing them to ImportError/OSError, as an external assessment proposed, converts a malformed decision object into a turn-spine crash — trading silent failure for served-surface failure, the worse trade. What changed is visibility, not tolerance.
tests/test_accrual_swallow_telemetry.py, 7 pins, the two behavioral ones observed red against a build with the fields present but the recording removed — so they discriminate rather than merely pass. Registered in both gates on creation (#136); local/CI delta unchanged at ten (local 25, CI 15, CI-only 0).
H-12 · The two smoke gates have diverged by ten files, and one comment says they cannot
Verdict: strained — a real asymmetry, smaller than it first looks · Layers: MV
Evidence: TEST_SUITES["smoke"] is 23 files; .github/workflows/smoke.yml is 8 path patterns expanding to 13. The ten local-only files are test_audit_ledger_r7, test_cli_runner_contract, test_pack_draft_serve_boundary, test_workbench_deduction_provenance, test_prior_surface_deduction_binding, test_negation_survives_articulation, test_adr_status_governance, test_adr_index, test_volume_honesty, test_curriculum_polarity.
State the counter-evidence first. AGENTS.md §CI/CD is explicit that .github/workflows/*.yml are "secondary observability only — never a substitute for local gates": the merge gate is the in-worktree run, and the in-worktree run is the superset. Eight of the ten files carry in-code comments saying they belong "on the pre-push gate" — which is exactly where they are. Under doctrine, nothing is unguarded, and any reading of this entry as "ten pins run nowhere" is wrong.
Why it hinders, precisely: (1) two independent places assert the parity — the audio block in core/cli_test.py says it is listed explicitly "so the local-first pre-push gate (AGENTS.md protocol) equals the CI gate rather than silently narrowing it," accurate about the six audio files and false as the statement about the suite a reader will take it for; and scripts/hooks/pre-push, the automation of the AGENTS.md protocol itself, describes its own step 1 as "the smoke suite — exact CI-gate parity" while running 23 files against CI's 13. A claim made twice inside the enforcement tooling is the strongest available evidence that the drift was never intended; (2) the real exposure is the push that skipped the local gate — from a cloud session, another machine, or an agent — for which CI is the only automatic check, and for which ADR-0265's denial pin, both ADR-governance pins, volume honesty, and curriculum polarity currently run nowhere before merge. Six of these files were promoted after real silent-regression incidents (#136, #113, the 2026-07-20..24 register-axis drift), so the failure mode they exist to catch is demonstrated, not hypothetical.
Better home: the gate-parity pin in G-7 — the drift is only invisible because nothing measures it. Measured parity cost: 429 tests in 46s on the Act runner's own hardware (ubuntu-latest:host = native macOS host).
Authority: R-14 sets the direction (raise CI, or lower local, or keep them different and correct the comment); the pin itself is mechanical.
AMENDED 2026-07-28 (N-9) — "the drift was never intended" is withdrawn. It was intended, deliberated, and recorded.
A third artifact settles what two comments only suggested. tests/test_cli_test_suites.py::test_cli_smoke_suite_covers_ci_smoke_gate has enforced smoke.yml ⊆ TEST_SUITES["smoke"] all along — which is why this entry's own measurement finds CI-only = 0 — and carries a comment headed "DELIBERATELY ONE-DIRECTIONAL — do not 'complete' this by also asserting local_paths <= ci_paths." Its history is 50fa287d (2026-07-25): the bidirectional assertion was added and reverted the same day, because AGENTS.md:280 makes GitHub Actions "billing-locked … dead signals — never chase them" and §277 makes the workflows "secondary observability only."
So: the local suite is the source and is free to be broader; the ten-file delta is the designed state, not drift. What this entry got right is narrower and still true — one in-code comment (core/cli_test.py's audio block) and scripts/hooks/pre-push's "exact CI-gate parity" line both assert an equality that does not hold and should be corrected to say what the pin says.
And the real gap this entry was circling is elsewhere: the parity pin lives in the fast suite, while the pre-push gate runs smoke + deductive. The pin guarding the gate does not run on the gate. That is the mechanical fix worth making, and it is ruling-free. (Status: promoted into smoke on 2026-07-28.)
On the number itself — "ten files" is not an invariant and should stop being quoted as one. Measured at 98a6e8b4+ the delta is 12 (local 27, CI 15), because this session added three pins to the local suite. Under the corrected reading that is the design working, not drift widening: the local suite is the source and grows as pins are written; smoke.yml is observability and is edited only when convenient. The invariant is CI-only == 0, and that one is pinned. Earlier entries in this directory quote 10 (and 24/14, 25/15) as measurements true on their date; none of them is a target.
H-13 · The speculative-marker cache un-marks a sibling proposal's material on promotion
Verdict: defect — honesty regression on a served marker · Layers: M4/M5
Evidence: _speculative_subjects is a flat token OrderedDict with no owner tracking (core/cognition/pipeline.py:161). A SPECULATIVE proposal seeds its subject plus every ≥4-char non-stopword token (:726-729); on COHERENT promotion, _forget_speculative_subject pops the subject and each token regardless of which proposal added it (:736-739, :1045-1055). Promoting "practical wisdom" therefore evicts the shared token "wisdom" while an independent "wisdom" proposal is still SPECULATIVE — and that proposal's material is then served without its marker.
Why it hinders: the marker is the honesty surface for unreviewed material, and the failure direction is served-unhedged — the direction this architecture treats as the expensive one. (Provenance: surfaced by an external assessment that described this seam with the direction inverted — it claimed under-eviction; the code over-evicts. The verification that caught the inversion is what confirmed the real bug.)
Better home: a reference-counted cache (token → count of live proposals; decrement on promotion, evict at zero), with the LRU cap retained as a size valve. Failing test first: promote one proposal, assert the sibling's marker survives — red before green.
Authority: mechanical PR + red-then-green test; flag at review whether ADR cover is wanted, since served-marker behavior changes (in the honest direction).
Status (2026-07-28): FIXED — on the second attempt, and the first attempt is the more useful record.
The value of _speculative_subjects is now the set of subjects claiming each token (OrderedDict[str, set[str]]). A token is evicted exactly when the subject that actually claimed it is reviewed. Token derivation moved from the call site into _speculative_index_tokens, because ownership is precisely what the call site cannot see.
The first fix was a reference count, and it did not work. It rested on "seeding and eviction walk the same source list, so counts balance." They do not: the call site's arms are mutually exclusive — a proposal is seeded when SPECULATIVE or released when COHERENT, never both — so a release never balances a claim the same proposal made, and a COHERENT proposal always releases claims it never held. Refcounting therefore only repaired the sub-case where both proposals had been taught speculatively; the common case (an unreviewed wisdom, then a separate correction about practical wisdom that passes review on its own turn) still stripped the marker. Demonstrated after the refcount landed: sibling marked? False.
The first attempt's tests passed because their helpers split tokens themselves, testing a call pattern production no longer used — a test written to the fix instead of to the defect. The replacement helpers call the cache exactly as pipeline.py §10b does, and the lead pin (test_coherent_proposal_does_not_unmark_an_unrelated_subject) was confirmed to fail against the refcount design before the claimant design landed. 13 pins pass, 8 of them the pre-existing lifecycle pins, unchanged.
Ratification note: this changes served surfaces — markers now appear on turns where they previously vanished. The direction is toward disclosure and it restores ADR-0021 §Articulation's stated intent rather than extending it, so it is offered as a defect fix; say if you want ADR cover before it goes further.
Suite membership resolved, not deferred (G-7's mechanism, live). tests/test_speculative_subject_lifecycle.py pinned this exact behavior while sitting in no curated suite — reachable only through full — which is why the regression was invisible. It is now registered in both TEST_SUITES["smoke"] and smoke.yml, per the #136 precedent that an unregistered pin runs nowhere. Registering it in both leaves the local/CI delta at exactly ten files (verified: local 24, CI 14, CI-only 0), so it is compatible with all three R-14 options and settles none of them. PR-4 still owns the standing ten.
H-14 · The cognitive spine's turn method is 759 lines, with back-stamp repairs as the symptom
Verdict: strained — structure debt on the highest-traffic path; H-4's sibling · Layers: M3/M4
Evidence: _run_turn spans core/cognition/pipeline.py:189-947 (759 lines) under a module docstring still describing a thin delegating wrapper ("delegates to ChatRuntime internals… clean plug-in surface"). Trace-hash inputs accumulate across the whole span, and two explicit back-stamp calls exist (finalize_turn_trace_hash ×2, finalize_turn_surface ×1) because those values cannot be computed atomically where first needed.
Why it hinders: prospectively, H-4's mechanism — each landing phase is added inline, and the contributor must manually audit every prior phase for trace determinism. The back-stamps are the measured symptom, not the disease.
Better home: staged decomposition — deterministic pre-turn context → the delegated runtime.chat() call → post-turn resolution → a stateful learn stage (the teach step mutates the teaching store and the speculative cache, so a pure-tripartite framing is wrong and would mislead its own implementer). Zero-delta bar: byte-identical trace on the live lanes, PR-10's discipline.
Authority: refactor ADR, sequenced with or after PR-10 (H-4); not before Wave 2.
Explicitly examined and cleared
For symmetry with the Candidate Register's "considered and not registered" — hindrance candidates this audit rejects:
-
The 18 derivation organs — condemned but ruled to keep serving (
superseded-in-placeby explicit ruling); their continued service is governance working, not failing. The hindrance was their unreproducible count (H-8b), not their existence. -
Off-serve quarantines (holographic vault, wave modules,
topological_reasoning) — capacity that exists and cannot be used by AST-pinned design; legitimate research containment with failing-when-violated enforcement. An exit criterion would be nice (M1 card); the quarantine itself is fit. -
Pure-Python-by-default algebra — measured as the correct posture: determinism is the product,
versor_conditionis 0.22% of turn time, and the urgency argument for Rust-by-default dissolved under measurement. The open parity question (blocked on network) is a question, not a hindrance. -
The five unreconciled articulations — dissolved by the taxonomy (D1), not a standing hindrance; the residue is one stale Draft banner (folded into H-8's amendment batch).
-
Flag-gated conservatism itself — seventeen dark flags is not inherently hindrance; unregistered darkness is (G-8). The posture may be exactly right; the register exists so that judgment can be made deliberately.
-
Six proposals from two external assessments (2026-07-28) — each verified against code and cleared, with the refuting file named: EpistemicState compression (the "unused" states are the vault's refuse-forcing states and the serving path's
UNVERIFIED_POSSIBLE—vault/store.py:99-103,chat/runtime.py:1329; ADR-0206 already partitions the taxonomy per-state incore/response_governance/policy.py:64-100); an EpistemicState×NormativeClearance product type (forbidding DECODED+SUPPRESSED at the type level erases the refusal's evidence — H-3's failure rebuilt as a type constraint; the coupling already exists as policy, where the legitimate combinations are decided); PID attestation onlived_life.json(a reboot-resumed life's writer PID is dead by definition, so the check refuses every legitimate resume, and PID reuse defeats attestation — the same pid-file pitfalls the lock's own comment derives against); path-based cycle skipping in the inductive closure (would refuse sound transitive derivations; see H-8e — the docstring, not the code, is the wrong side); a depth-enrichment session cache (the cost it targets is already@lru_cached at the pack layer,chat/pack_resolver.py:19; measure first — the 0.22% Rust precedent); a unified reasoning engine presented as refactor (changesoperator_invocationbytes →trace_hash, silently widens capability by letting compose see closure-derived triples, and reduces entailment to set membership one merge after ADR-0265 ratified denial representation — the underlying facts are real and are recorded as design considerations under H-4/H-14). Triage rule kept from this round: no external lead folds in without the one-more-file check — every rejected proposal above failed on a file its author did not open. -
Six architectural proposals from a third external assessment (2026-07-28), whose author states the method up front: "I have enough from the directory and CLAIMS.md to reason seriously." That is the method
AGENTS.mdprotocol rule 1 forbids, and the hedges mark where it broke — "almost certainly a nested conditional or a big dict," "likely doing both," "may be operating at a resolution." One folded in (G-23); five falsified by opening the file:conftest.pyis "almost certainly the most dangerous file in the repo"; suite-membership logic has accumulated in it. False. It holds two autouse engine-state isolation fixtures, a QUARANTINE nodeid registry, a SLOW_FILES/SLOW_TESTS registry,_is_slow, andpytest_collection_modifyitems— which stamps markers and never skips ("classification ONLY, never skipped here"). Zero suite membership, zero gate-tier assignment, zero conditional inclusion. The 12KB is two data tables with per-entry justifications: already the declared-table pattern the proposal asks for.cli_test.pymanages suite topology "through what is almost certainly a nested conditional or a big dict." A flat dict — 17 keys, all tuple values, zero conditionals in the module body. 463 lines, 171 of them comments (37%). The surviving half of the point — gate tier is a property of which suites the shell invokes, not of the suite — is real; but it is already declared and verified:test_suite_reachability.pydeclaresGATE_SUITESand asserts it againstpre-push/local-ci.shprecisely so the pin cannot go vacuous. The claim that this "makes pin 3's ratchet trivially implementable" describes a pin that shipped this arc.field/+algebra/+morphology/are a triad a caller must compose correctly or bypass the ratification contract; give them a singleserve(). Not a triad.algebra/has 72 non-test importers (a foundational library),field/15,morphology/3 — andmorphology/is 2 files, 97 lines total. Nodef serve(exists anywhere incore/,chat/orgenerate/; the blessed path isChatRuntime. Top-level directories look like peers regardless of size, which is the entire content of this proposal.- The epistemic grade space is richer than the serve layer consumes; collapse it. All 15
EpistemicStatemembers have non-test consumers (min 1, max 13). Nothing is unconsumed. Compression was already examined and cleared in the round above, on different evidence. - Give each of the 260+ ADRs a machine-readable
constraints:block. The count is 314, and the class already exists in the better direction:test_adr_status_governance.pyparsescore/config.py's bool flags with their cited ADR numbers and fails when a default-ON flag is governed by aProposedADR, with a non-vacuity guard. The proposal inverts this the wrong way — 314 ratified, immutable decision records each carrying live assertions is 314 new places that must be kept true, in the repository whose dominant defect class is records drifting from reality. Either the ADR is edited when code moves (breaking ratification) or the assertion goes stale (H-8, at 314×). Machine-readability belongs in the checker that reads the ADR, not in the ADR. - The unifying proposal — a root
contracts.tomlholding every declared relationship — is "the highest-leverage single change." The principle is already this repository's (ADR-0263 Rule 5: declared in the table, not the call site) and is implemented in the very file the assessment cites:core/epistemic_state.pydeclaresGroundingSourceas a closedLiteralplus a runtime-iterableGROUNDING_SOURCESfrozenset, single-sourced across the runtime, the lane validator, the Workbench API coercion, and a build-time enum-coverage test underworkbench-ui/— and its docstring records the bug that pattern caught (unregistereddeduction/curriculumlabels floored to"none", "recording a proved answer as ungrounded in a durable audit artifact"). Centralizing four tables with four different authorities and lifecycles into one file adds a fifth copy that must agree with four generators; it is a ratchet to guard ratchets (standing philosophy 2). Cleared as a proposal, kept as an observation: nobody can currently enumerate "which declared tables exist and what enforces each" — that is one page, folded into PR-5, not a new mechanism.
What it got right, and it is worth saying: proposal 1 pointed at the pack/domain seam. Every specific was wrong, and reading the code there anyway found G-23 — a real, load-bearing, one-directional check on the band whose license is next to be earned. Bad method, useful direction. The triage rule survives unchanged and earned a second demonstration: every rejected proposal above failed on a file its author did not open.