Skip to content

fix(standards): one renderer, two callers — reconcile the two GT-633 implementations - #294

Merged
beyondnetPeru merged 1 commit into
developfrom
integration/gt-633-one-renderer
Jul 30, 2026
Merged

fix(standards): one renderer, two callers — reconcile the two GT-633 implementations#294
beyondnetPeru merged 1 commit into
developfrom
integration/gt-633-one-renderer

Conversation

@beyondnetPeru

Copy link
Copy Markdown
Contributor

Pull Request Summary

GT-633 was fixed twice, in parallel, by sessions that could not see each other. One shipped a standalone capture script reachable by the derived-artifact chain guard and the documentation job (#276, #287, on main); the other rendered the document inside rule-corpus-triage.spec.ts, where jest can pin it byte-for-byte (#279, on develop). Both were right about their half, and both recaptured the same numbers — mutual corroboration of the measurement.

But two generators for one artifact is GT-633's own defect one level up: whichever ran last would win, and the other's --check would go red for no reason a reader could see. That is what has been blocking developmain (#284).

One renderer, two callers

The renderer now lives once, in test/rule-corpus-triage.ts:

  • rule-corpus-triage.spec.ts pins it byte-for-byte — it can recompute, so it is the real guard;
  • capture-native-evaluability-snapshot.mjs writes it and --checks it — what the GT-630 chain and docs.yml invoke.

The spec no longer writes. UPDATE_EVALUABILITY_SNAPSHOT=1 is gone: a second writer is how this artifact ended up with two generators, and the surviving one is the command the chain guard already runs.

Resolving it surfaced the same defect in miniature, twice

  1. The spec asserted SUMMARY.byClass against an inline literal sitting beside the PINNED_CLASS_COUNTS constant that the dependency-free guard in src/rulesets/standards reads out of that file. Two copies of six numbers; editing either left the other silently disagreeing. Now one declaration, asserted against and read by both.
  2. My own first pass deleted PINNED_CLASS_COUNTS while lifting the loader out — and the documentation-job guard threw rather than passing: "Could not find the PINNED_CLASS_COUNTS literal … update this parser rather than deleting the check." Exactly the behaviour that fix was built for, catching the person who wrote it. Restored.

The sticky date survives the port

capturedOn is provenance, not content. The script renders once with the previous date and replaces that single field only when the classification moved, so the chain's fixed-point replay stays byte-identical without paying for a second ts-node run.

Converged onto main's shape, so the branch merge stops conflicting

iso-5055-mapping.test.mjs, both standards READMEs, the 5-link chain guard with its fixtures, and the two GT-598 steps in docs.yml.

A number worth stating rather than hiding

This branch computes native-handler 151; main pins 154. Not a measurement bug — main has more handler closures landed. The pin and the byte-for-byte snapshot assertion are what will catch it when the branches meet, which is the point of having one renderer.

Verified

  • capture --check → faithful capture, 386 rules; build --check → up to date, 388 rules
  • replay is byte-identical (the sticky date works through the new driver)
  • iso-5055-mapping.test.mjs → 9/9 · chain guard → 5 links current and at a fixed point, own suite 8/8
  • core-domain jest → 1444 passed / 128 suites · tsc --noEmit clean
  • 01-validate-docs, 04-check-bilingual-parity, 08-validate-tracking, 09-reconcile --check green

What this does not do

It reconciles the GT-633 collision only. developmain also has unrelated collisions from parallel sessions — the closure-evidence registry (34 conflicts), board rows, ci-cd.yml, guard 41 and a CLI e2e test. Those belong to their authors, not to this change.

Evolith Core Quality Gates

  • Bilingual Parity: both standards READMEs updated together.
  • Validation Scripts: 01-validate-docs.mjs green.
  • Bilingual Validation: 04-check-bilingual-parity.mjs green.
  • Agnosticism: no new technology dependency.

Linked ADRs / Issues

Conventional Commits

  • Commit follows Conventional Commits.

🤖 Generated with Claude Code

…implementations

GT-633 was fixed twice, in parallel, by sessions that could not see each other.
One shipped a standalone capture script reachable by the derived-artifact chain
guard and the documentation job (#276, #287, on main); the other rendered the
document inside `rule-corpus-triage.spec.ts`, where jest can pin it byte-for-byte
(#279, on develop). Both were right about their half and both recaptured the same
numbers — which is mutual corroboration of the measurement.

But TWO GENERATORS FOR ONE ARTIFACT IS GT-633's OWN DEFECT ONE LEVEL UP: whichever
ran last would win and the other's `--check` would go red for no reason a reader
could see. That is what blocked develop -> main.

The renderer now lives ONCE, in `test/rule-corpus-triage.ts`, with two callers:

  - `rule-corpus-triage.spec.ts` PINS it byte-for-byte (it can recompute);
  - `capture-native-evaluability-snapshot.mjs` WRITES it and `--check`s it, which
    is what the GT-630 chain and docs.yml invoke.

The spec no longer writes. `UPDATE_EVALUABILITY_SNAPSHOT=1` is gone: a second
writer is how this artifact ended up with two generators, and the surviving one is
the command the chain guard already runs.

RESOLVING IT SURFACED THE SAME DEFECT IN MINIATURE, twice, and both are fixed:

  1. The spec asserted `SUMMARY.byClass` against an INLINE literal sitting beside
     the `PINNED_CLASS_COUNTS` constant that the dependency-free guard in
     src/rulesets/standards reads out of this file. Two copies of six numbers,
     and editing either left the other silently disagreeing. Now one declaration,
     asserted against and read by both.
  2. My own first pass DELETED `PINNED_CLASS_COUNTS` while lifting the loader out.
     The documentation-job guard THREW rather than passing — "Could not find the
     PINNED_CLASS_COUNTS literal ... update this parser rather than deleting the
     check" — which is exactly the behaviour that fix was built for. Restored.

The sticky `capturedOn` survives the port: the script renders once with the
previous date and replaces that single field only when the CLASSIFICATION moved,
so the chain's fixed-point replay stays byte-identical without a second ts-node run.

Also converged onto main's shape so the branch merge is trivial rather than
conflicted: `iso-5055-mapping.test.mjs`, both standards READMEs, the 5-link chain
guard with its fixtures, and the two GT-598 steps in docs.yml.

NOTE ON THE NUMBERS: this branch computes native-handler 151, and main pins 154.
Not a measurement bug — main has more handler closures landed. The pin and the
byte-for-byte snapshot assertion are what will catch it when the branches meet,
which is the point of having one renderer.

Verified: capture --check faithful (386 rules), build --check up to date (388
rules), replay byte-identical, iso-5055-mapping guard 9/9, chain guard 5 links
current and at a fixed point with its own suite 8/8, core-domain jest 1444 passed
/ 128 suites, tsc --noEmit clean, 01/04/08/09 green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@beyondnetPeru
beyondnetPeru requested a review from a team as a code owner July 30, 2026 14:28
@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

Copy link
Copy Markdown

📊 Bilingual Coverage Impact

PR Changes

  • Paired EN/ES files modified: 6
  • New EN files needing ES translation: 3

Repository Coverage

Metric Value
Total EN files 524
Total ES files 498
Paired files 0
Coverage 0%

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

To create skeletons:

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

Generated by GitHub Actions

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.

1 participant