Skip to content

feat: complete greenfield phase 0 substrate - #108

Merged
aryeko merged 19 commits into
mainfrom
feat/greenfield-phase-0-substrate
Jul 27, 2026
Merged

feat: complete greenfield phase 0 substrate#108
aryeko merged 19 commits into
mainfrom
feat/greenfield-phase-0-substrate

Conversation

@aryeko

@aryeko aryeko commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Summary

Reworks Phase 0 under the amended per-story-evidence policy.

  • keeps the codec, runtime-contracts, conformance, and authority-kernel packages intact
  • removes per-story evidence runners, finalizers, contracts, committed provenance pins, and CI fetches
  • renames tests and oracle fixtures by behavior/package; adds one runtime-derived generic evidence writer
  • moves pure-package import/export restrictions into a TypeScript-AST boundary checker, including unbound ambient-capability reads and fail-closed missing entries
  • restores the runtime-topology guard to the required check chain and statically prevents that chain from reaching evidence-writing or artifacts/ output

Verification

Clean detached worktree at 2325231:

  • pnpm install --frozen-lockfile --config.confirmModulesPurge=false — pass
  • pnpm check — pass; includes lint, formatting, docs links, delivery and structure checks, typecheck, boundaries, runtime:check, and workspace tests
  • focused delivery-track, active-repository, package-boundaries, and runtime-topology regressions — pass
  • git diff --check — pass
  • independent read-only re-review — pass

write-evidence.mjs intentionally runs pnpm test again after the gate: it records the observed test exit status in evidence and remains reporter-only, so a failed observed test does not make the evidence writer itself a gate.

Rule-16 certification

  • no gf-0NN identifier remains in tracked scripts/, tests/, packages/, or .github/ filenames
  • the content sweep excludes only the unchanged check-delivery-track.mjs and its test, which validate canonical delivery-story data
  • within that test, grep -nE '/[^/*]*GF-0[0-9]{2}[^/]*/' leaves only the four legitimate catalog-data matches (coverage-table rows and doc-content replacement inputs)
  • the SHA sweep permits only the four immutable GitHub Action pins and three immutable archive anchors

The exclusions are not blanket file exclusions: all other values still fail the sweep.

Out of scope

  • no package API or behavior changes
  • no provider, adapter, ledger/storage, controller process, CLI/MCP surface, credential, or external effect
  • no delivery-policy amendment or change to scripts/check-delivery-track.mjs
  • archive anchors remain as immutable-tag tamper checks

Scope notes

  • PR remains draft pending hosted checks and review.
  • No secrets or generated artifacts are included.

Summary by CodeRabbit

  • New Features
    • Introduced strict canonical frame/identity/digest encoding and validation.
    • Added runtime topology and controlled crossing authorization checks.
    • Implemented an authority kernel with deterministic state transitions and replay.
    • Added a conformance harness for evidence ingestion and gate evaluation.
    • Enabled workspace package discovery and project build wiring.
  • Documentation
    • Updated Phase 0 status, repository posture, and repository check requirements.
  • Tests
    • Added expanded codec, runtime topology, authority kernel, conformance, and workspace/boundary test coverage.
  • Chores
    • Updated CI evidence generation/artifact naming to Phase 0 and added the new evidence writer workflow support.

@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2ba509b1-a22e-4463-b45c-3af241baf7ea

📥 Commits

Reviewing files that changed from the base of the PR and between 2325231 and d371474.

📒 Files selected for processing (17)
  • README.md
  • packages/authority-kernel/src/index.ts
  • packages/codec/src/index.ts
  • packages/conformance/src/index.ts
  • packages/runtime-contracts/src/index.ts
  • scripts/check-active-repository.mjs
  • scripts/check-active-repository.test.mjs
  • scripts/check-package-boundaries.mjs
  • scripts/check-package-boundaries.test.mjs
  • scripts/write-evidence.mjs
  • tests/authority-kernel/authority-kernel.test.mjs
  • tests/codec/codec.test.mjs
  • tests/codec/corpus.test.mjs
  • tests/conformance/conformance.test.mjs
  • tests/fixtures/authority-oracle.json
  • tests/fixtures/codec-corpus.json
  • tests/runtime-contracts/topology.test.mjs
💤 Files with no reviewable changes (2)
  • tests/fixtures/codec-corpus.json
  • tests/codec/corpus.test.mjs
🚧 Files skipped from review as they are similar to previous changes (15)
  • scripts/write-evidence.mjs
  • tests/fixtures/authority-oracle.json
  • README.md
  • scripts/check-package-boundaries.test.mjs
  • tests/authority-kernel/authority-kernel.test.mjs
  • tests/runtime-contracts/topology.test.mjs
  • packages/codec/src/index.ts
  • tests/codec/codec.test.mjs
  • packages/authority-kernel/src/index.ts
  • scripts/check-active-repository.test.mjs
  • packages/runtime-contracts/src/index.ts
  • scripts/check-active-repository.mjs
  • scripts/check-package-boundaries.mjs
  • tests/conformance/conformance.test.mjs
  • packages/conformance/src/index.ts

