release: promote develop to main (a20bb900) — the loader stops dropping documents in silence - #636
Merged
Merged
Conversation
* fix(ci): the inventory tally ran on the one condition that could never change it `07-generate-inventories.mjs` counts ADRs, rulesets and schemas. In the local hook it hung off `infraChanged` — docker-compose, helm, `.github/workflows` — so a ruleset or an ADR could be added without ever triggering it. And it ran in no workflow at all: its only other appearance in the repository is its own unit test in ci-cd.yml. The published summary had been stale since 2026-08-16 (141/181 against a measured 142/182) and the front page quoted it onward. - regenerate both halves of the summary, so the numbers match the corpus - run the generator with `--check` in the required `Validate documentation` job, plus its self-test, which also ran nowhere - move the local trigger to `governanceChanged || adrChanged`, the two things that can actually move the count Verified: `--check` exits 0 against the tree; self-test 7/7. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: aarroyo <beyondnet.peru@gmail.com> * docs(mcp): the tool catalog and the product vision both undercounted the surface Closes #566, closes #567. The server registers 52 `evolith-*` tools. The hand-maintained catalog listed 51 -- `evolith-ruleset-list` was never added when the tool landed -- and the product vision master still said 47 tools and 11 resources, a figure corrected in the README months ago and missed here. - add the missing `evolith-ruleset-list` row, in the shape of its neighbours - correct the catalog's two declared totals (51 and "current 47-tool surface") and the Spanish twin's, which asserted 51 as well - product vision EN/ES: 47 tools / 11 resources -> 52 / 12, matching the generated `product-inventory.md` Verified: the server's registered names and the catalog rows are now the same 52-element set (`comm` on both sorted lists returns nothing either way); bilingual suite green, 17/17 entry-surface documents. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: aarroyo <beyondnet.peru@gmail.com> * docs(evidence): publish the front page's first-run capture, in full and in both languages The README quotes counters from one run of the published CLI against a fresh satellite. Until now the run itself lived nowhere, so the numbers had to be taken on faith and the elided rows could not be inspected. Captured today against `@beyondnet/evolith-cli@1.3.2` resolved from the public registry: 133 checked / 26 skipped / 0 errored of 159 selected, 72 issue rows, 37 blocking, nine of those blocking rows being rules the engine could not decide, exit 2. `stderr` was empty. Three things the capture makes checkable rather than asserted: - the two denominators reconcile in the output itself -- the `GOV-RULE-NOT-APPLICABLE` row states 253 inapplicable rules, and 253 + 159 = 412 - the same repository on the default native engine checks 41 rules and skips 118. CI holds the two engines to agreement over fixtures, not to equal coverage over a real repository, and today they do not have it - the three `[Nest] WARN Skipping non-standard ruleset` lines the README still quotes are gone in 1.3.2 -- on both streams. `INFRA-001` and `INFRA-OPA-001` are still in no denominator, so #575 is now silent rather than fixed Both halves written together, as the entry-surface rule requires. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: aarroyo <beyondnet.peru@gmail.com> * docs(readme): say what the tool is before showing what it found The front page opened with a 490-word forensic account of a run that ends in `exit 2` with 37 blocking findings, and in 498 lines it never said what category of tool this is. A reader with a minute left believing it was broken, having never learned what it does. Worse, the hero taught `validate --engine opa` and Quick Start taught bare `validate` — two commands that produce different denominators (133 rules evaluated against 41) with nothing explaining the flag. That is the exact defect this project exists to catch, on its own front page. Restructured, 498 -> 201 lines and 19 -> 10 sections, in both languages: - category sentence first, then the command, then the real output - the capture stays but is trimmed to the counters, one `did not run` row, the `GOV-RULE-NOT-APPLICABLE` row that reconciles both denominators, and `echo $?`; it now carries its date and resolved version, and links the full capture - `--engine opa` used consistently, and the divergence between the two engines disclosed rather than hidden behind the inconsistency - Quick Start moves to the top fifth and gains Node requirements, a sample `evolith.yaml`, what the tool actually inspects, and the `--select` mitigation for the first-run findings - Network Egress goes from 50 lines to 6, pointing at SECURITY.{md,es.md}, which already carried the full disclosure bilingually and with two limitations the README never had - the hand-written 15-entry Menu, the inline Q&A and the ASCII diagram go; the documentation table is rebuilt around intent, 21 rows to 9 - Contributing now names the open good-first-issues and Discussions instead of linking four process documents at the 96% mark Every figure was measured today rather than carried over. The old "412 rules / 181 files" is replaced by counts CI verifies (142 ADRs, 182 ruleset files, 50 schemas) alongside what the published CLI reports loading (177 packs, 412 rules). A tree-side rule count is deliberately absent: the published CLI evaluates its bundled corpus regardless of `coreRef.path`, so that number could not be measured with the real counting rule, and an unverifiable figure has no business on this page. Verified: 201 lines and ten `##` on both sides, every relative link resolves, both anchors exist, guards 01 and 04 green (17/17 entry-surface documents). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: aarroyo <beyondnet.peru@gmail.com> * docs(nav): one canonical master index, and the other one stops competing Closes #564. Two files called MASTER_INDEX.md, and a reader who found either had no way to know the other existed. The root pair was six links deep and sat on the entry surface; the taxonomy pair was already a redirect, but its two halves pointed at DIFFERENT documents -- English at the control-center hub, Spanish at the Core hub -- so the bilingual pair disagreed about where it was sending you. - the root pair becomes canonical, and is filled out to earn the link the README now gives it: architecture, governance, product, project state and knowledge, twenty entries a side - the taxonomy pair becomes a pure redirect to the root, with both halves naming the same destination, and says in words why it holds no content of its own The redirect stays rather than being deleted: 60-odd ADRs and both reference hubs link to it. Verified: guards 01 and 04 green, five `##` a side at the root and two a side in the redirect, every relative link resolves from its own directory. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: aarroyo <beyondnet.peru@gmail.com> * docs(core): rehome the three blocks the front page shed, and fix what they carried The README rewrite dropped three blocks. Two had a home to go to and one had a defect that only showed once it was moved. - **Core concepts** land in the Core hub as section 8, both languages, with the ten terms the rest of the corpus assumes and links to where each is defined. `Related Navigation` renumbers 8 -> 9; nothing links to those anchors. - **The directory tree** lands in the repository taxonomy, replacing one that had gone stale at the `src/` refactor: it still showed `sdk/`, `rulesets/`, `apps/` and `packages/` at the repository root, four paths that have not existed for months, and omitted `docs/`, `product/` and `.claude-plugin/` entirely. Both halves rewritten from the tracked tree. - **The Q&A** gains the two entries the Spanish half never had. This was not two missing translations: Spanish was missing EN's `T04-P04` (topology composition) and `T07-P03` (Strangler Fig), and had silently renumbered everything after them, so `T04-P04` named different questions in the two languages. The ids now agree as a set, 43 a side. - One Spanish line read `no六个月 después` -- a CJK fragment where "seis meses" belonged, sitting in the file since it was written. The README's Spanish half is corrected from 41 questions to 43 to match. Verified: `T##-P##` id sets identical across both halves (`diff` empty), guards 01 and 04 green, every relative link in the touched files resolves. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: aarroyo <beyondnet.peru@gmail.com> * docs(nav): two bilingual pairs sent their readers to different documents Measured across the seventeen entry-surface pairs: seventeen link entries differ between halves, and thirteen of them are correct -- a Spanish half pointing at the Spanish anchor of a bilingual document is what it should do. Two were defects. - `gap-tracking` and `gap-reference-catalog` both ended with a "Back to Vision Index" footer whose halves resolved to DIFFERENT files: `../README.md` (Control Center) in English, `../../README.es.md` (the Core hub) in Spanish. Both resolve, so guard 01 was green over the contradiction. Unified on the Control Center, which is the hub these two documents actually live under, and the label now names it -- neither file is a vision index. - `reference/core/interfaces/README.md` had no bilingual navigation line at all while its Spanish half linked back to it, so the Spanish version was reachable in one direction only. Two further divergences are real but out of scope here, and are being left visible rather than papered over: `AGENTS.es.md` has no script-taxonomy section to hang the EN pointer on, and `gap-tracking.es.md` has no 2026-06-27 wave paragraph. Both are abridged translations -- content gaps, not path bugs. A link-parity guard is deliberately NOT added in this change. Of the seventeen divergences it would see today, thirteen are correct translations; a guard that needs a hand-maintained exemption list for its own true negatives is the pattern this repository emptied out of guard 66. It needs a rule that can tell a translated anchor from a wrong destination, and that is its own piece of work. Verified: guards 01, 04 and 08 green (706 gaps, 682/682 catalog sections). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: aarroyo <beyondnet.peru@gmail.com> * docs: cite #628 where the engine coverage gap is disclosed Opening the issue corrected the framing the disclosure carried. Guard 68 (`68-validate-engine-verdict-parity.mjs`) states in its own header that the two engines ARE allowed to disagree about coverage and are held only to agreement about facts -- so the 133-versus-41 gap is an accepted design position, not an undiscovered defect, and calling it one would have contradicted the repository's own stance. What is not accepted, and is what #628 asks for: `evolith validate` with no flag is the lower-coverage command, and nothing in its output says which engine ran or what that engine could decide. The reader sees 118 skips and has no way to tell they belong to the engine rather than to their repository. Both READMEs and both halves of the first-run capture now say that distinction in those terms and link the issue. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: aarroyo <beyondnet.peru@gmail.com> --------- Signed-off-by: aarroyo <beyondnet.peru@gmail.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…pendabot PRs touch (#631) Dependabot has five pull requests open (#435-#439) and they cover nestjs, opentelemetry, types/node and eslint-plugin-boundaries. The seven open alerts are about three other packages entirely, so merging all five would have closed none of them. - `@hono/node-server` 1.19.14 -> 1.19.15 (alerts 80, 81) - `esbuild` ^0.24.2 -> ^0.25.0 (alert 82) - `hono` 4.12.27 -> 4.12.34 via a root override (alerts 75, 77, 78, 79): ReDoS in CORS middleware, `memo()` retaining SSR output across requests, Proxy Helper leaking `Connection`-listed headers, and complexity DoS in the language middleware `hono` needs the override rather than a bump: it is transitive, reached through `@modelcontextprotocol/sdk` (`^4.11.4`) and as a peer of `@hono/node-server` (`^4`), so neither consumer's range forces the patched version. Changing `overrides` alone did not move it -- npm leaves an already-locked package where it is -- so the lock entry was re-resolved deliberately and its `resolved` and `integrity` restored from the registry, since dropping those would break `npm ci`. Verified, not assumed: - `npm ci` from a clean directory with only the manifests present: 1303 packages, hono 4.12.34 installed, **0 vulnerabilities** - esbuild 0.25 still vendors the ESM dependencies the packaged binary needs (GT-707): `dist/vendor/clack.cjs` 107 kB / 59 exports, `dist/vendor/conf.cjs` 410 kB / 1 export, and the built CLI answers `--version` and `rulesets` - tests on the three workspaces that touch hono: agent-runtime-api 86 passed, agent-runtime 483 passed, CLI 133 passed Signed-off-by: aarroyo <beyondnet.peru@gmail.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…carry (#633) Five consecutive tags failed, each one filing a "Release Pipeline Failed" issue, and all five had the same cause: v1.3.3 -> cli 1.3.1 (#599) v1.3.4 -> cli 1.3.1 (#603) v1.3.5 -> cli 1.3.1 (#606) v1.3.6 -> cli 1.3.2 v1.3.7 -> cli 1.3.2 (#627) The pipeline reads the version from two places and never compared them. `publish-npm` reads `package.json` -- correctly -- and since #569 it asks the registry first, so an already-published version is skipped as a non-failure. `smoke-test-functional` then installs `@beyondnet/evolith-cli@${tag#v}`. When the two disagree, publish "succeeds" by skipping and the smoke test dies on `npm error code ETARGET / No matching version found`. Nothing was ever wrong with the build: the tag named a version that was never built. No re-run could fix it, and the run spent a full build, three binary packagings and three platform smoke tests before finding out. The question now lives in `release-gate`, before anything is built or published: if the tag and `src/sdk/cli/package.json` disagree, the run stops with both numbers named and a step summary saying which of the two to change. `release-gate` gains the checkout it needs to read the file. Verified: the assertion logic run against this tree rejects `v1.3.7` (package carries 1.3.2) and accepts `v1.3.2`. Workflow parses as YAML. Signed-off-by: aarroyo <beyondnet.peru@gmail.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…#635) * fix(core): a corpus file that becomes no rules now reaches the report Closes #575. The loader globs `*.rules.json` and four shipped files are not rule SETS. They were read, produced nothing, and the only trace was a log line. A log line does not survive `--format json`, never reaches an exit code, and left the documents out of every denominator the report published -- the silent drop this project exists to stop, inside its own loader. #575 asked for the accounting FIRST and the files second, and it was right: the files turned out not to need changing. GT-649 had already classified three of them by declared `$schema`, and the two INFRA rules are genuinely enforced elsewhere -- `src/rulesets/opa/infrastructure/*.rego` plus the dedicated `29-validate-opa-sidecar-bundles.mjs` guard. Wrapping them into the corpus would have double-counted them. What was missing was the accounting, and only that. - `IRulesetRepository` gains `CorpusDocumentOutcome` and an optional `describeLastLoad()`. Optional so an implementation that cannot know stays valid; an implementation that drops documents and stays quiet reintroduces this bug. - The validator emits two rows, deliberately weighted differently. `GOV-CORPUS-NOT-A-RULESET` (COULD, non-blocking) names each document that declares a known non-ruleset schema and satisfies it -- a fact about the corpus, not a violation. `GOV-CORPUS-REJECTED` (MUST, blocking) names each document that claims to be a ruleset and is not, because such a file is indistinguishable downstream from one that was never there. - The fourth file, `sdlc/phase-gates.rules.json`, was recognised by FILENAME -- `filePath.endsWith("phase-gates.rules.json")` skipped schema validation and then normalised to zero rules, so it was neither validated nor reported. It declares `ruleset-sdlc.schema.json` like its neighbours declare theirs, so it now dispatches on that. The path literal is gone, and a rename can no longer defeat it. `PhaseGateValidatorService` reads the file at its own path and is unaffected. Verified against the built CLI on a fresh satellite, not asserted: - the row appears in the report AND in `--format json`, naming all four files with the reason for each - the blocking branch is falsifiable: dropping one deliberately broken `*.rules.json` into the corpus produced `GOV-CORPUS-REJECTED ... | YES` and exit 2; removing it returned the run to the previous state - no rules were lost by the phase-gates change: `evolith rulesets` reports 178 packs / 413 rules before and after Tests: infra-providers 181, core-domain 1997 (5 new in `corpus-load-accounting.spec.ts`), CLI 133, core-api 163 -- all passing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: aarroyo <beyondnet.peru@gmail.com> * docs(readme): publish the tree's rule count, now that it can be measured The front page said the tree "carries 182 ruleset files" and stopped there, because a tree-side RULE count could not be obtained: the published CLI evaluates its bundled corpus regardless of `coreRef.path`, so pointing it at this tree returns the tarball's numbers, not the tree's. Building the CLI from this tree answers it — 178 packs, 413 rules — and #575's accounting explains the gap between 182 files and 178 packs without hand-waving: four files declare a non-ruleset schema and contribute no rules by design, and they are now named in every report rather than dropped. Both halves say the same three numbers, and the previous sentence blaming "the loader rejection above" goes with them — nothing is being rejected. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: aarroyo <beyondnet.peru@gmail.com> --------- Signed-off-by: aarroyo <beyondnet.peru@gmail.com> 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. |
…ranch The last three promotions merged with `--rebase`, so main carries copies of develop's commits under different shas. Git therefore sees the two branches as divergent (4 commits each way) even though their content matched exactly, and this promotion conflicted on the only file both sides had touched since: the README pair. Resolved to develop's side for both halves. That is not a preference -- develop's README is main's plus this branch's own edits. Verified rather than asserted: after the merge, `git diff origin/develop` is empty. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: aarroyo <beyondnet.peru@gmail.com>
📊 Bilingual Coverage ImpactPR Changes
Repository Coverage
✅ Good: All EN changes have ES counterparts. Generated by GitHub Actions |
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.
Promotion of
developtomain, pinned at the head of #635.Closes #575 — a corpus file that becomes no rules now reaches the report.
The loader globs
*.rules.jsonand four shipped files are not rule sets. They were read, produced nothing, and the only trace was a log line, which does not survive--format jsonand never reaches an exit code. Two rows now carry them:GOV-CORPUS-NOT-A-RULESET(COULD, non-blocking) for a document that declares a known non-ruleset schema and satisfies it, andGOV-CORPUS-REJECTED(MUST, blocking) for one that claims to be a ruleset and is not.The issue counted three such files; there are four.
sdlc/phase-gates.rules.jsonwas recognised by filename, skipped validation, normalised to zero rules and was never reported. It now dispatches on its declared schema like its neighbours, and the path literal is gone.The files themselves needed no change: GT-649 had already classified three, and the two
INFRArules are enforced by their paired Rego policies and29-validate-opa-sidecar-bundles.mjs. Wrapping them into the corpus would have double-counted them.Also carries the README figures this made measurable: 178 packs / 413 rules across 182 files, in both languages.
Verified on #635: rollup SUCCESS; the blocking branch falsified with a deliberately broken ruleset (exit 2, then restored);
evolith rulesetsreports 178/413 before and after; infra-providers 181, core-domain 1997, CLI 133, core-api 163 tests pass.🤖 Generated with Claude Code