feat(aep): human-alignment skill v3.3.0 — one-page project brief from product-context.yaml - #29
Merged
Merged
Conversation
… product-context.yaml Implements docs/decisions/human-alignment.md (PR #28, revision 7). The planning layer gets a human-facing surface: one command turns product-context.yaml into a single self-contained HTML page answering where are we, what needs me, and where reality drifted from intent. Proven end-to-end against a real 396-story consumer, whose unedited output ships as the reference example in docs/human-alignment/example-looplia/. Skill (skills/human-alignment/, a fifth marketplace plugin): - derive.mjs — the only legal source of numbers; validates its own output against facts.schema.json before anything reads it - scan-workspace.mjs → arch-rules.mjs → receipt-consumer.mjs — the deterministic architecture pipeline; rules R1–R10 are executable data, and repairs come only from archify's structured receipts within a two-round bound - audit.mjs — the independent mechanical audit; the agent that wrote the prose does not grade it - assemble.mjs — srcdoc-embeds five diagrams into one file, prunes to newest 3 - template.html — the single source of CSS classes AND of the data-fact binding convention, so number provenance is statically checkable Framework specs (skills/product-context/_shared/references/): - attention-set.md — what needs a human, deterministic one-ask order, per-predicate schema tolerance - drift-facts.md — the five drift derivations; hand-authored drift is banned Tooling: - build-skills.sh materializes shared resources into top-level skills, not only product-context children — a standalone skill must carry its own copy because the skills CLI installs one directory at a time. Existing corpus byte-identical. - oxfmt ignores docs/human-alignment/example-*/ — generated artifacts are evidence, not source, and reformatting them would break their content digest. Two derivations corrected by running against real data rather than a fixture: intent-without-evidence derives from the coverage counters (coverage.uncovered is empty precisely when a gate never opened), and its layer scope excludes `ready` as well as `pending` — a dispatchable task is not a started one. Only a `passed` gate yields an unchipped capability; `scripted_passed` appears solely under an EXP chip naming the acceptance run that would settle it. Known gap: evals/skill-routing-observations.json has no entries for the three new routing cases. Those record an independent model's selection against the installed description corpus and cannot be authored by the agent that wrote the description. check-skills-package.sh fails until that probe is run. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EDTHXC2N5mDL1DtFXopAWn
Adding aep-human-alignment changed the description corpus that routing decisions are made against, so the whole suite was re-run rather than the three new cases appended — the recorded run binds to a corpus digest, and a partial update would leave 36 selections attributed to a corpus that no longer exists. Method: a subagent was given exactly one file (the 23 skill names and descriptions, plus the 39 prompts), instructed not to open any other file and not to look for the expectation list, and asked to self-report confidence. It made one tool call. The description text it saw was verified byte-identical to what the official Agent Skills parser produces before the digest was recorded. Result: 39/39 match expectations, zero regressions. One boundary probe (validate-vs-gen-eval) came back medium confidence; the rest high. The three human-alignment cases all resolved correctly, with aep-envision and aep-watch as runners-up — the two neighbours those probes were written to test. check-skills-package.sh now passes. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EDTHXC2N5mDL1DtFXopAWn
…ructural Owner rulings after the implementation run, on what the Engineering band is for. (a) The band is prospective and structural, not a deeper cut of progress. An engineer needs the current structure and what the next design does to it; "where work happened / what it cost / where it failed" is Project's depth. Spine: Now · Concepts · Next · Options. (b) The ontology stops being a deployment taxonomy. Nodes are concept modules measured against the code units that carry them — derivable today, because stories[].module and files_affected are present on 396/396 stories in the reference consumer with 84% of paths resolving to a real package. (c) R7 is corrected from a naming convention to a measurement. Splitting package names on a hyphen was deterministic and worthless: 14 domains from 19 packages, 11 singletons, and it discarded 32 prose module descriptions. Determinism is a means to trust for claims about reality; a grouping is not one. (d) D8 — suggestions are allowed, as Design Option Sets with a required grammar: derived trigger, >=3 options including "leave it as is", per-option cost in the project's own measured terms, a design sketch, and a stated ranking criterion. Bare one-liner recommendations are banned. (e) Thresholds are fixed in the spec, not configurable, and all detectors run against the Next projection only. The control run earned that scope rule: on completed work the same detectors produce 5 / 3 / 68 hits, all noise. A third detector (declared-independent modules sharing files) is rejected from v1 at 68 hits with no principled cut point, rather than tuned until it looked reasonable. (f) The mining principle: when a signal looks underivable, ask what the project actually records. Revision 7's implementation broke this three times and each error shipped — cost was in stories[].cost_usd ($735.15) not the zeroed roll-up; the module-to-code binding was measurable from the work record; and the "1 name in common" figure compared declared modules against package names instead of against the modules stories are filed under (44 used vs 32 declared). Calibrated on the reference consumer: concept crowding fires exactly once (do-agent, 7 concepts, 85 files, 81% pairwise-disjoint), homeless concepts zero. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EDTHXC2N5mDL1DtFXopAWn
…ve Engineering, Design Option Sets Brings the implementation up to decision doc revision 8 and regenerates the looplia example against it. The three false statements the previous example shipped are gone, because the signals behind them turned out to be derivable. Mining (derive.mjs): - cost rolls up from stories[].cost_usd — $735.15 across 34 priced stories, attributable per module — instead of trusting a zeroed cost.total_usd. Their disagreement is now itself a drift fact. - concept-to-code binding measured from stories[].module x files_affected: 30 of 44 concepts resolve to a real unit. Drift 5 restated accordingly; architecture.modules[].paths becomes a way to declare what is already measurable, not a precondition for measuring it. - module vocabulary drift: 44 modules used by work vs 32 declared, 13 never written down and 1 declared but never touched. This replaces the old "1 name in common" figure, which compared declared modules against package names — the wrong two sets. - structure plane: Now / Concepts / Next / Options, with the D8 triggers at their fixed thresholds, scoped to the queued-work projection only. Architecture (arch-rules.mjs): - R7 no longer synthesizes domains from package-name prefixes. Tiers are now "what exists now" (units annotated with the concepts they carry), "where the next design lands" (queued work projected onto them), and the declared narrative. The dead name-stem helper is removed with the rule it served. Surface (template.html): - Design Option Set markup and styling: trigger, options as buys/costs/design/ settled-by, and a criterion line that states how the ranking was chosen. Example regenerated at looplia 65e359c6: 31 data-fact bindings, zero unresolved; five archify artifacts green within the two-round bound; audit passes standalone; one Option Set fires (do-agent, 7 concepts, 85 files, 17 of 21 pairings disjoint) and its cleanest seam is company-assurance-incident-ops at zero shared files — correcting the by-hand reading that named authority-kernel, which shares one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EDTHXC2N5mDL1DtFXopAWn
An independent generator/evaluator pass on the generated brief returned FAIL. Nine content defects; eight of them are the same defect wearing different clothes: the prose needed a fact the derivation had not produced, so the authoring agent supplied it from a diagram label, from ambient knowledge, or by counting manually — and the audit could not object, because its unit of check was the digit rather than the claim. Root cause: the facts plane was designed top-down (what should the brief show?) against a source carrying 483 populated key paths, of which the derivation reads about thirty. Every hole was a path nobody had looked at. D9 replaces hole-by-hole patching with four deterministic mechanisms: 1. Source census — enumerate every populated path in the plan file and classify it against a committed manifest as derived / ignored(with a reason) / unhandled. Unhandled paths carrying data are reported, and the brief states its own reading coverage. Closes the cost, files_affected, attempt_count and closure_status defects at once. 2. Claims bind, not numbers — every assertive block declares the facts it rests on; no uncited assertive block may exist; number-words count as numbers. One rule closes both the unbound numeral and the uncited causal claim. 3. Facts carry predicates, not raw fields — retries_exhausted, sign_off_withdrawn, root_cause_stated, completions_in_window. If the predicate does not exist, rule 2 forbids the sentence, so the derivation and the prose are forced to co-evolve. Corollary: a fact may not collapse ambiguity — ties are carried whole, or the prose will assert uniqueness. 4. Every tool declares its own coverage — a scanner reports what it did not cover, and no tool may imply totality. Owner rulings: classification is at path-template level (~100 entries, not 483 leaves), and an ignored entry must carry a reason rather than a checkmark. Recorded honestly: one of the nine (an unsorted changelog slice) is an ordinary bug that none of these mechanisms would have caught. Eight become structurally impossible; one was simply wrong code. Acceptance is not "the defects are gone" but "the defects cannot be authored": re-running against the reference consumer, the census must report the unhandled paths that produced them and the audit must reject the sentences that shipped. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EDTHXC2N5mDL1DtFXopAWn
…rage declaration The four mechanisms from decision doc revision 9, each verified against the specific defect it exists to prevent. 1. Source census (census.mjs + source-census.json) Enumerates every populated path template in the plan file and classifies it as derived / ignored(with a reason) / unhandled. Subtree rules (`a.b[].*`) let one genuine reason cover one homogeneous group; the most specific rule wins, so exceptions stay expressible. An ignore rule with no reason fails the census outright — a checkmark records that someone clicked past a field. Against the reference consumer: 486 populated paths, 55 derived, 431 ignored, 0 unhandled, read coverage 11.3%. The number is small and that is the point: it was previously unknown. 2. Claim-level audit (audit.mjs) The unit of check moves from the digit to the claim. Every assertive block must carry data-claims, an inline fact binding, or an explicit data-authored mark; number-words count as numbers. Run against the prose that shipped, it now raises 50 receipts — 18 number-words and 32 uncited assertions, the first being the headline sentence the evaluator found contradicted by the source. That is D9's acceptance bar: not "the defects are gone" but "the defects cannot be authored". 3. Predicates (derive.mjs) retries_exhausted, root_cause_stated, sign_off_withdrawn, successor_layer, completions_in_window. Each exists because prose previously inferred it: "automatic repair has already given up" (attempts used 0 of 2), "a specification and an implementation disagreeing" (both failure logs record the root as unproven), "the last thing before sign-off" (the acceptance was retired by owner decision, successor layer 41). A withdrawn sign-off now also drops the layer from the capability list. 4. Coverage declaration (scan-workspace.mjs) The scanner reports what it did not read. On the reference consumer it names four unscanned Rust crates including apps/daemon — work the same page prices at $55.09 while excluding it from "the system". Also fixed: the changelog was sliced from the tail without sorting, so the newest entries were invisible. It is 26-pairs out of order in the reference consumer, and the entries being missed were the owner decisions that closed the current layer. Ids now bind to the source index, not to list position. The example artifact is deliberately NOT regenerated in this commit: the new audit rejects its prose, which is the evidence that the mechanisms work. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EDTHXC2N5mDL1DtFXopAWn
Two independent evaluator rounds have now run against the generated brief. Both returned FAIL, and the second failed differently from the first — which is the finding worth recording. Round 1: the prose needed facts the derivation had not produced, so the agent supplied them from diagram labels, ambient knowledge, or manual counting. That produced D9 (census, claim-level audit, predicates, coverage declaration), and those mechanisms hold: the round-1 defects are now unauthorable and the round-1 prose is rejected by the current audit. Round 2, on the far side of that fix: - A queued stage is called unstarted while its only story completed hours before generation; the citation counts pending/deferred, which say nothing about that layer. - "closed by your decision last week" — the decision is dated the same day, and the anchor prints that date directly beneath the words. - "first brief, nothing to compare against" is true only because regenerating by rm+cp bypassed assemble.mjs and discarded the committed baseline. Checklist P2 fails. - The DELIVERED file fails the skill's own P0 audit with 34 uncited assertions: the audit was only ever run on the authored HTML, never after assembly. Three injected diagram captions carry numbers contradicting the prose beside them (18 vs 21 units, 30 vs 31 concepts, 8 vs 7 net-new) — partly a labelling gap, partly a code graph one commit behind the facts. - Several citations resolve without bearing their sentence: the scripted_passed count bound to a clause that means the EXP capabilities; cleanest_seam (one module, no size) bound to a sentence naming two and comparing size. The last item is the design finding. Mechanism 2 enforces that a path resolves; it cannot enforce that the path bears the claim, and a citation that resolves without bearing is worse than none because it reads verified. Recorded as an open question in eval-findings.md rather than patched — two rounds have produced two different failure modes, and a third round of the same shape would not be evidence of convergence. The example and its README are flagged as failing. This PR must not merge. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EDTHXC2N5mDL1DtFXopAWn
Each fix is verified by the defect firing before and not after. 1. Audit the delivered file, not only the authored one. Phase 3 ran before Phase 4 injected the diagrams, so nothing ever checked the artifact that ships. `--delivered` excludes embedded payloads from the claim rules — that prose is archify's, validated separately — while still checking provenance. On the round-2 artifact it drops 34 false positives and leaves the one real finding. 2. Commit-skew gate. The round-2 brief embedded a code graph one commit behind its facts, which is why three diagram captions disagreed with the prose. assemble.mjs now refuses to write when facts and code graph name different commits, and the delivered audit raises the same skew as a receipt. 3. Baseline-destruction guard. "This is the first brief, there is nothing to compare against" was true only because regenerating by rm+cp bypassed assemble.mjs and discarded the committed ledger. assemble.mjs now refuses when the manifest names a brief that is no longer present and history is empty. The destroyed baseline is restored from git, and the example now carries a real history[] with two retained briefs. 4. Diagram captions state their own scope: "18 of 21 units shown after R1/R2 reduction" rather than "18 units" beside prose saying 21. The reduced count and the raw count were both correct and neither said which it was. The example is regenerated in place at a single commit and the delivered file now passes its own audit. Round 2's remaining findings — citations that resolve without bearing their claim, a scoped measurement stated unscoped, a dependency described backwards — are NOT fixed here; they need a design answer, and they stay recorded in eval-findings.md. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EDTHXC2N5mDL1DtFXopAWn
…he page Scope note first, because revisions 7-9 blurred it: this revision is about the surface's own design. The reference consumer's plan-file hygiene — stale calibration entries, gates never flipped, an unwired cost roll-up, undeclared modules — is that consumer's business and /aep-validate's. Those are evidence about what this surface makes visible, not requirements on it, and treating them as requirements is how a rendering skill grew a detector suite. D10 — The unit of delivery is the clock, not the page. Revision 9's velocity number was the interval between edits, not the survival time of a fact. Re-measured over sixty commits the bands do not share a clock: band 1 (the attention set, the one ask) survives ~110h, band 2 ~29h, band 3 and 4 ~10h. Revision 6's band split turns out to sit almost exactly on the seam in the survival curve — that decomposition was right. Fusing the bands into one file is what is wrong: to keep the fastest band true you re-author the slowest band's prose about a hundred times per fact change, and each pass is an independent draw from the defect distribution. Of eighteen findings across two evaluation rounds, two or three are staleness; the rest are authoring failures against a fact plane that was correct and twenty-two minutes old. Ruling: emit the fact plane per commit, answer "what happened since I last looked" at read time in events rather than states, and generate the orientation document per layer. The delta narrative — the design's own velocity answer — has never produced a line of output and is promoted to a first-class emission. D11 — Render; do not detect. The skill accumulated detectors because it was the surface that noticed. A finding that wants an action belongs where it can block (/aep-validate), not in a document where it narrates. The derived-view specs stay framework vocabulary that both consume. This removes the pressure that produced the detector suite. D12 — Never a private store. A reviewer proposed an owner-ledger for rulings, obligations and invariants. The insight is right; the mechanism is not. The framework already defines product.decisions[] and product.open_questions[].revisit_trigger — a private file would be a third home for a truth the schema owns, which is exactly the second-source failure D7 exists to prevent. Where a consumer invents fields the schema does not define (the reference consumer added closure_status, decision_realignment, notes, release to its gates), that is itself drift to surface. The one genuine gap is obligations: manual_pending is a boolean with no owed_by and no since, so nothing can age or escalate it — recommended to the schema, following the modules[].paths precedent. D7 corrections, the design's own: the one ask must order topologically before alphabetically (the rule selected a blocked item over its blocker), and every signal must carry a `since` because age is often the finding. D9 corrections, the design's own: the census postcondition must be adversarial (unhandled_count == 0 was satisfied at 11.5% coverage, and one templated ignore caused the one-ask defect), and claim-binding raises apparent verification without raising verification — it needs a checkable claim-to-fact relation or a downgrade from guarantee to lint. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EDTHXC2N5mDL1DtFXopAWn
…rdering Two changes, both from revision 10. D7 correction: the one ask now orders topologically before alphabetically. Within a rank and layer, an item another candidate depends on comes first. The alphabetical tie-break alone selected a blocked story over its own blocker and told the reader to restart it; against the reference consumer the ask flips from FIX-L32-CANARY-502-001 to FIX-L32-SUPERVISOR-START-001, which is the one that actually unblocks anything. D10 emission 2: pulse.mjs — the read-time answer to "what happened since I last looked". It is the piece the design has specified since revision 2 and never once produced. It writes nothing, asserts nothing, and deals in events rather than states, so the failure mode behind every content defect in two evaluation rounds has no surface to occur on. Four sections: obligations with their age, transitions since the cursor, what needs a human (dependency-ordered), and open work that has stopped moving. Against the reference consumer it immediately surfaces what nine revisions of brief never did: two obligations addressed to the owner personally, 46 and 45 days old, recorded only as prose inside a gate's notes field, which no framework consumer can read and nothing ages or escalates. SKILL.md now leads with the three emissions and their clocks, and says plainly that generating the orientation document per invocation was the mistake. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EDTHXC2N5mDL1DtFXopAWn
…emissions The fact plane, the pulse, and the orientation document, all at one commit. Both audits pass — the authored file and, for the first time, the delivered one. The pulse output is captured alongside the brief so the two forms can be read against each other: the same project, one as computed events, one as careful prose. Also fixes a pre-commit defect this commit exposed. oxlint and oxfmt error rather than no-op when handed nothing they handle, and a glob alone was not enough: .json staged under a path in .oxfmtrc.json's ignorePatterns still reaches oxfmt, which filters it away and exits non-zero. A docs-only commit could not pass. Both jobs now carry a glob and oxfmt guards on the post-filter set, so an empty result is a no-op while a real formatting failure still fails. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EDTHXC2N5mDL1DtFXopAWn
… renders The skill had been accumulating detectors because it was the surface that noticed. A finding that wants an action belongs where it can block. Five checks move out of derive.mjs and into a shared detector: completed stories under a gate recorded as not_started; a gate status outside the defined set; a roll-up that disagrees with the record it summarizes; a module used by stories but never declared, or declared and never worked; and fields a consumer invented that the schema does not define. Against the reference consumer they find 9 blocking and 4 warnings — findings that had been narrated weekly in a document while nothing stopped. /aep-validate gains them as Step 0: mechanical, deterministic, run before any agent is spawned, exiting non-zero on a blocking finding with a fix for each. Agents cannot evaluate an artifact that contradicts itself, and spending agent judgment on what a check already decided is waste. A Control-plane coherence dimension is added to Mode A. human-alignment now imports the same detector and renders its output as drift facts. It no longer owns the logic. The detector is shared rather than duplicated: build-skills.sh materializes _shared/scripts/ into consumers on the same per-file rule it has always used for references — a skill receives what its SKILL.md names. Two copies of a drift detector drift, and a drift detector that drifts is worse than none. The existing corpus stays in sync and the build fixtures pass unchanged. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EDTHXC2N5mDL1DtFXopAWn
Converges the release to what actually survived ten revisions and two failed evaluations: the deterministic half. The skill's description led with the one-page brief — the emission that failed both evaluations — so routing sent people at the unproven path. It now leads with what is supported: where a project stands, what is owed to a human and for how long, and what changed since you last looked. The marketplace entry and the README catalog row follow. SKILL.md now carries a maturity column. Emissions 1 (the fact plane) and 2 (the pulse) are supported. Emission 3 (the brief) ships unproven and says so, with a pointer to the committed findings, a note that its per-layer trigger is unbuilt, and the specific warning that its audit passing does not mean its claims are verified — the audit checks that claims cite facts, not that the facts bear the claims. The example directory is reframed as evidence rather than a model: the machinery passes, the prose does not, and that distinction is the finding. The pulse output for the same project sits beside it for comparison. Routing re-run: the description change invalidated the recorded corpus digest, so the whole 40-case suite was re-probed by an independent subagent under the same one-file protocol. 40/40 match. A new case covers the pulse phrasing directly, and human-alignment-direct is reclassified as a boundary probe since it now competes with envision — the probe self-reported medium confidence there, which is recorded rather than smoothed over. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EDTHXC2N5mDL1DtFXopAWn
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
/aep-human-alignment— a project pulse. Answers where a project stands, what is owed to a human and for how long, and what changed since you last looked, fromproduct-context.yaml.Implements
docs/decisions/human-alignment.md, which went through ten revisions and two independent generator/evaluator rounds. Both rounds failed the artifact the design originally set out to produce. What ships is what survived that: the deterministic half. Additive → v3.3.0.Three emissions, three clocks
The design's central error, found by re-measuring in revision 10: the facts do not share a clock. The attention set survives ~110 h; story-status counts survive ~1 h. Fusing them into one document meant re-authoring the slow prose at the fast plane's rate — about a hundred authoring passes per slow fact change, each an independent draw from a defect distribution.
derive.mjs,census.mjs,facts.schema.jsonpulse.mjsThe pulse writes nothing and asserts nothing. Against the reference consumer it immediately surfaced what nine revisions of brief never did: two obligations addressed to the owner personally, 46 and 45 days old, recorded only as prose inside a gate's
notesfield, which no framework consumer can read and nothing ages or escalates./aep-validategains a blocking coherence precheckFive plan-file defects that want an action rather than a reader moved out of this skill (D11): completed work under a gate recorded as never started, an undefined gate status, a roll-up disagreeing with the record it summarizes, a module used but never declared, and fields a consumer invented. They run mechanically before any agent is spawned and exit non-zero. On the reference consumer: 9 blocking, 4 warnings — findings that had been narrated weekly while nothing stopped.
The detector is shared, not copied:
build-skills.shnow materializes_shared/scripts/on the same per-file rule it has always used for references. Two copies of a drift detector drift.What is honestly not ready
Emission 3 ships unproven. Two independent evaluations failed it — not on machinery, which passes (facts validate, five archify artifacts reach green inside the receipt bound, both audits pass), but on prose asserting more than the facts carried. Findings are committed at
docs/human-alignment/example-looplia/eval-findings.md; the generated example beside them is evidence, not a model.The deepest finding, and the open design question:
D9's claim-binding makes citation mandatory; nothing makes the sentence follow from the citation. Recorded in revision 10 as needing either a checkable claim-to-fact relation or a downgrade from guarantee to lint.
Verification
build-skills --checkin sync ·test-build-skills3 fixtures passcheck-skills-packagePASS — 23/23 skills valid, 40/40 routing selections re-probed by an independent subagent after the description change invalidated the corpus digestReview focus
_shared/scripts/— extending the materialization mechanism to executables.evidence.manual_pendingis a boolean with noowed_byand nosince, so nothing can age it. Recommended to the schema in D12 rather than solved by a private store.🤖 Generated with Claude Code
https://claude.ai/code/session_01EDTHXC2N5mDL1DtFXopAWn