Skip to content

feat(gaps): second parallel wave over 19 gaps — 5 closed, 14 advanced, 1 new P0 found - #233

Merged
beyondnetPeru merged 5 commits into
developfrom
feat/gap-fix-wave-2026-07-28
Jul 28, 2026
Merged

beyondnetPeru merged 5 commits into
developfrom
feat/gap-fix-wave-2026-07-28

Conversation

@beyondnetPeru

Copy link
Copy Markdown
Contributor

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.0 into a clean directory installs, and then --version dies with MODULE_NOT_FOUND: the shipped dist deep-imports a subpath the published @beyondnet/evolith-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.

Closed (5)

Gap
GT-613 P2 HeuristicStructuralReviewer implements the port in-process and deterministically. grep "implements IStructuralReviewer" went 0 → 1, and not a stub.
GT-593 P2 An append-only step journal content-addressed on input. Proven by killing the Core mid-pipeline. Approvals and policy verdicts are deliberately not journaled — replaying a grant could resume on a revoked decision — and the whole NOT-resumable set is written into the port rather than implied.
GT-598 P1 All 381 corpus rules mapped to an ISO/IEC 5055 weakness or marked no-equivalent with a reason; the 138-weakness index extracted programmatically from OMG ATDM V2 tables, not from memory. The gap's own premise is refuted: adoption closes 9 of 60 rules outright, not a large slice of a 240-handler backlog.
GT-581 P1 All 50 MCP tools declare an output contract and return structuredContent that validates under the SDK's own validator — including on FORBIDDEN denials, the result an agent most needs to read mechanically.
GT-424 P2 R3 now measures the effective routing surface and audits GT-608's derivation instead of trusting it.

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 declared true. 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 → domain import produced a blocking MUST while every real domain → infrastructure inversion passed.

Two regressions the wave caused, both repaired here

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 this could not have merged.

34-check-skill-registry-parity went 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-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 reconciliation of 624.

Board: 573/625 done · 25 in progress · 23 pending · 4 deferred. Executive summary: 11 P0, 52 open.

Evolith Core Quality Gates

  • Bilingual Parity: 1636 markdown files scanned; 522 English docs checked for an ES counterpart.
  • Validation Scripts: 01-validate-docs.mjs green.
  • Bilingual Validation: 04-check-bilingual-parity.mjs green.
  • Agnosticism: no vendor coupling introduced.

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:contract 43 · test:exploration 6/6 findings=0 · ci-runner governance 17/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 --arch case (the test invokes a flag the command never exposed) and a stale COVERAGE_REPORT.md.

Linked ADRs / Issues

  • Link to Issue: GT-613, GT-593, GT-598, GT-581, GT-424 (close) · GT-586, GT-614, GT-595, GT-584, GT-602, GT-572, GT-608, GT-591, GT-578, GT-573, GT-605, GT-599, GT-571, GT-607 (advance) · GT-625 (new, P0)

Conventional Commits

  • Title and commits follow Conventional Commits, enforced since GT-623.

🤖 Generated with Claude Code

beyondnetPeru and others added 2 commits July 28, 2026 05:47
…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>
@beyondnetPeru
beyondnetPeru requested a review from a team as a code owner July 28, 2026 10:58
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@github-actions

github-actions Bot commented Jul 28, 2026 •

Copy link
Copy Markdown
Contributor

📊 Bilingual Coverage Impact

PR Changes

  • Paired EN/ES files modified: 15
  • New EN files needing ES translation: 1

Repository Coverage

Metric Value
Total EN files 522
Total ES files 496
Paired files 0
Coverage 0%

⚠️ Action required: 1 new EN file(s) added without ES counterparts.

To create skeletons:

node .harness/scripts/generate-es-skeleton.mjs <file.md>

Generated by GitHub Actions

@github-actions

Copy link
Copy Markdown
Contributor

Knowledge Intake Validation Report

Gate Status
Schema + Transition Validation ❌ FAILED
OPA Policy Evaluation ✅ PASSED

⚠️ One or more validation gates failed. Please review the CI logs and fix the issues before merging.


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();
beyondnetPeru and others added 3 commits July 28, 2026 06:04
…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>
@beyondnetPeru
beyondnetPeru merged commit 4f6e394 into develop Jul 28, 2026
31 of 36 checks passed
@beyondnetPeru
beyondnetPeru deleted the feat/gap-fix-wave-2026-07-28 branch July 30, 2026 19:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants