[PR #1370] [MERGED] perf(javascript): validate the version change graph once #2833

Closed
opened 2026-10-17 21:10:48 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/1370
Author: @keemsisi
Created: 10/9/2026
Status: ✅ Merged
Merged: 10/9/2026
Merged by: @morluto

Base: main ← Head: perf/version-change-graph-reuse


📝 Commits (1)

  • 0653a83 perf(javascript): validate the version change graph once

📊 Changes

4 files changed (+160 additions, -6 deletions)

View changed files

📝 src/domain/javascript/javascriptApplicationChangeGraph.ts (+5 -3)
➕ src/domain/javascript/javascriptApplicationVersionComparison.test.ts (+140 -0)
📝 src/domain/javascript/javascriptApplicationVersionComparison.ts (+2 -2)
📝 src/domain/javascript/javascriptApplicationVersionComparisonSchemas.ts (+13 -1)

📄 Description

Summary

compareJavaScriptApplicationVersions validates its cross-version change graph twice. It is first built with createJavaScriptApplicationGraph, which validates the graph and re-derives every node, observation, edge and graph ID. Then the whole result is parsed with applicationVersionComparisonResultSchema, whose graph field is the full javascriptApplicationGraphSchema, so all of that validation and hashing runs again on the same graph. This change seals the change graph once with the owned immutable factory and accepts that exact sealed graph when parsing the result, the same pattern owned analysis results already use (#1112). The comparison is 1.13–1.40× faster across every measured size and shape, and the output is byte-identical.

No issue is linked: this is a focused performance fix, and the measurements below describe the problem and the result.

Problem and expected behavior

Trigger: any compare_application_versions call. The cost scales with the size of the change graph.

On a CPU profile of main at b1e85ad71 (4,000 modules with about 6 edges each), hashing and validation of the change graph were the largest costs inside the comparison:

  • about 22% under buildJavaScriptApplicationChangeGraph → checkGraphInvariants (graph validation, re-hashing IDs);
  • about 22% under the final applicationVersionComparisonResultSchema.parse → checkGraphInvariants, validating the same graph again.

Expected: the change graph is validated once, and the final result parse still validates every other field, with the same output.

Change and scope

  • javascriptApplicationChangeGraph.ts: build the graph with createImmutableJavaScriptApplicationGraphSteps and drain its steps synchronously. Validation still runs eagerly inside createJavaScriptApplicationGraph, so invalid input throws as before. The graph is then deep-frozen and recorded as owned.
  • javascriptApplicationVersionComparisonSchemas.ts: add ownedApplicationVersionComparisonResultSchema, which is applicationVersionComparisonResultSchema.safeExtend({ graph: z.custom(isValidatedImmutableJavaScriptApplicationGraph) }). It keeps strictness and the coverage refinement. The public applicationVersionComparisonResultSchema is unchanged.
  • javascriptApplicationVersionComparison.ts: parse the result with the owned schema.

Not included: no change to graph validation itself, ID derivation, createJavaScriptApplicationGraph, the public result schema, MCP/CLI contracts, or evidence creation.

Contract and boundary impact

  • Semantic owner and earliest changed stage: domain, src/domain/javascript version comparison.
  • CLI and MCP/tool-catalog contract: none; inputs and outputs are unchanged. The MCP output path still validates the result with the full public schema.
  • Provider, bridge, target-format, or platform compatibility: none.
  • Evidence, artifact, provenance, or reconstruction contract: none; the comparison result, comparison_id, change graph and Evidence are byte-identical. The returned graph is now a frozen owned snapshot. The only production consumer (createApplicationVersionComparisonEvidence) copies it via jsonValueSchema.parse, and nothing mutates it.
  • Process execution, authorization, cleanup, or containment impact: none.
  • Generated metadata (docs/public/product-catalog.json), package, or installation impact: none; no generated outputs committed.

Evidence and regression coverage

  • Tests added: src/domain/javascript/javascriptApplicationVersionComparison.test.ts:

    • returns a sealed change graph (containing a changed_from edge) that passes parseJavaScriptApplicationGraph and the public applicationVersionComparisonResultSchema unchanged;
    • does not reuse a change graph without an owned proof: a structurally valid copy is rejected by the owned schema and still accepted by the public schema;
    • keeps the coverage refinement for owned results.

    The tests assert behaviour only, not timing or call counts.

  • Mutants applied to this change, run against the new tests plus javascriptApplicationVersionRelationships.test.ts and tests/boundary/filesystem/javascriptApplicationWorkflows.test.ts. All were caught, and the restored code passes 19/19:

    Mutant Result
    owned schema accepts any graph 1 of 19 tests fails
    owned schema falls back to full graph validation 2 of 19 tests fail
    owned schema built without the coverage refinement 1 of 19 tests fails
  • Performance: end-to-end compareJavaScriptApplicationVersions on synthetic version pairs, using the built dist of main (b1e85ad71) and of this branch. Runs are interleaved main/PR/PR/main; each run is 1 warm-up plus 5 repetitions, and small sizes repeat the call within each timing to reach about 2,000 module-comparisons. The tables show the best run's best / median. The full result JSON hash is identical for every row.

    Changed versions (every module's source differs; about a fifth of edges change relation):

Modules Edges per module main This PR Speedup (best) Output identical (sha256 prefix)
10 ~2 5.28 / 5.57 ms 4.20 / 4.45 ms 1.26× yes, b52031fae7a63785
10 ~6 8.89 / 9.64 ms 6.68 / 7.11 ms 1.33× yes, 69a588451f3099d3
100 ~2 59.50 / 62.33 ms 46.02 / 49.05 ms 1.29× yes, 3c351ba04c39634a
100 ~6 106.2 / 115.7 ms 87.10 / 88.70 ms 1.22× yes, ea2eb722943ce873
1,000 ~2 661.9 / 739.6 ms 527.8 / 562.5 ms 1.25× yes, 814bce35ceb5910c
1,000 ~6 1,172.0 / 1,202.6 ms 918.4 / 993.9 ms 1.28× yes, 8b5ec959e7390f50
4,000 ~2 2,800.1 / 2,910.6 ms 2,276.2 / 2,394.0 ms 1.23× yes, 958201fc5a3c61c9
4,000 ~6 4,949.9 / 5,115.9 ms 3,829.1 / 3,941.3 ms 1.29× yes, 69ba838f3fdea9f1
8,000 ~2 6,174.3 / 6,520.9 ms 4,994.8 / 5,275.4 ms 1.24× yes, 380bf5e8bae2dfe7
8,000 ~6 11,463.1 / 11,914.7 ms 8,976.8 / 9,776.3 ms 1.28× yes, d8695a92e3183709

Identical versions (all modules unchanged):

Modules Edges per module main This PR Speedup (best) Output identical (sha256 prefix)
10 ~2 4.23 / 4.73 ms 3.69 / 3.99 ms 1.15× yes, 8ee59e951065ee4e
10 ~6 7.89 / 8.11 ms 5.76 / 6.54 ms 1.37× yes, c6d9e6975b04efa8
100 ~2 45.38 / 48.07 ms 36.31 / 40.79 ms 1.25× yes, 72a14801c84d956d
100 ~6 96.46 / 98.60 ms 68.84 / 73.49 ms 1.40× yes, b805055971d0ea0a
1,000 ~2 491.1 / 511.7 ms 403.5 / 429.8 ms 1.22× yes, 83d90c7272d44e21
1,000 ~6 1,026.2 / 1,138.6 ms 821.1 / 866.1 ms 1.25× yes, 8c920cd7191eceee
4,000 ~2 2,024.8 / 2,104.8 ms 1,649.1 / 1,702.4 ms 1.23× yes, 0d4b5a50bfe30086
4,000 ~6 4,263.2 / 4,966.3 ms 3,522.9 / 3,836.6 ms 1.21× yes, a05d86fc49f03c4c

Comparison followed by createApplicationVersionComparisonEvidence, as compare_application_versions does (changed versions; output hash covers the Evidence):

Modules Edges per module main This PR Speedup (best) Output identical (sha256 prefix)
10 ~2 6.81 / 7.37 ms 6.02 / 6.37 ms 1.13× yes, 6ec8b56ec8a36df4
10 ~6 12.04 / 12.40 ms 9.81 / 10.48 ms 1.23× yes, a30012c4e46afd9a
100 ~2 77.13 / 81.30 ms 66.86 / 72.96 ms 1.15× yes, 0d48d5e6aac0495b
100 ~6 142.8 / 147.0 ms 120.0 / 122.6 ms 1.19× yes, 09d44a8f02eb48fa
1,000 ~2 857.0 / 887.4 ms 727.7 / 789.6 ms 1.18× yes, a305ba3a20ef2181
1,000 ~6 1,646.8 / 1,722.8 ms 1,376.6 / 1,464.5 ms 1.20× yes, 9498eae8a947022c
4,000 ~2 3,619.6 / 3,902.2 ms 3,198.1 / 3,382.4 ms 1.13× yes, 859405f1d05e1854
4,000 ~6 6,739.8 / 7,283.4 ms 5,922.9 / 6,135.5 ms 1.14× yes, 1ca824d99f272c79

Same, identical versions:

Modules Edges per module main This PR Speedup (best) Output identical (sha256 prefix)
10 ~2 5.68 / 6.16 ms 4.73 / 4.81 ms 1.20× yes, 959fb972dc097fbd
10 ~6 10.73 / 10.90 ms 8.94 / 10.02 ms 1.20× yes, 940430d61b64322a
100 ~2 65.53 / 74.49 ms 52.99 / 56.22 ms 1.24× yes, a85a9cb142bc2d70
100 ~6 130.1 / 132.1 ms 110.2 / 119.4 ms 1.18× yes, 14c81c3faf93ac6e
1,000 ~2 771.3 / 791.5 ms 618.3 / 662.2 ms 1.25× yes, 0120f4cec21e5e4e
1,000 ~6 1,451.0 / 1,550.6 ms 1,187.7 / 1,310.1 ms 1.22× yes, ee4e81b5ccef9e6b
4,000 ~2 3,009.7 / 3,090.5 ms 2,454.6 / 2,727.5 ms 1.23× yes, 19a31d9ff7551e09
4,000 ~6 5,904.3 / 6,008.8 ms 5,121.3 / 5,263.9 ms 1.15× yes, fa84abac5fa87c8c

The full sweep above was run on base b1e85ad71. After rebasing onto 6ce3288f3, a 12-configuration re-check (changed versions; 10, 1,000 and 4,000 modules; ~2 and ~6 edges; with and without Evidence creation) gave 1.16–1.29× with identical output hashes in every case.

A separate reviewer spot-check at 1 module (about 2 edges) gave 0.38 → 0.32 ms best, so freezing and the owned-proof check cost less than the second validation even on the smallest input.

  • User-visible CLI/MCP output: unchanged; only latency changes.
  • Remaining proof gaps: measured on synthetic graphs, not a recorded real application pair. MCP calls also validate the result with the full public output schema at the boundary, which this change does not touch, so the end-to-end MCP gain is smaller than the domain numbers above.

For evidence-bearing changes:

  • Observed, derived, and inferred claims remain distinguishable.
  • Artifact identity, source provenance, and failed attempts remain preserved.
  • Unsupported, incomplete, unavailable, or uncertain outcomes remain visible.

Validation performed

Run in a Linux arm64 container with Node 24, on this branch rebased onto current main and on unchanged main at 6ce3288f3:

Command This branch main
npm run build:cached 3 of 3 tasks successful 3 of 3 tasks successful
npx vitest run new test + javascriptApplicationVersionRelationships.test.ts + tests/boundary/filesystem/javascriptApplicationWorkflows.test.ts + tests/acceptance/applications/applicationWorkflowCli.test.ts 4 files, 30 tests passed 3 files, 27 tests passed
npm run check 6 of 6 tasks successful 6 of 6 tasks successful
npm run verify:test-discovery all 705 test files discovered once all 704 test files discovered once
npx vitest run --project mcp-boundary (after npm run artifacts:mcp-catalog) 306 passed, 2 skipped 306 passed, 2 skipped
npm run test:fast 3,684 passed, 4 skipped 3,681 passed, 4 skipped

The only differences are the new test file and its three tests. The same commands also passed on the original base b1e85ad71 (test:fast 3,651 vs 3,648; mcp-boundary 297 vs 297), and the three mutants above were re-run after the rebase with the same results.

Compatibility, safety, and release

  • Breaking changes or migration steps: none.
  • Real Hopper/Ghidra, browser, or OS coverage: not applicable; pure domain change.
  • Package or release metadata impact: none.
  • Security, privacy, process, or containment review: the change graph is still fully validated once, before it is sealed. The owned schema accepts only the exact sealed graph produced by the owned factory; any other graph is rejected rather than trusted. The public schema is unchanged.

Review checklist

  • This PR addresses a concrete problem or an agreed enhancement.
  • The PR has one focused outcome and the title follows type(scope): outcome.
  • Related issue is linked, or the reason for not linking one is stated above.
  • Tests cover changed observable behavior and meaningful failure paths.
  • Owning docs, contracts, and generated metadata are updated where needed.
  • User-visible CLI/MCP changes include representative output.
  • I checked the final diff for secrets, unrelated cleanup, and unsupported claims.

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/1370 **Author:** [@keemsisi](https://github.com/keemsisi) **Created:** 10/9/2026 **Status:** ✅ Merged **Merged:** 10/9/2026 **Merged by:** [@morluto](https://github.com/morluto) **Base:** `main` ← **Head:** `perf/version-change-graph-reuse` --- ### 📝 Commits (1) - [`0653a83`](https://github.com/morluto/rea/commit/0653a83e4862370b5ff70ae7dc9d0c392166f4ad) perf(javascript): validate the version change graph once ### 📊 Changes **4 files changed** (+160 additions, -6 deletions) <details> <summary>View changed files</summary> 📝 `src/domain/javascript/javascriptApplicationChangeGraph.ts` (+5 -3) ➕ `src/domain/javascript/javascriptApplicationVersionComparison.test.ts` (+140 -0) 📝 `src/domain/javascript/javascriptApplicationVersionComparison.ts` (+2 -2) 📝 `src/domain/javascript/javascriptApplicationVersionComparisonSchemas.ts` (+13 -1) </details> ### 📄 Description ## Summary `compareJavaScriptApplicationVersions` validates its cross-version change graph twice. It is first built with `createJavaScriptApplicationGraph`, which validates the graph and re-derives every node, observation, edge and graph ID. Then the whole result is parsed with `applicationVersionComparisonResultSchema`, whose `graph` field is the full `javascriptApplicationGraphSchema`, so all of that validation and hashing runs again on the same graph. This change seals the change graph once with the owned immutable factory and accepts that exact sealed graph when parsing the result, the same pattern owned analysis results already use (#1112). The comparison is 1.13–1.40× faster across every measured size and shape, and the output is byte-identical. No issue is linked: this is a focused performance fix, and the measurements below describe the problem and the result. ## Problem and expected behavior Trigger: any `compare_application_versions` call. The cost scales with the size of the change graph. On a CPU profile of `main` at `b1e85ad71` (4,000 modules with about 6 edges each), hashing and validation of the change graph were the largest costs inside the comparison: - about 22% under `buildJavaScriptApplicationChangeGraph` → `checkGraphInvariants` (graph validation, re-hashing IDs); - about 22% under the final `applicationVersionComparisonResultSchema.parse` → `checkGraphInvariants`, validating the same graph again. Expected: the change graph is validated once, and the final result parse still validates every other field, with the same output. ## Change and scope - `javascriptApplicationChangeGraph.ts`: build the graph with `createImmutableJavaScriptApplicationGraphSteps` and drain its steps synchronously. Validation still runs eagerly inside `createJavaScriptApplicationGraph`, so invalid input throws as before. The graph is then deep-frozen and recorded as owned. - `javascriptApplicationVersionComparisonSchemas.ts`: add `ownedApplicationVersionComparisonResultSchema`, which is `applicationVersionComparisonResultSchema.safeExtend({ graph: z.custom(isValidatedImmutableJavaScriptApplicationGraph) })`. It keeps strictness and the coverage refinement. The public `applicationVersionComparisonResultSchema` is unchanged. - `javascriptApplicationVersionComparison.ts`: parse the result with the owned schema. Not included: no change to graph validation itself, ID derivation, `createJavaScriptApplicationGraph`, the public result schema, MCP/CLI contracts, or evidence creation. ## Contract and boundary impact - Semantic owner and earliest changed stage: domain, `src/domain/javascript` version comparison. - CLI and MCP/tool-catalog contract: none; inputs and outputs are unchanged. The MCP output path still validates the result with the full public schema. - Provider, bridge, target-format, or platform compatibility: none. - Evidence, artifact, provenance, or reconstruction contract: none; the comparison result, `comparison_id`, change graph and Evidence are byte-identical. The returned `graph` is now a frozen owned snapshot. The only production consumer (`createApplicationVersionComparisonEvidence`) copies it via `jsonValueSchema.parse`, and nothing mutates it. - Process execution, authorization, cleanup, or containment impact: none. - Generated metadata (`docs/public/product-catalog.json`), package, or installation impact: none; no generated outputs committed. ## Evidence and regression coverage - Tests added: `src/domain/javascript/javascriptApplicationVersionComparison.test.ts`: - returns a sealed change graph (containing a `changed_from` edge) that passes `parseJavaScriptApplicationGraph` and the public `applicationVersionComparisonResultSchema` unchanged; - does not reuse a change graph without an owned proof: a structurally valid copy is rejected by the owned schema and still accepted by the public schema; - keeps the coverage refinement for owned results. The tests assert behaviour only, not timing or call counts. - Mutants applied to this change, run against the new tests plus `javascriptApplicationVersionRelationships.test.ts` and `tests/boundary/filesystem/javascriptApplicationWorkflows.test.ts`. All were caught, and the restored code passes 19/19: | Mutant | Result | |---|---| | owned schema accepts any graph | 1 of 19 tests fails | | owned schema falls back to full graph validation | 2 of 19 tests fail | | owned schema built without the coverage refinement | 1 of 19 tests fails | - Performance: end-to-end `compareJavaScriptApplicationVersions` on synthetic version pairs, using the built `dist` of `main` (`b1e85ad71`) and of this branch. Runs are interleaved `main`/PR/PR/`main`; each run is 1 warm-up plus 5 repetitions, and small sizes repeat the call within each timing to reach about 2,000 module-comparisons. The tables show the best run's best / median. The full result JSON hash is identical for every row. Changed versions (every module's source differs; about a fifth of edges change relation): | Modules | Edges per module | `main` | This PR | Speedup (best) | Output identical (sha256 prefix) | |---|---|---|---|---|---| | 10 | ~2 | 5.28 / 5.57 ms | 4.20 / 4.45 ms | 1.26× | yes, `b52031fae7a63785` | | 10 | ~6 | 8.89 / 9.64 ms | 6.68 / 7.11 ms | 1.33× | yes, `69a588451f3099d3` | | 100 | ~2 | 59.50 / 62.33 ms | 46.02 / 49.05 ms | 1.29× | yes, `3c351ba04c39634a` | | 100 | ~6 | 106.2 / 115.7 ms | 87.10 / 88.70 ms | 1.22× | yes, `ea2eb722943ce873` | | 1,000 | ~2 | 661.9 / 739.6 ms | 527.8 / 562.5 ms | 1.25× | yes, `814bce35ceb5910c` | | 1,000 | ~6 | 1,172.0 / 1,202.6 ms | 918.4 / 993.9 ms | 1.28× | yes, `8b5ec959e7390f50` | | 4,000 | ~2 | 2,800.1 / 2,910.6 ms | 2,276.2 / 2,394.0 ms | 1.23× | yes, `958201fc5a3c61c9` | | 4,000 | ~6 | 4,949.9 / 5,115.9 ms | 3,829.1 / 3,941.3 ms | 1.29× | yes, `69ba838f3fdea9f1` | | 8,000 | ~2 | 6,174.3 / 6,520.9 ms | 4,994.8 / 5,275.4 ms | 1.24× | yes, `380bf5e8bae2dfe7` | | 8,000 | ~6 | 11,463.1 / 11,914.7 ms | 8,976.8 / 9,776.3 ms | 1.28× | yes, `d8695a92e3183709` | Identical versions (all modules unchanged): | Modules | Edges per module | `main` | This PR | Speedup (best) | Output identical (sha256 prefix) | |---|---|---|---|---|---| | 10 | ~2 | 4.23 / 4.73 ms | 3.69 / 3.99 ms | 1.15× | yes, `8ee59e951065ee4e` | | 10 | ~6 | 7.89 / 8.11 ms | 5.76 / 6.54 ms | 1.37× | yes, `c6d9e6975b04efa8` | | 100 | ~2 | 45.38 / 48.07 ms | 36.31 / 40.79 ms | 1.25× | yes, `72a14801c84d956d` | | 100 | ~6 | 96.46 / 98.60 ms | 68.84 / 73.49 ms | 1.40× | yes, `b805055971d0ea0a` | | 1,000 | ~2 | 491.1 / 511.7 ms | 403.5 / 429.8 ms | 1.22× | yes, `83d90c7272d44e21` | | 1,000 | ~6 | 1,026.2 / 1,138.6 ms | 821.1 / 866.1 ms | 1.25× | yes, `8c920cd7191eceee` | | 4,000 | ~2 | 2,024.8 / 2,104.8 ms | 1,649.1 / 1,702.4 ms | 1.23× | yes, `0d4b5a50bfe30086` | | 4,000 | ~6 | 4,263.2 / 4,966.3 ms | 3,522.9 / 3,836.6 ms | 1.21× | yes, `a05d86fc49f03c4c` | Comparison followed by `createApplicationVersionComparisonEvidence`, as `compare_application_versions` does (changed versions; output hash covers the Evidence): | Modules | Edges per module | `main` | This PR | Speedup (best) | Output identical (sha256 prefix) | |---|---|---|---|---|---| | 10 | ~2 | 6.81 / 7.37 ms | 6.02 / 6.37 ms | 1.13× | yes, `6ec8b56ec8a36df4` | | 10 | ~6 | 12.04 / 12.40 ms | 9.81 / 10.48 ms | 1.23× | yes, `a30012c4e46afd9a` | | 100 | ~2 | 77.13 / 81.30 ms | 66.86 / 72.96 ms | 1.15× | yes, `0d48d5e6aac0495b` | | 100 | ~6 | 142.8 / 147.0 ms | 120.0 / 122.6 ms | 1.19× | yes, `09d44a8f02eb48fa` | | 1,000 | ~2 | 857.0 / 887.4 ms | 727.7 / 789.6 ms | 1.18× | yes, `a305ba3a20ef2181` | | 1,000 | ~6 | 1,646.8 / 1,722.8 ms | 1,376.6 / 1,464.5 ms | 1.20× | yes, `9498eae8a947022c` | | 4,000 | ~2 | 3,619.6 / 3,902.2 ms | 3,198.1 / 3,382.4 ms | 1.13× | yes, `859405f1d05e1854` | | 4,000 | ~6 | 6,739.8 / 7,283.4 ms | 5,922.9 / 6,135.5 ms | 1.14× | yes, `1ca824d99f272c79` | Same, identical versions: | Modules | Edges per module | `main` | This PR | Speedup (best) | Output identical (sha256 prefix) | |---|---|---|---|---|---| | 10 | ~2 | 5.68 / 6.16 ms | 4.73 / 4.81 ms | 1.20× | yes, `959fb972dc097fbd` | | 10 | ~6 | 10.73 / 10.90 ms | 8.94 / 10.02 ms | 1.20× | yes, `940430d61b64322a` | | 100 | ~2 | 65.53 / 74.49 ms | 52.99 / 56.22 ms | 1.24× | yes, `a85a9cb142bc2d70` | | 100 | ~6 | 130.1 / 132.1 ms | 110.2 / 119.4 ms | 1.18× | yes, `14c81c3faf93ac6e` | | 1,000 | ~2 | 771.3 / 791.5 ms | 618.3 / 662.2 ms | 1.25× | yes, `0120f4cec21e5e4e` | | 1,000 | ~6 | 1,451.0 / 1,550.6 ms | 1,187.7 / 1,310.1 ms | 1.22× | yes, `ee4e81b5ccef9e6b` | | 4,000 | ~2 | 3,009.7 / 3,090.5 ms | 2,454.6 / 2,727.5 ms | 1.23× | yes, `19a31d9ff7551e09` | | 4,000 | ~6 | 5,904.3 / 6,008.8 ms | 5,121.3 / 5,263.9 ms | 1.15× | yes, `fa84abac5fa87c8c` | The full sweep above was run on base `b1e85ad71`. After rebasing onto `6ce3288f3`, a 12-configuration re-check (changed versions; 10, 1,000 and 4,000 modules; ~2 and ~6 edges; with and without Evidence creation) gave 1.16–1.29× with identical output hashes in every case. A separate reviewer spot-check at 1 module (about 2 edges) gave 0.38 → 0.32 ms best, so freezing and the owned-proof check cost less than the second validation even on the smallest input. - User-visible CLI/MCP output: unchanged; only latency changes. - Remaining proof gaps: measured on synthetic graphs, not a recorded real application pair. MCP calls also validate the result with the full public output schema at the boundary, which this change does not touch, so the end-to-end MCP gain is smaller than the domain numbers above. For evidence-bearing changes: - [x] Observed, derived, and inferred claims remain distinguishable. - [x] Artifact identity, source provenance, and failed attempts remain preserved. - [x] Unsupported, incomplete, unavailable, or uncertain outcomes remain visible. ## Validation performed Run in a Linux arm64 container with Node 24, on this branch rebased onto current `main` and on unchanged `main` at `6ce3288f3`: | Command | This branch | `main` | |---|---|---| | `npm run build:cached` | 3 of 3 tasks successful | 3 of 3 tasks successful | | `npx vitest run` new test + `javascriptApplicationVersionRelationships.test.ts` + `tests/boundary/filesystem/javascriptApplicationWorkflows.test.ts` + `tests/acceptance/applications/applicationWorkflowCli.test.ts` | 4 files, 30 tests passed | 3 files, 27 tests passed | | `npm run check` | 6 of 6 tasks successful | 6 of 6 tasks successful | | `npm run verify:test-discovery` | all 705 test files discovered once | all 704 test files discovered once | | `npx vitest run --project mcp-boundary` (after `npm run artifacts:mcp-catalog`) | 306 passed, 2 skipped | 306 passed, 2 skipped | | `npm run test:fast` | 3,684 passed, 4 skipped | 3,681 passed, 4 skipped | The only differences are the new test file and its three tests. The same commands also passed on the original base `b1e85ad71` (`test:fast` 3,651 vs 3,648; `mcp-boundary` 297 vs 297), and the three mutants above were re-run after the rebase with the same results. ## Compatibility, safety, and release - Breaking changes or migration steps: none. - Real Hopper/Ghidra, browser, or OS coverage: not applicable; pure domain change. - Package or release metadata impact: none. - Security, privacy, process, or containment review: the change graph is still fully validated once, before it is sealed. The owned schema accepts only the exact sealed graph produced by the owned factory; any other graph is rejected rather than trusted. The public schema is unchanged. ## Review checklist - [x] This PR addresses a concrete problem or an agreed enhancement. - [x] The PR has one focused outcome and the title follows `type(scope): outcome`. - [x] Related issue is linked, or the reason for not linking one is stated above. - [x] Tests cover changed observable behavior and meaningful failure paths. - [x] Owning docs, contracts, and generated metadata are updated where needed. - [x] User-visible CLI/MCP changes include representative output. - [x] I checked the final diff for secrets, unrelated cleanup, and unsupported claims. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-17 21:10:48 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#2833
No description provided.