Repository navigation
fix: align main — 19-gap wave plus the GT-625 release fix - #234
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>
…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>
feat(gaps): second parallel wave over 19 gaps — 5 closed, 14 advanced, 1 new P0 found
|
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 |
…al reviewer
CodeQL flagged `/\/\/.*$/` in `normalizeForDuplication` as a polynomial regular
expression on uncontrolled data, and it is right. The input is a line of a file
this reviewer was pointed at, so it is attacker-influenced exactly when the
reviewer is doing its job — reviewing code somebody else wrote. A line made of
many `//` makes the engine rescan to end-of-line from every position.
Replaced with `indexOf('//')` and a slice: identical semantics, linear, no
backtracking.
This is the alert that blocked #234. `CodeQL SAST`, the required check, was
green; the finding arrived as an unresolved review thread, and `main` requires
conversation resolution. Resolving the thread would have merged it. Fixing the
regex is the same amount of work and leaves nothing behind.
agent-runtime 384/384, tsc clean.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
4 tasks done
fix(agent-runtime): remove a polynomial-ReDoS regex from the structural reviewer
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.
Aligns
mainwithdevelop: the second gap wave (GT-613, GT-593, GT-598, GT-581, GT-424 closed) and the GT-625 fix — core-domain 1.2.0 ships the module the published CLI required, ranges tightened to^1.2.0, and every release is gated on a clean-room install run inside the publish loop.Publishing follows this merge: core-domain@1.2.0, infra-providers@1.2.0, mcp@1.2.1, cli@1.2.1.
🤖 Generated with Claude Code