📝 Walkthrough

Walkthrough

The repository now contains four private Phase 0 packages: canonical codec, runtime contracts, conformance evaluation, and authority kernel. Workspace wiring, strict repository validators, fixtures, tests, and Greenfield Phase 0 evidence generation were updated accordingly.

Changes

Phase 0 workspace substrate

Layer / File(s) Summary
Workspace foundation
AGENTS.md, README.md, package.json, pnpm-workspace.yaml, tsconfig.json, tests/fixtures/workspace/*, tests/workspace/*
Workspace metadata, documentation, package references, fixtures, and workspace tests now describe the Phase 0 package layout.
Canonical codec and identity handling
packages/codec/*, tests/codec/*, tests/fixtures/codec-*
Adds canonical JSON frames, strict parsing, governed identities, staged SHA-256 digests, and golden corpus validation.
Runtime topology contracts
packages/runtime-contracts/*, tests/runtime-contracts/*, scripts/check-runtime-topology.*, tests/fixtures/runtime-*
Adds topology units, semantic ports, allowed crossings, denial validation, framed opaque values, scripted fakes, and topology checks.
Authority state-transition kernel
packages/authority-kernel/*, tests/authority-kernel/*, tests/fixtures/authority-oracle.json
Adds immutable authority state validation, legal story/run transitions, reduction, and ordered replay.
Evidence conformance engine
packages/conformance/*, tests/conformance/*, tests/fixtures/conformance-oracle.json
Adds evidence ingestion, deterministic attempts, route oracles, and realization/provider/product gate evaluation.
Repository validation and evidence wiring
scripts/*, .github/workflows/check.yml
Updates workspace, package-boundary, topology, delivery-track, and active-repository validation; adds Phase 0 evidence writing and artifact upload.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CI
  participant RepositoryChecks
  participant Packages
  participant EvidenceWriter
  CI->>RepositoryChecks: run pnpm check
  RepositoryChecks->>Packages: typecheck and test workspace packages
  Packages-->>RepositoryChecks: validation results
  RepositoryChecks-->>CI: check status
  CI->>EvidenceWriter: write Phase 0 evidence
  EvidenceWriter-->>CI: artifacts/phase-0/evidence.json
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 1.82% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main change: completing the Greenfield Phase 0 substrate and related checks/packages.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/greenfield-phase-0-substrate

Comment @coderabbitai help to get the list of available commands.

@aryeko
aryeko force-pushed the feat/greenfield-phase-0-substrate branch 3 times, most recently from d68d77b to 12049e0 Compare July 26, 2026 21:41
@aryeko
aryeko force-pushed the feat/greenfield-phase-0-substrate branch from 12049e0 to bfe4a6d Compare July 26, 2026 23:28
@aryeko
aryeko marked this pull request as ready for review July 27, 2026 00:05

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 232523152b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/authority-kernel/src/index.ts
Comment thread packages/authority-kernel/src/index.ts
Comment thread scripts/write-evidence.mjs Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

🧹 Nitpick comments (21)
packages/codec/tsconfig.json (1)

6-6: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

"DOM" lib widens the ambient surface for a pure package.

The package only needs TextEncoder/TextDecoder, which @types/node provides. Including DOM makes fetch, document, localStorage, etc. type-visible, which conflicts with the pure-package/ambient-capability boundary checks this stack introduces. Consider dropping DOM and relying on Node types.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/codec/tsconfig.json` at line 6, Remove "DOM" from the lib array in
the codec TypeScript configuration, retaining only the ES2022 library and
relying on the existing `@types/node` declarations for TextEncoder and
TextDecoder.
tests/codec/codec.test.mjs (1)

95-101: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the arity the test name promises.

Nothing enforces "22" — if a constructor is dropped from tests/fixtures/codec-corpus.json, this loop still passes vacuously. Same applies to the identity loop at Lines 70-71.

💚 Proposed change
+  assert.equal(corpus.constructors.length, 22);
   for (const entry of corpus.constructors)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/codec/codec.test.mjs` around lines 95 - 101, Ensure the formatter test
explicitly asserts that corpus.constructors contains exactly 22 entries before
iterating, and add the equivalent count assertion for the identity loop’s
constructor collection. Keep the existing per-entry assertions unchanged so the
tests still validate every supplied canonical form.
packages/codec/src/index.ts (2)

97-106: 🗄️ Data Integrity & Integration | 🔵 Trivial | 💤 Low value

Key ordering is code-point based, not UTF-16 code-unit based.

RFC 8785 (JCS) sorts object keys by UTF-16 code units. This comparator sorts by code point, so keys containing non-BMP characters order differently from any JCS-compatible implementation. Self-consistent within this package, but cross-runtime golden vectors produced elsewhere would disagree. If the divergence is intentional, a short comment stating that jig.codec.v1 is not JCS would prevent future confusion.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/codec/src/index.ts` around lines 97 - 106, Update compareKeys to
compare string characters by UTF-16 code units rather than spreading into
Unicode code points, preserving lexicographic ordering and length fallback. If
the code-point ordering is intentional, instead document near compareKeys that
jig.codec.v1 is not JCS-compatible; otherwise implement the UTF-16 ordering
required for cross-runtime compatibility.

502-506: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Re-derive the same-run check from the shared grammar constants.

The inline literal duplicates the run constant defined at Line 56; a future change to the run grammar silently desynchronizes this check from patterns.

♻️ Suggested refactor
-      const runs = /^(run-[0-9]{12}-[0-9a-f]{16})\/txn\/[0-9]+\/(run-[0-9]{12}-[0-9a-f]{16})\/gen\//.exec(value);
+      const runs = new RegExp(`^(${run})/txn/${ordinal}/(${run})/gen/`).exec(value);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/codec/src/index.ts` around lines 502 - 506, Update the same-run
validation in the ID-TXN/ID-OP branch to derive its regular expression from the
shared run grammar constant and existing patterns utilities, rather than
duplicating the inline run literal. Preserve the current capture comparison and
INVALID_SCOPE behavior, keeping the check synchronized with the run definition.
tests/codec/corpus.test.mjs (2)

92-96: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Positional case indices make the tamper matrix brittle.

cases[0], cases[7], cases[1] silently target the wrong case if the corpus is reordered — and a mutation that lands on a case without canonicalBytesSha256/stagedDigest would make the assertion pass for the wrong reason. Select by id (valid-canonical, digest-bound, malformed) instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/codec/corpus.test.mjs` around lines 92 - 96, Select mutation targets by
their stable case IDs in the tamper matrix instead of positional indexes: use
valid-canonical for canonicalBytesSha256, digest-bound for stagedDigest, and
malformed for result.error.code. Preserve the existing mutations while ensuring
each field is modified on the intended corpus case.

79-79: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Test depends on cwd and a hardcoded /tmp.

'tests/codec/golden-consumer.mjs' resolves against process.cwd(), so the test only passes when the runner is invoked from the repository root; and mkdtempSync('/tmp/...') ignores TMPDIR and is not portable. Both are easy to make self-locating.

♻️ Proposed change
-import { join } from 'node:path';
+import { tmpdir } from 'node:os';
+import { join } from 'node:path';
+import { fileURLToPath } from 'node:url';
+
+const consumer = fileURLToPath(new URL('./golden-consumer.mjs', import.meta.url));
-  const result = spawnSync(process.execPath, ['tests/codec/golden-consumer.mjs'], { encoding: 'utf8' });
+  const result = spawnSync(process.execPath, [consumer], { encoding: 'utf8' });
-  const root = mkdtempSync('/tmp/codec-corpus-');
+  const root = mkdtempSync(join(tmpdir(), 'codec-corpus-'));
-      const result = spawnSync(process.execPath, ['tests/codec/golden-consumer.mjs', path], { encoding: 'utf8' });
+      const result = spawnSync(process.execPath, [consumer, path], { encoding: 'utf8' });

Also applies to: 90-90, 109-109

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/codec/corpus.test.mjs` at line 79, Update the test’s spawnSync calls to
resolve golden-consumer.mjs relative to the test file rather than process.cwd(),
and replace hardcoded /tmp mkdtempSync prefixes with a portable
temporary-directory source such as os.tmpdir(). Apply the same self-locating
changes to the occurrences around the referenced lines.
tests/codec/golden-consumer.mjs (1)

25-31: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Dispatch on key presence rather than truthiness.

An empty-string frame (a natural hostile-input case to add later) is falsy and would fall through to validateStagedDigest(undefined). Object.hasOwn(entry, 'frame') keeps the dispatch faithful to the fixture shape.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/codec/golden-consumer.mjs` around lines 25 - 31, Update actualCase to
dispatch based on whether each fixture key exists, not whether its value is
truthy; use own-property checks for frame, generator, identity, and staged so
empty-string values still reach their intended handlers and unsupported entries
continue throwing.
packages/authority-kernel/tsconfig.json (1)

6-6: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Drop DOM from lib for this package.

src/index.ts uses no DOM APIs, and including DOM makes ambient browser capabilities (fetch, document, timers) type-visible inside a package that the boundary checker is meant to keep free of unbound ambient-capability reads. ["ES2022"] is sufficient here.

♻️ Proposed change
-    "lib": ["ES2022", "DOM"],
+    "lib": ["ES2022"],
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/authority-kernel/tsconfig.json` at line 6, Update the TypeScript
compiler options in tsconfig.json by removing "DOM" from the lib array, leaving
only "ES2022" so browser ambient APIs are not type-visible in this package.
tests/runtime-contracts/topology.test.mjs (2)

175-177: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the crossing lookup succeeded before encoding it.

Only PORT-DECIDE, PORT-SESSION, PORT-WORKSPACE, PORT-VERIFY, PORT-DELIVERY, PORT-LEDGER, and PORT-ARTIFACT have an RT-CONTROLLER-sourced crossing in tests/fixtures/runtime-topology.json. If tests/fixtures/runtime-fakes.json ever lists any other port, crossing is undefined and the failure surfaces as an opaque crash inside encodedCrossing instead of a diagnosable assertion.

🛡️ Proposed guard
     const crossing = fixture.allowedCrossings.find((entry) => entry.port === port && entry.source === 'RT-CONTROLLER');
+    assert.ok(crossing, `no RT-CONTROLLER crossing declared for ${port}`);
     const serialized = encodedCrossing(crossing);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/runtime-contracts/topology.test.mjs` around lines 175 - 177, In the
crossing lookup test, assert that the `crossing` result from
`fixture.allowedCrossings.find` is defined before passing it to
`encodedCrossing`. Add a clear assertion message identifying the missing port,
while preserving the existing encoding and invocation flow for valid crossings.

102-149: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

These hostile-object probes only re-test the typeof serialized !== 'string' guard.

validateTopologyCrossing rejects any non-string before decoding, so the toJSON trap, the getter accessor, and the Proxy trap counters at Lines 120-121 and 149 pass vacuously — no descriptor-vs-getter or ownKeys behavior is actually exercised. If the intent is to prove the parser never invokes user code, drive these through the string frame path (e.g. encode a canonical frame whose payload is the hostile shape, or assert the same invariants inside parsedCrossing); otherwise this collapses to a single non-string rejection case.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/runtime-contracts/topology.test.mjs` around lines 102 - 149, Update the
hostile-object probes around validateTopologyCrossing and
createScriptedFake().invoke so they exercise the string-frame decoding path
rather than only the typeof serialized !== 'string' rejection. Encode canonical
frames containing the accessor and Proxy payloads, or move the assertions into
parsedCrossing, and preserve checks that getters and Proxy traps remain unused
during validation.
packages/authority-kernel/src/index.ts (1)

178-187: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Symbol-keyed extra properties slip past the exact-shape check.

Object.keys(descriptors) enumerates only string keys, so { ...event, [Symbol('extra')]: 1 } satisfies both the length and membership checks. The returned snapshot is rebuilt from keys so nothing leaks, but it does weaken the stated "exact shape" rejection that tests/runtime-contracts/topology.test.mjs asserts for the codec path. Use Reflect.ownKeys(value) for the count if strict rejection is intended.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/authority-kernel/src/index.ts` around lines 178 - 187, Update the
exact-shape validation around the descriptors check to count all own keys,
including symbols, by using Reflect.ownKeys(value) for the property-count
comparison. Preserve the existing descriptor and string-key membership checks,
and continue returning undefined when extra symbol-keyed properties are present.
tests/authority-kernel/authority-kernel.test.mjs (1)

231-232: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the reducer succeeded before spreading .value.

If reduceAuthority regresses, transition becomes undefined, every { ...transition, ... } case degrades to a bare object, and all twelve validateTransition cases still return FC-INPUT — passing for the wrong reason.

🛡️ Proposed guard
-  const transition = kernel.reduceAuthority(state, event, bindings).value;
+  const reduced = kernel.reduceAuthority(state, event, bindings);
+  assert.equal(reduced.ok, true);
+  const transition = reduced.value;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/authority-kernel/authority-kernel.test.mjs` around lines 231 - 232,
Validate the result of kernel.reduceAuthority(state, event, bindings) before
accessing its value or constructing transition assertions. Add an explicit
success assertion for the reducer result in this test flow, then preserve the
existing transition and replayStep handling so failures stop immediately instead
of allowing validateTransition cases to pass on an empty object.
tests/fixtures/conformance-oracle.json (2)

133-139: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

faults.timeout and faults.resume are unreferenced.

Only before-record / after-record / before-evaluation are consumed by the tests, and runAttempt has no timeout/resume crash points. Either exercise them or drop them from the oracle.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/fixtures/conformance-oracle.json` around lines 133 - 139, Remove the
unreferenced timeout and resume entries from the faults object in the
conformance oracle, since runAttempt has no corresponding crash points and the
tests only consume before-record, after-record, and before-evaluation.

186-186: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Unify the route digest key name.

routeElementsBatch1 uses digest while batches 2 and 3 use routeDigest, forcing the route.digest ?? route.routeDigest fallback in tests/conformance/conformance.test.mjs (Line 88). Pick one key so the oracle stays mechanically checkable.

Also applies to: 277-277

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/fixtures/conformance-oracle.json` at line 186, Unify the route digest
property in tests/fixtures/conformance-oracle.json by renaming the batch 1
routeElements entries’ digest key to routeDigest, matching batches 2 and 3. Then
update the conformance test’s route digest access to use the single routeDigest
key without the digest fallback.
packages/conformance/tsconfig.json (1)

3-3: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider a narrow ambient instead of the whole DOM lib.

packages/runtime-contracts/src/index.ts declares minimal TextEncoder/TextDecoder ambients rather than pulling DOM in; matching that here keeps the pure package from acquiring the entire browser global surface (and accidentally type-checking document/fetch usage).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/conformance/tsconfig.json` at line 3, Update the conformance
tsconfig compilerOptions to remove the broad DOM library and use the package’s
narrow TextEncoder/TextDecoder ambient declarations, matching the approach in
runtime-contracts/src/index.ts while retaining ES2022 support.
tests/conformance/conformance.test.mjs (1)

99-99: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

This assertion is tautological.

Appending 0 to a truncated digest only differs from the original when the last character isn't 0, which is true by luck for this fixture. It proves nothing about tamper detection — either drop it or recompute a digest over mutated elements (as done on Lines 92-98).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/conformance/conformance.test.mjs` at line 99, The assertion involving
oracle.routeElementsBatch1[0].digest is tautological because it relies on the
fixture’s final character; remove it or replace it with a meaningful
tamper-detection check that mutates route elements and recomputes their digest,
following the established approach in the assertions on lines 92-98.
packages/conformance/src/index.ts (1)

740-742: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Loop/local suite shadows the module-level suite() route-element helper.

Purely a readability nit — rename to suiteId in suiteGate and evaluateProvider to keep the helper visible.

Also applies to: 752-752

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/conformance/src/index.ts` around lines 740 - 742, Rename the
loop-local suite variables to suiteId in suiteGate and evaluateProvider,
including their references in seen/expected checks and reason construction,
while leaving the module-level suite() route-element helper unchanged.
scripts/write-evidence.mjs (1)

14-14: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Use a byte-stable comparator for digest ordering.

localeCompare is locale- and ICU-sensitive, so key insertion order in fixtureDigests — and therefore the serialized evidence.json bytes — can differ between machines. For a determinism-oriented evidence artifact, prefer a plain code-unit comparison.

♻️ Proposed fix
-  for (const entry of readdirSync(current, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
+  for (const entry of readdirSync(current, { withFileTypes: true }).sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0))) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/write-evidence.mjs` at line 14, Update the directory-entry sort in
the evidence generation loop to use a locale-independent plain code-unit
comparator instead of localeCompare, ensuring fixtureDigests and serialized
evidence.json ordering remain byte-stable across machines.
scripts/check-runtime-topology.test.mjs (1)

22-41: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider covering the missing-input early return and the manifest gate.

Lines 36-38 (runtime topology required input is missing, which short-circuits everything downstream) and the manifest checks at Lines 60-70 of check-runtime-topology.mjs have no test. Both are cheap to add with the existing withCopy helper.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/check-runtime-topology.test.mjs` around lines 22 - 41, Add tests in
scripts/check-runtime-topology.test.mjs using withCopy to cover the missing
required input early return in validateRuntimeTopology and the manifest
validation checks in check-runtime-topology.mjs. Assert the missing-input case
returns the expected error without running downstream validation, and add a
copied-manifest case that exercises the manifest gate and verifies its reported
failure.
scripts/check-runtime-topology.mjs (1)

71-75: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Text-regex capability scan duplicates — and weakens — the AST checker on a blocking path.

check-package-boundaries.mjs replaced exactly this rule with a TypeScript AST walk (importSpecifiers / unboundIdentifierReads), and its test asserts that comments and string literals are not scanned. Here the raw /\b(fetch|process|require)\b/ matches inside comments and strings, so a doc comment mentioning process fails pnpm runtime:check with a misleading message; conversely /from ['"].../ misses bare side-effect imports (import 'node:fs';) and dynamic import('node:fs').

Export the two helpers from check-package-boundaries.mjs and reuse them here so both gates share one implementation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/check-runtime-topology.mjs` around lines 71 - 75, Replace the raw
regex capability scan in check-runtime-topology.mjs with the shared AST-based
helpers importSpecifiers and unboundIdentifierReads from
check-package-boundaries.mjs. Export those helpers there, then reuse them for
runtime topology validation so comments and strings are ignored while
side-effect and dynamic imports are detected consistently.
scripts/check-package-boundaries.mjs (1)

174-197: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

exportedNames misses several export forms, leaving gaps in the prohibited-surface gate.

Not covered: export default ..., export * from '...' / export * as ns from '...', and binding-pattern declarations (export const { dispatch } = impl;declaration.name is not an Identifier, so it is silently skipped). A star re-export of an allowed dependency, or a default export object, bypasses the prohibitedExportNames regex entirely.

Suggest at minimum treating export default and export * as unresolvable surfaces and rejecting them outright, and recursing into BindingPattern names.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/check-package-boundaries.mjs` around lines 174 - 197, Update
exportedNames to reject unresolvable export forms by detecting default export
declarations and export-all declarations, including namespace re-exports, rather
than allowing them through the prohibited-surface check. Extend variable export
handling to recursively collect identifiers from BindingPattern names such as
object and array destructuring, while preserving existing handling for direct
identifiers and named exports.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@package.json`:
- Around line 31-34: Remove the tsc --build tsconfig.json step from the test
script in package.json so test only runs the Node test suite. Keep compilation
handled by the existing typecheck step invoked by check, avoiding duplicate
builds and emitted artifacts.

In `@packages/authority-kernel/src/index.ts`:
- Around line 451-458: Remove the tautological sameBinding(subject, { ...subject
}) condition from the FC-SUBJECT validation in the event-binding gate. Preserve
the parseIdentity, event-prefix, subject.basis, and fence.generation checks
unchanged.

In `@packages/codec/package.json`:
- Around line 6-10: Update the package exports configuration around the
"exports" and "types" fields to use an object export map with a "types"
condition pointing to the declaration file and a default condition pointing to
the JavaScript entry. Remove reliance on the separate top-level "types" field
while preserving the existing entry paths.

In `@packages/codec/src/index.ts`:
- Around line 112-119: Update the surrogate validation loop in the frame
encoding/decoding path to reject a high surrogate when it is the final code
unit, explicitly checking that the next code unit exists before validating its
range. Preserve existing handling for valid pairs and lone low surrogates, and
add coverage for trailing lone surrogates through both encodeFrame and
decodeFrame.

In `@packages/conformance/package.json`:
- Line 10: Update the typecheck script in package.json to use a TypeScript
5.8.2-compatible command instead of tsc --build --noEmit, while preserving the
script’s purpose of validating the package types.

In `@packages/conformance/src/index.ts`:
- Line 66: Deeply freeze all exported authority data: in
packages/conformance/src/index.ts at line 66, freeze the SUITES.slice(0, 32)
result and type REALIZATION_SUITES as readonly SuiteId[]; at line 124, freeze
each ProductRoute, its elements array, and each element before freezing
PRODUCT_ROUTE_ORACLE; in packages/runtime-contracts/src/index.ts at line 97,
freeze every ALLOWED_CROSSINGS entry and its ports/TOPOLOGY members, and make
validateTopologyCrossing return a frozen copy instead of the live match.

In `@README.md`:
- Around line 45-46: Update the README description of the delivery check to
include typecheck, package-boundary validation, runtime-topology validation, and
the full test suite executed by the pnpm check chain, or explicitly label the
current list as non-exhaustive.

In `@scripts/check-active-repository.mjs`:
- Around line 376-517: Update scripts/check-active-repository.mjs lines 376-517
and scripts/check-package-boundaries.mjs lines 308-368 to use the existing
shared readTextOr/readJsonOr helpers for every required text and JSON input
identified by the review, including the guarded package manifests. Ensure
missing or malformed files push validation errors and return undefined instead
of throwing, while preserving existing validation behavior when reads succeed.

In `@scripts/check-package-boundaries.mjs`:
- Around line 321-328: Update the runtime-contracts validatePureSurface call to
provide the ambient capabilities it is allowed to use, including the existing
process export and fetch/require capabilities used by the other pure-package
validations, instead of passing an empty Set. Keep the current rootDir, package
name, export regex, and errors handling unchanged.

In `@scripts/write-evidence.mjs`:
- Line 7: Validate the CLI subject immediately after reading process.argv[2] and
before any path construction or file writes. Accept only the expected phase-0
subject format (for example, a strict allowlist) and reject invalid values so
path segments cannot escape the artifacts directory; apply the same validation
to the related usages around lines 43–44.
- Around line 28-41: Update the test invocation in the evidence-writing flow to
set an appropriate spawn timeout and inspect both test.error and a null
test.status, treating spawn failures, signal termination, and timeouts as failed
runs. Ensure the script exits nonzero and does not produce a successful-looking
artifact when pnpm test does not complete normally, while preserving the
existing exitCode recording for completed runs.

In `@tests/fixtures/codec-corpus.json`:
- Around line 6-13: The requiredClassSet metadata is disconnected from the
corpus case classifications and is not validated. In the codec corpus fixture
and its tests, either rename/assign case class values so every entry in
requiredClassSet is represented and update corpus.test.mjs to assert each
required class appears, or remove requiredClassSet and its self-equality
assertion entirely.

---

Nitpick comments:
In `@packages/authority-kernel/src/index.ts`:
- Around line 178-187: Update the exact-shape validation around the descriptors
check to count all own keys, including symbols, by using Reflect.ownKeys(value)
for the property-count comparison. Preserve the existing descriptor and
string-key membership checks, and continue returning undefined when extra
symbol-keyed properties are present.

In `@packages/authority-kernel/tsconfig.json`:
- Line 6: Update the TypeScript compiler options in tsconfig.json by removing
"DOM" from the lib array, leaving only "ES2022" so browser ambient APIs are not
type-visible in this package.

In `@packages/codec/src/index.ts`:
- Around line 97-106: Update compareKeys to compare string characters by UTF-16
code units rather than spreading into Unicode code points, preserving
lexicographic ordering and length fallback. If the code-point ordering is
intentional, instead document near compareKeys that jig.codec.v1 is not
JCS-compatible; otherwise implement the UTF-16 ordering required for
cross-runtime compatibility.
- Around line 502-506: Update the same-run validation in the ID-TXN/ID-OP branch
to derive its regular expression from the shared run grammar constant and
existing patterns utilities, rather than duplicating the inline run literal.
Preserve the current capture comparison and INVALID_SCOPE behavior, keeping the
check synchronized with the run definition.

In `@packages/codec/tsconfig.json`:
- Line 6: Remove "DOM" from the lib array in the codec TypeScript configuration,
retaining only the ES2022 library and relying on the existing `@types/node`
declarations for TextEncoder and TextDecoder.

In `@packages/conformance/src/index.ts`:
- Around line 740-742: Rename the loop-local suite variables to suiteId in
suiteGate and evaluateProvider, including their references in seen/expected
checks and reason construction, while leaving the module-level suite()
route-element helper unchanged.

In `@packages/conformance/tsconfig.json`:
- Line 3: Update the conformance tsconfig compilerOptions to remove the broad
DOM library and use the package’s narrow TextEncoder/TextDecoder ambient
declarations, matching the approach in runtime-contracts/src/index.ts while
retaining ES2022 support.

In `@scripts/check-package-boundaries.mjs`:
- Around line 174-197: Update exportedNames to reject unresolvable export forms
by detecting default export declarations and export-all declarations, including
namespace re-exports, rather than allowing them through the prohibited-surface
check. Extend variable export handling to recursively collect identifiers from
BindingPattern names such as object and array destructuring, while preserving
existing handling for direct identifiers and named exports.

In `@scripts/check-runtime-topology.mjs`:
- Around line 71-75: Replace the raw regex capability scan in
check-runtime-topology.mjs with the shared AST-based helpers importSpecifiers
and unboundIdentifierReads from check-package-boundaries.mjs. Export those
helpers there, then reuse them for runtime topology validation so comments and
strings are ignored while side-effect and dynamic imports are detected
consistently.

In `@scripts/check-runtime-topology.test.mjs`:
- Around line 22-41: Add tests in scripts/check-runtime-topology.test.mjs using
withCopy to cover the missing required input early return in
validateRuntimeTopology and the manifest validation checks in
check-runtime-topology.mjs. Assert the missing-input case returns the expected
error without running downstream validation, and add a copied-manifest case that
exercises the manifest gate and verifies its reported failure.

In `@scripts/write-evidence.mjs`:
- Line 14: Update the directory-entry sort in the evidence generation loop to
use a locale-independent plain code-unit comparator instead of localeCompare,
ensuring fixtureDigests and serialized evidence.json ordering remain byte-stable
across machines.

In `@tests/authority-kernel/authority-kernel.test.mjs`:
- Around line 231-232: Validate the result of kernel.reduceAuthority(state,
event, bindings) before accessing its value or constructing transition
assertions. Add an explicit success assertion for the reducer result in this
test flow, then preserve the existing transition and replayStep handling so
failures stop immediately instead of allowing validateTransition cases to pass
on an empty object.

In `@tests/codec/codec.test.mjs`:
- Around line 95-101: Ensure the formatter test explicitly asserts that
corpus.constructors contains exactly 22 entries before iterating, and add the
equivalent count assertion for the identity loop’s constructor collection. Keep
the existing per-entry assertions unchanged so the tests still validate every
supplied canonical form.

In `@tests/codec/corpus.test.mjs`:
- Around line 92-96: Select mutation targets by their stable case IDs in the
tamper matrix instead of positional indexes: use valid-canonical for
canonicalBytesSha256, digest-bound for stagedDigest, and malformed for
result.error.code. Preserve the existing mutations while ensuring each field is
modified on the intended corpus case.
- Line 79: Update the test’s spawnSync calls to resolve golden-consumer.mjs
relative to the test file rather than process.cwd(), and replace hardcoded /tmp
mkdtempSync prefixes with a portable temporary-directory source such as
os.tmpdir(). Apply the same self-locating changes to the occurrences around the
referenced lines.

In `@tests/codec/golden-consumer.mjs`:
- Around line 25-31: Update actualCase to dispatch based on whether each fixture
key exists, not whether its value is truthy; use own-property checks for frame,
generator, identity, and staged so empty-string values still reach their
intended handlers and unsupported entries continue throwing.

In `@tests/conformance/conformance.test.mjs`:
- Line 99: The assertion involving oracle.routeElementsBatch1[0].digest is
tautological because it relies on the fixture’s final character; remove it or
replace it with a meaningful tamper-detection check that mutates route elements
and recomputes their digest, following the established approach in the
assertions on lines 92-98.

In `@tests/fixtures/conformance-oracle.json`:
- Around line 133-139: Remove the unreferenced timeout and resume entries from
the faults object in the conformance oracle, since runAttempt has no
corresponding crash points and the tests only consume before-record,
after-record, and before-evaluation.
- Line 186: Unify the route digest property in
tests/fixtures/conformance-oracle.json by renaming the batch 1 routeElements
entries’ digest key to routeDigest, matching batches 2 and 3. Then update the
conformance test’s route digest access to use the single routeDigest key without
the digest fallback.

In `@tests/runtime-contracts/topology.test.mjs`:
- Around line 175-177: In the crossing lookup test, assert that the `crossing`
result from `fixture.allowedCrossings.find` is defined before passing it to
`encodedCrossing`. Add a clear assertion message identifying the missing port,
while preserving the existing encoding and invocation flow for valid crossings.
- Around line 102-149: Update the hostile-object probes around
validateTopologyCrossing and createScriptedFake().invoke so they exercise the
string-frame decoding path rather than only the typeof serialized !== 'string'
rejection. Encode canonical frames containing the accessor and Proxy payloads,
or move the assertions into parsedCrossing, and preserve checks that getters and
Proxy traps remain unused during validation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 69795f10-4203-4b48-aac0-a8a94ebfeb58

📥 Commits

Reviewing files that changed from the base of the PR and between ef16251 and 2325231.

⛔ Files ignored due to path filters (2)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • tests/fixtures/workspace/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (58)
  • .github/workflows/check.yml
  • AGENTS.md
  • README.md
  • package.json
  • packages/authority-kernel/package.json
  • packages/authority-kernel/src/index.ts
  • packages/authority-kernel/tsconfig.json
  • packages/codec/package.json
  • packages/codec/src/index.ts
  • packages/codec/tsconfig.json
  • packages/conformance/package.json
  • packages/conformance/src/index.ts
  • packages/conformance/tsconfig.json
  • packages/runtime-contracts/package.json
  • packages/runtime-contracts/src/index.ts
  • packages/runtime-contracts/tsconfig.json
  • pnpm-workspace.yaml
  • scripts/check-active-repository.mjs
  • scripts/check-active-repository.test.mjs
  • scripts/check-delivery-track.mjs
  • scripts/check-delivery-track.test.mjs
  • scripts/check-package-boundaries.mjs
  • scripts/check-package-boundaries.test.mjs
  • scripts/check-runtime-topology.mjs
  • scripts/check-runtime-topology.test.mjs
  • scripts/run-gf-001-tests.mjs
  • scripts/write-evidence.mjs
  • scripts/write-gf-001-evidence.mjs
  • tests/authority-kernel/authority-kernel.test.mjs
  • tests/codec/codec.test.mjs
  • tests/codec/corpus.test.mjs
  • tests/codec/golden-consumer.mjs
  • tests/conformance/conformance.test.mjs
  • tests/fixtures/authority-oracle.json
  • tests/fixtures/codec-corpus.json
  • tests/fixtures/codec-vectors.json
  • tests/fixtures/conformance-oracle.json
  • tests/fixtures/runtime-fakes.json
  • tests/fixtures/runtime-topology.json
  • tests/fixtures/workspace/.gitignore
  • tests/fixtures/workspace/package.json
  • tests/fixtures/workspace/packages/pkg-a/package.json
  • tests/fixtures/workspace/packages/pkg-a/src/index.ts
  • tests/fixtures/workspace/packages/pkg-a/tsconfig.json
  • tests/fixtures/workspace/packages/pkg-b/package.json
  • tests/fixtures/workspace/packages/pkg-b/src/index.ts
  • tests/fixtures/workspace/packages/pkg-b/tsconfig.json
  • tests/fixtures/workspace/packages/pkg-c/package.json
  • tests/fixtures/workspace/packages/pkg-c/src/index.ts
  • tests/fixtures/workspace/packages/pkg-c/tsconfig.json
  • tests/fixtures/workspace/pnpm-workspace.yaml
  • tests/fixtures/workspace/tsconfig.base.json
  • tests/fixtures/workspace/tsconfig.json
  • tests/gf-001/evidence-contract.json
  • tests/gf-001/evidence.test.mjs
  • tests/runtime-contracts/topology.test.mjs
  • tests/workspace/workspace-substrate.test.mjs
  • tsconfig.json
💤 Files with no reviewable changes (4)
  • tests/gf-001/evidence-contract.json
  • scripts/run-gf-001-tests.mjs
  • tests/gf-001/evidence.test.mjs
  • scripts/write-gf-001-evidence.mjs

Comment thread package.json
Comment thread packages/authority-kernel/src/index.ts
Comment thread packages/codec/package.json
Comment thread packages/codec/src/index.ts
Comment thread packages/conformance/package.json
Comment thread scripts/check-active-repository.mjs Outdated
Comment thread scripts/check-package-boundaries.mjs
Comment thread scripts/write-evidence.mjs
Comment thread scripts/write-evidence.mjs Outdated
Comment thread tests/fixtures/codec-corpus.json Outdated
@aryeko
aryeko merged commit 0c3cfe3 into main Jul 27, 2026
2 checks passed
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