Repository navigation
feat(gaps): second parallel wave over 19 gaps — 5 closed, 14 advanced, 1 new P0 found - #233
Merged
Merged
Conversation
…ave caused Nine agents with disjoint file ownership, then serial verification against a worktree pinned at HEAD so "regression" and "pre-existing" were separated by measurement rather than by how the failure looked. Two gaps close. GT-613 — `implements IStructuralReviewer` returned zero hits against a port, a provider and a rubric that were all already in place; `HeuristicStructuralReviewer` now satisfies it in-process and deterministically. GT-593 — a run killed mid-pipeline restarted from zero, so for an audit product the record of what happened depended on when it crashed; an append-only step journal content-addressed on input makes it resumable, and the set that is NOT resumable is written into the port rather than left implied. Seventeen advance, several by refuting their own row. GT-602: the 15 MCP tools denied in production are permitted with each tool/role pair argued individually, because an authorization widening has to be argued and not asserted. GT-586: a verdict now carries who asked for it and which revision it judged, additively — absent in, absent out, since an invented commit sha in an audit trail is worse than an absent one. GT-614: the pipeline reads the requested kinds BEFORE executing, and an unserviceable kind is refused instead of silently dropped. GT-595 measures the corpus instead of guessing at it: of 380 rules, 129 are documentation or declare no check at all, so the "240 handlers to write" figure was counting work nobody can do — that reframing is worth more than the handlers it also adds. GT-598 maps the corpus against ISO/IEC 5055 to find what could be adopted rather than authored. GT-591 brings the Rego corpus to v1 (85/85 files) without touching the toolchain pin, because a half-migrated corpus under a new binary is worse than the current state. Three findings are worth more than the fixes. GT-571 was tested against the published registry rather than assumed, and came back REFUTED harder than the row claimed: @beyondnet/evolith-cli@1.2.0 does not survive a clean install — even `--version` dies with MODULE_NOT_FOUND, because a deep import resolves only through the workspace symlink. The new check-install-smoke script is what found it. GT-608 corrected its own brief: the claim that all 16 capabilities declare `requiresApproval: false` was false before the wave started. GT-424's guard was green in one direction and blind in the other. The wave broke two things and both are repaired here rather than deferred. `npm run test:contract` went red because GT-595 added five fields to ValidationResult without the wire contract that pins it — that suite is a required check, so the wave could not have merged. And 34-check-skill-registry- parity went red on five capabilities it called unroutable. That second one is the more interesting repair, because the guard was right about the old world and wrong about the new one. GT-608's derivation now synthesizes a routable skill for every unbound manifest capability, so reachability holds by construction; the five hand-written descriptors the guard demanded would have changed nothing observable and would in fact have broken the runtime, since binding a capability suppresses its synthesized twin and renames the id every caller targets. I wrote those five descriptors first, watched four agent-runtime tests go red, and reverted them. R3 now measures the effective surface — but it audits the derivation instead of trusting it: the synthesizer must be exported, actually called, and filtering on nothing but the complement of the bound set, with three negative fixtures including the one that matters, a synthesis narrowed by a single extra conjunct. The report keeps hand-bound and synthesized separate, because a synthesized skill answers only to its capability name and never to a natural intent, and one number would have hidden that. Verified: root build clean; core-domain 1336 + 13 e2e; core 62; contracts 68; mcp-server 432; core-api 168 + 5 e2e; sdk-client 63; infra-providers 125; agent-runtime 384; agent-runtime-api 81; CLI unit 1382; test:contract 43; test:exploration 6 with findings=0; governance 17/17; the four validators CI runs and the local runner skips; OPA 224/224; guard 34 self-test 15/15. Two pre-existing failures recur and are NOT from this wave, confirmed against a pinned HEAD worktree: the CLI e2e `--arch` case (the test invokes a flag the command never exposed) and a stale COVERAGE_REPORT.md. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…rds it built
Five gaps close: GT-613, GT-593, GT-598, GT-581, GT-424. Fourteen advance with
their remainder stated. One new row is registered — GT-625 — and it is the most
important thing in this commit.
GT-625: the published CLI is not installable, and the workspace is what hid it.
GT-571's first acceptance criterion had sat open for weeks as "blocked on
GT-570"; with 1.2.0 published, it was finally testable, and testing it refuted
the row harder than the row claimed. `npm i @beyondnet/evolith-cli@1.2.0` into a
clean directory installs, and then `--version` dies with MODULE_NOT_FOUND: the
shipped dist deep-imports a subpath the published core-domain does not expose.
Inside this repository the same import resolves, because the workspace symlink
points at source rather than at what was packed — so the CLI's 1382 unit tests,
its e2e suite and the exploratory tester are all structurally blind to it. This
is the maturity audit's "a green local run is not evidence" with a new hiding
mechanism: not a stale dist, not a gitignored directory, but npm workspaces.
Three guards the wave built were sitting outside CI, which in this repository is
the same as not existing — the board already tracks one dormant guard that let
inconsistencies accumulate undetected. All three are now in the governance job:
43 (every scanning guard OBSERVED failing against an empty tree, 33/33), 44 (ADR
implementation-status declarations resolve, 280 scanned, 212 baselined) and 34
(skill-registry parity). The dead-reference ratchet drops 305 -> 303, and the
number is no longer machine-dependent: the guard now prints its own basis,
adding back references that resolve only through generated state, so a laptop
and the runner agree despite raw counts differing by 15.
The 44 guard came out of the session scratchpad, where its author had left it as
a handover because `.harness/scripts/ci/` belonged to another agent that wave. It
would have been lost. Its classification in `guard-classification.mjs` is the
registration that keeps 42 honest about it.
Three things the board's own machinery caught while I wrote this up, each of
which I had gotten wrong:
· I first wrote the Spanish board's wave notes in English. That is GT-620
inverted — a Spanish file in an English slot — and `04-check-bilingual-parity`
compares heading counts, so nothing would have failed. Rewritten in Spanish.
· `08-validate-tracking` rejected five closure records whose evidence paths I
had guessed rather than read. All five were wrong.
· `05-validate-executive-summary` refused a board of 625 against a maturity
reconciliation of 624.
Board: 573/625 done · 25 in progress · 23 pending · 4 deferred. Executive
summary: 11 P0, 52 open (was 10 P0 / 56 open — GT-625 is the new P0).
Verified: governance 17/17 exit 0; the four validators CI runs and the local
runner skips; 42/43/44/34 exit 0; bilingual parity over 1636 files; tracking
validation 625 gaps, 601/601 EN/ES catalog sections, 555 closure records.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Contributor
📊 Bilingual Coverage ImpactPR Changes
Repository Coverage
To create skeletons: node .harness/scripts/generate-es-skeleton.mjs <file.md>Generated by GitHub Actions |
Contributor
Knowledge Intake Validation Report
Automated by Knowledge Intake CI — 2026-07-28 |
|
|
||
| /** Normalize a line for duplication comparison: no indentation, no comments, no blanks. */ | ||
| function normalizeForDuplication(line: string): string { | ||
| const stripped = line.replace(/\/\/.*$/, '').trim(); |
…re it `Validate documentation` failed on `main`'s required checks with "Executive governance summary is stale" while the same validator passed locally. It was not a flake and not an environment difference: I generated the summary at the wrong point in the sequence. The generator reads its closure-record count from `maturity-reconciliation.json` rather than from the evidence file, and a later script in the governance suite refreshes that reconciliation. So generating BEFORE the suite captures a value the suite then moves — 550 committed against 555 derived — and `05` passes at that moment because the content matches what it just wrote. Regenerated after a full suite run and confirmed as a fixed point: governance 17/17, generator reports "Already current", `05` exits 0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…lean-room install (GT-625)
`@beyondnet/evolith-cli@1.2.0` could not print its own `--version` on any machine
but ours. The cause was one rung below where the existing guards look.
It was NOT the exports map: core-domain's `exports` carries a `./*` catch-all, so
`./application/paths/rulesets-location` is exposed. It was the TARBALL. Verified
by unpacking what the registry actually serves — `core-domain@1.1.0`, published
2026-07-18, ships no `dist/application/paths/` at all. The module was added after
that release, and the 2026-07-27 wave published four packages of which
core-domain was not one. So the CLI's `^1.1.0` range resolved to a version that
predates a module its own `dist` requires.
In the workspace the same specifier resolves, because `node_modules/@beyondnet/*`
are symlinks to locally built siblings. The publish was validated against a tree
no consumer will ever have.
The fix is the publish, not a code change: core-domain 1.2.0 (it now contains the
module), infra-providers 1.2.0 (its dist deep-imports the same module), and cli
and mcp to 1.2.1. Ranges are tightened `^1.1.0` -> `^1.2.0` wherever the deep
import exists — a caret would resolve correctly for a fresh install today, but it
also permits 1.1.0, and permitting the broken version is what got us here.
Rehearsed before publishing anything: all four packed, installed together into a
directory that has never seen this workspace, and the CLI boots and prints 1.2.1.
The 1.2.0 core-domain tarball contains `dist/application/paths/rulesets-location.js`.
The guard now gates the release. `check-install-smoke.mjs` gained `--pkg` so it
covers every workspace rather than the CLI alone — the defect is not CLI-specific,
the CLI is just the package with a binary a human runs. It executes INSIDE the
publish loop, immediately before each `npm publish`, because the loop is in
dependency order: by a package's turn, everything it depends on is on the
registry, so the question is answerable and the answer is the one a user gets.
Running it in PR CI would ask about dependencies that do not exist yet and fail
every legitimate version bump; an unsatisfiable gate gets deleted.
Two things the generalization forced, both stated rather than papered over:
· A leaf package imports no sibling, and the original anti-vacuous rule would
have failed four correctly-shaped packages for it. The denominator is now the
MANIFEST, not the scan: zero specifiers with zero declared sibling deps is
not-applicable and says so; zero specifiers against a manifest that declares
some is still a hard failure, because then the scan broke.
· A dry run publishes nothing, so it cannot answer the question for any
consumer. It emits a `::warning::` saying the smoke was skipped and that a
green dry run does NOT mean the artifact installs.
Release plan resolves to 4 of 8 packages, in dependency order: core-domain@1.2.0,
infra-providers@1.2.0, mcp@1.2.1, cli@1.2.1. Planner self-test 11/11.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… where it was measured Two failures on the runner, both mine, neither a flake. **Version-derived artifacts.** Bumping the CLI to 1.2.1 makes three generated things stale, and only one of them is checked by the local governance suite: `evolith-machine-contracts.json` pins the producer version, the product inventory embeds it, and `maturity-reconciliation.json` records `cliPackage`. Regenerated all three with their own generators and re-established the fixed point in the order that holds: reconcile -> suite -> summary -> validate. `Validate documentation` runs `09-reconcile-maturity` as its own step, outside the governance suite, so a green `ci-runner governance` never implied it. That is the second time this week a locally-green suite has not covered a required check. **The ratchet.** I lowered `--max-dead` from 305 to 303 on the strength of the guard's computed "ratchet basis" — 288 counted locally plus 15 that resolve only through generated state. The runner counted 305 and the job went red. The basis is a useful diagnostic and is not yet an accurate predictor, so it must not set the budget. Restored to 305, with the rule written down: only a number this job has printed may lower it. That was already the rule; I broke it by preferring a derived figure to a measured one. Verified after the fix: governance 17/17, 09, 05, 10, 11, 19, 20, 24 all exit 0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
Pull Request Summary
Nine agents with disjoint file ownership, then serial verification against a worktree pinned at HEAD so regression and pre-existing were separated by measurement rather than by how the failure looked. 5 gaps close, 14 advance, 1 new P0 is registered.
The most important thing here is a finding, not a fix
GT-625 — the published CLI is not installable, and the workspace is what hid it. GT-571's first acceptance criterion had sat open for weeks as "blocked on GT-570". With 1.2.0 published it was finally testable, so it was tested — and it refuted the row harder than the row claimed.
npm i @beyondnet/evolith-cli@1.2.0into a clean directory installs, and then--versiondies withMODULE_NOT_FOUND: the shippeddistdeep-imports a subpath the published@beyondnet/evolith-core-domaindoes not expose. Inside this repository the same import resolves, because the workspace symlink points at source rather than at what was packed.So the CLI's 1382 unit tests, its e2e suite and the exploratory tester are all structurally blind to it. This is the maturity audit's "a green local run is not evidence" with a new hiding mechanism — not a stale
dist, not a gitignored directory, but npm workspaces.Closed (5)
HeuristicStructuralReviewerimplements the port in-process and deterministically.grep "implements IStructuralReviewer"went 0 → 1, and not a stub.structuredContentthat validates under the SDK's own validator — including onFORBIDDENdenials, the result an agent most needs to read mechanically.Three findings that corrected their own rows
GT-608 corrected its brief before fixing anything: "all 16 capabilities declare
requiresApproval: false" was false before the wave — 7 playbooks already declaredtrue. The real defect was that the registry seeded 7 hardcoded skills and never read the manifest, so approval-requiring capabilities were unroutable and the approval branch unreachable. It has now executed end to end for the first time, including pending → denied → not executed.GT-591 corrected its evidence: the v0 set was 77 files, not 32. All 85 are now v1, with 275 test cases passing identically under the pinned 0.65.0 and a real 1.10.0 — while HEAD produces 813 parse errors under that same binary. The pin is deliberately not bumped: six v0 policies elsewhere are the ones the parity gate actually executes.
GT-584 found the unmeasured error rate was concrete: the layer comparison was inverted, so every legal
application → domainimport produced a blocking MUST while every realdomain → infrastructureinversion passed.Two regressions the wave caused, both repaired here
npm run test:contractwent red because GT-595 added five fields toValidationResultwithout the wire contract that pins it. That suite is a required check, so this could not have merged.34-check-skill-registry-paritywent red on five capabilities it called unroutable — and the guard was right about the old world and wrong about the new one. GT-608's derivation synthesizes a routable skill for every unbound capability, so reachability holds by construction; the five hand-written descriptors the guard demanded would have changed nothing observable and would in fact have broken the runtime, since binding a capability suppresses its synthesized twin and renames the id every caller targets. I wrote those five first, watched four agent-runtime tests go red, and reverted them. R3 now audits the derivation rather than trusting it: the synthesizer must be exported, actually called, and filtering on nothing but the complement of the bound set — with three negative fixtures, including a synthesis narrowed by a single extra conjunct.Guards wired, because outside CI is the same as not existing
43 (every scanning guard observed failing against an empty tree, 33/33), 44 (ADR implementation-status, 280 scanned) and 34 are now in the governance job. The dead-reference ratchet drops 305 → 303 and is no longer machine-dependent — the guard prints its own basis, so a laptop and the runner agree despite raw counts differing by 15. Guard 44 came out of the session scratchpad, where its author had left it as a handover because that directory belonged to another agent; it would have been lost.
What the board's own machinery caught in my write-up
I first wrote the Spanish board's wave notes in English — GT-620 inverted, and the parity gate compares heading counts, so nothing would have failed.
08-validate-trackingrejected five closure records whose evidence paths I had guessed rather than read; all five were wrong.05-validate-executive-summaryrefused a board of 625 against a reconciliation of 624.Board: 573/625 done · 25 in progress · 23 pending · 4 deferred. Executive summary: 11 P0, 52 open.
Evolith Core Quality Gates
01-validate-docs.mjsgreen.04-check-bilingual-parity.mjsgreen.Verification
Root build clean · core-domain 1336 + 13 e2e · core 62 · contracts 68 · mcp-server 432 · core-api 168 + 5 e2e · sdk-client 63 · infra-providers 125 · agent-runtime 384 · agent-runtime-api 81 · CLI unit 1382 ·
test:contract43 ·test:exploration6/6 findings=0 ·ci-runner governance17/17 exit 0 · the four validators CI runs and the local runner skips · OPA 224/224 · guard self-tests 42/43/44/34 all green (34 at 15/15).Two pre-existing failures recur and are not from this wave, confirmed against a pinned HEAD worktree: the CLI e2e
--archcase (the test invokes a flag the command never exposed) and a staleCOVERAGE_REPORT.md.Linked ADRs / Issues
Conventional Commits
🤖 Generated with Claude Code