[PR #5129] fix(cli): load Evidence record pairs from JSON files #6782

Open
opened 2026-11-01 21:43:00 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/5129
Author: @jaelliot
Created: 10/18/2026
Status: 🔄 Open

Base: main ← Head: fix/cli-evidence-record-pairs-5107


📝 Commits (9)

  • 26a4f94 fix(cli): read explicit Evidence record pairs from JSON files
  • 2e1d64f test(cli): isolate record-pair file regression
  • 1cb1546 style(cli): format record-pair file regression
  • bb92d9c merge(main): refresh Evidence record-pair file input
  • a016ac2 test(cli): reuse comparison fixture for record-pair file input
  • dd0cc5d style(cli): format reused record-pair test invocation
  • ea086bb test(cli): keep paired-input coverage within lint function limit
  • 418c037 merge(main): refresh Evidence JSON-file input PR
  • a225dd7 merge(main): refresh Evidence record-pair file input

📊 Changes

3 files changed (+38 additions, -44 deletions)

View changed files

📝 docs/cli.md (+6 -4)
📝 src/cliEvidenceCommands.ts (+8 -18)
📝 tests/boundary/cli/bundleComparisonCli.test.ts (+24 -22)

📄 Description

Summary

Add local JSON-file input for the existing Evidence --record_pairs CLI option by reusing REA's established parseCliJsonInput helper. Inline arrays already work on main; callers should also be able to keep the same array in a file. Related: #5107.

Current source: a225dd7. This refresh merges upstream main at d7df9df into the existing branch without rewriting its history. The contribution remains three files, 38 insertions and 44 deletions.

Problem and expected behavior

rea compare left.json right.json --record_pairs '[{...}]' --json accepts inline record pairs. Supplying a path to a JSON file containing that same nonempty array should produce the same validated comparison:

rea compare left.json right.json --record_pairs pairs.json --json

Missing files should produce the existing typed input failure. Unpaired record identities remain unknown; explicitly pairing records does not establish behavioral equivalence.

Change and scope

  • src/cliEvidenceCommands.ts: replace the duplicate inline-only parser and error construction with the existing bounded inline-or-file parser, forwarding the CLI cancellation signal.
  • tests/boundary/cli/bundleComparisonCli.test.ts: extend the existing regression to compare file and inline results and check missing-file failure, reusing its fixture and a small local call helper.
  • docs/cli.md: document the file-input form.

The schema, application comparer, rea compare command and MCP contract retain their existing owners. This is an ordinary offline CLI extension within the contribution scope; a new-provider or target-execution scope decision is not applicable.

Contract and boundary impact

  • Semantic owner / earliest stage: CLI JSON-option parsing; the existing shared parser replaces the inline-only decoding path.
  • CLI / MCP: existing --record_pairs flag and MCP record_pairs schema; CLI additionally accepts a local file path. The removed compare-bundles CLI alias stays removed.
  • Provider / platform: no provider, bridge, binary-format or process-runner changes.
  • Evidence / provenance: existing bundle authentication, record identities, explicit pair membership and unknown outcomes remain enforced by their current components.
  • Authority / cleanup: reads only the caller-selected local JSON input through the existing bounded parser and cancellation path.
  • Generated metadata / package / installation: no authored metadata or dependency changes.

Expected effects:

  • Read existing files or captured data.
  • Launch or attach to a process.
  • Inject instrumentation or run scripts/code.
  • Change process memory, registers, files, or configuration.
  • Contact network services.
  • Recover protected code or work around protections.
  • Documentation or usability only; no target interaction.
  • Not sure yet; investigation or maintainer guidance needed.

The regression harness writes disposable synthetic bundles. The CLI option does not execute or modify a target binary.

Evidence and regression coverage

Executed on the exact tree of the current source commit:

  • Nonempty file-input and inline-input comparisons produce equal schema-validated CLI results; existing MCP parity remains covered.
  • A missing pair file exits with code 1 and includes this validated output fragment:
{
  "code": "invalid_request",
  "input_path": "<the requested missing-pairs.json path>",
  "input_reason": "read-failed"
}
  • Existing coverage retains removed-alias rejection, unknown membership, bundle authentication and relative-path authority.
  • Negative control: temporarily restoring only src/cliEvidenceCommands.ts from d7df9df makes the regression fail at the file-input success assertion (expected exit 0, observed 1). Restoring this PR's implementation makes it pass. No negative-control edits are committed.
  • Boundary evidence covers CLI parsing, missing-file error projection, existing filesystem authority and CLI/MCP comparison parity. Process/provider lifecycle is outside the changed boundary; the existing cancellation signal is forwarded to the established parser.

The merge also imports upstream's existing formatting and JavaScript runtime-test repairs. The previously failing JavaScript runtime-observation test is included in the successful focused run below.

  • 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

Local Linux validation used repository-pinned Node 24.22.1 / npm 11.16.0 and the committed lockfile:

  • npm ci --no-audit --no-fund — passed.
  • npm run test:focused -- tests/boundary/cli/bundleComparisonCli.test.ts tests/boundary/mcp/bundleComparisonMcp.test.ts tests/boundary/filesystem/evidenceBundleFiles.test.ts tests/boundary/mcp/javascriptRuntimeObservationMcp.test.ts — 65/65 tests passed across four files, including package build.
  • Negative-control focused CLI run with the base implementation — failed as expected, precisely at file-input acceptance; restored implementation passed.
  • npm run check — passed: typecheck, lint, formatting, Knip, metadata, module boundaries, architecture guards, production reachability report and typed lint. Lint warnings remain reported; typed lint had zero errors.
  • npm run docs:check — passed, including all nine README consistency tests.
  • git diff --check d7df9df3393f77c78a76a06144ff4f515d5db928 — passed.

Hosted CI: run 41772420229 completed successfully on a225dd7: all eight built-test shards, source tests, static checks, documentation, package build, bundled Windows-controls build, Linux native package verification, Portable tests and CI required passed. The complete run has 17 successful jobs, 23 intentionally skipped jobs and no failures or cancellations. The selected run did not execute the skipped real-provider/conformance lanes; it is not fresh PSP/Ghidra runtime evidence. The previous run 41354850495 failed on the older 418c037 revision with baseline formatting issues and a JavaScript runtime-observation failure; it does not qualify the current revision.

Compatibility, safety, and release

  • Breaking changes / migration: none; inline record-pair input remains supported.
  • Real provider / OS coverage: local Linux CLI, MCP and filesystem tests ran. Real Hopper/Ghidra execution is not applicable to this offline parser change; the current-head hosted run passed its selected standard lanes, including the bundled Windows-controls build and Linux native package verification. Skipped real-provider and Windows-capability lanes remain unexecuted.
  • Package / release metadata: unchanged.
  • Security / privacy / containment: existing caller-selected, bounded file reading; no new network or target-execution authority.

Author readiness

Human owner: @jaelliot

  • I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work.
  • I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps.
  • I declare this PR ready for initial maintainer review.

Before merge

  • This PR addresses a concrete problem and follows up on #5107.
  • Scope is limited to ordinary file input without new target authority.
  • The PR has one focused outcome and a Conventional Commit title.
  • Related issue #5107 is linked.
  • Tests cover changed observable behavior and the meaningful missing-file failure.
  • Owning docs are updated; schema and generated metadata changes are unnecessary.
  • User-visible CLI behavior and representative failure output are described above.
  • 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/5129 **Author:** [@jaelliot](https://github.com/jaelliot) **Created:** 10/18/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `fix/cli-evidence-record-pairs-5107` --- ### 📝 Commits (9) - [`26a4f94`](https://github.com/morluto/rea/commit/26a4f9472a506007aaad3508d91912c234d82524) fix(cli): read explicit Evidence record pairs from JSON files - [`2e1d64f`](https://github.com/morluto/rea/commit/2e1d64ffb375d4e74745b31d866c424519bd3478) test(cli): isolate record-pair file regression - [`1cb1546`](https://github.com/morluto/rea/commit/1cb154654c20309ebf597c13edd5ce462b5518b4) style(cli): format record-pair file regression - [`bb92d9c`](https://github.com/morluto/rea/commit/bb92d9c166491d856793e80ac95e10d5ce2b9fd7) merge(main): refresh Evidence record-pair file input - [`a016ac2`](https://github.com/morluto/rea/commit/a016ac2e846cce40f70c44f5fdf6ba8a5bfcce80) test(cli): reuse comparison fixture for record-pair file input - [`dd0cc5d`](https://github.com/morluto/rea/commit/dd0cc5db0dbfb6508254ff5e7faa9a988e70f3d6) style(cli): format reused record-pair test invocation - [`ea086bb`](https://github.com/morluto/rea/commit/ea086bb26cd62d5bfacf07cc5703e65d7b1ff8af) test(cli): keep paired-input coverage within lint function limit - [`418c037`](https://github.com/morluto/rea/commit/418c03720b0f21685b4d84d13a5773546ae32365) merge(main): refresh Evidence JSON-file input PR - [`a225dd7`](https://github.com/morluto/rea/commit/a225dd7b7f0fee4212ff6f3be5259784db486192) merge(main): refresh Evidence record-pair file input ### 📊 Changes **3 files changed** (+38 additions, -44 deletions) <details> <summary>View changed files</summary> 📝 `docs/cli.md` (+6 -4) 📝 `src/cliEvidenceCommands.ts` (+8 -18) 📝 `tests/boundary/cli/bundleComparisonCli.test.ts` (+24 -22) </details> ### 📄 Description ## Summary Add local JSON-file input for the existing Evidence `--record_pairs` CLI option by reusing REA's established `parseCliJsonInput` helper. Inline arrays already work on `main`; callers should also be able to keep the same array in a file. Related: #5107. **Current source:** [`a225dd7`](https://github.com/jaelliot/rea/commit/a225dd7b7f0fee4212ff6f3be5259784db486192). This refresh merges upstream `main` at [`d7df9df`](https://github.com/morluto/rea/commit/d7df9df3393f77c78a76a06144ff4f515d5db928) into the existing branch without rewriting its history. The contribution remains **three files, 38 insertions and 44 deletions**. ## Problem and expected behavior `rea compare left.json right.json --record_pairs '[{...}]' --json` accepts inline record pairs. Supplying a path to a JSON file containing that same nonempty array should produce the same validated comparison: ```sh rea compare left.json right.json --record_pairs pairs.json --json ``` Missing files should produce the existing typed input failure. Unpaired record identities remain unknown; explicitly pairing records does not establish behavioral equivalence. ## Change and scope - `src/cliEvidenceCommands.ts`: replace the duplicate inline-only parser and error construction with the existing bounded inline-or-file parser, forwarding the CLI cancellation signal. - `tests/boundary/cli/bundleComparisonCli.test.ts`: extend the existing regression to compare file and inline results and check missing-file failure, reusing its fixture and a small local call helper. - `docs/cli.md`: document the file-input form. The schema, application comparer, `rea compare` command and MCP contract retain their existing owners. This is an ordinary offline CLI extension within the [contribution scope](https://github.com/morluto/rea/blob/main/CONTRIBUTING.md#contribution-scope); a new-provider or target-execution scope decision is not applicable. ## Contract and boundary impact - **Semantic owner / earliest stage:** CLI JSON-option parsing; the existing shared parser replaces the inline-only decoding path. - **CLI / MCP:** existing `--record_pairs` flag and MCP `record_pairs` schema; CLI additionally accepts a local file path. The removed `compare-bundles` CLI alias stays removed. - **Provider / platform:** no provider, bridge, binary-format or process-runner changes. - **Evidence / provenance:** existing bundle authentication, record identities, explicit pair membership and unknown outcomes remain enforced by their current components. - **Authority / cleanup:** reads only the caller-selected local JSON input through the existing bounded parser and cancellation path. - **Generated metadata / package / installation:** no authored metadata or dependency changes. Expected effects: - [x] Read existing files or captured data. - [ ] Launch or attach to a process. - [ ] Inject instrumentation or run scripts/code. - [ ] Change process memory, registers, files, or configuration. - [ ] Contact network services. - [ ] Recover protected code or work around protections. - [ ] Documentation or usability only; no target interaction. - [ ] Not sure yet; investigation or maintainer guidance needed. The regression harness writes disposable synthetic bundles. The CLI option does not execute or modify a target binary. ## Evidence and regression coverage **Executed on the exact tree of the current source commit:** - Nonempty file-input and inline-input comparisons produce equal schema-validated CLI results; existing MCP parity remains covered. - A missing pair file exits with code 1 and includes this validated output fragment: ```json { "code": "invalid_request", "input_path": "<the requested missing-pairs.json path>", "input_reason": "read-failed" } ``` - Existing coverage retains removed-alias rejection, unknown membership, bundle authentication and relative-path authority. - **Negative control:** temporarily restoring only `src/cliEvidenceCommands.ts` from `d7df9df` makes the regression fail at the file-input success assertion (expected exit 0, observed 1). Restoring this PR's implementation makes it pass. No negative-control edits are committed. - Boundary evidence covers CLI parsing, missing-file error projection, existing filesystem authority and CLI/MCP comparison parity. Process/provider lifecycle is outside the changed boundary; the existing cancellation signal is forwarded to the established parser. The merge also imports upstream's existing formatting and JavaScript runtime-test repairs. The previously failing JavaScript runtime-observation test is included in the successful focused run below. - [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 Local Linux validation used repository-pinned **Node 24.22.1 / npm 11.16.0** and the committed lockfile: - `npm ci --no-audit --no-fund` — passed. - `npm run test:focused -- tests/boundary/cli/bundleComparisonCli.test.ts tests/boundary/mcp/bundleComparisonMcp.test.ts tests/boundary/filesystem/evidenceBundleFiles.test.ts tests/boundary/mcp/javascriptRuntimeObservationMcp.test.ts` — **65/65 tests passed across four files**, including package build. - Negative-control focused CLI run with the base implementation — **failed as expected**, precisely at file-input acceptance; restored implementation passed. - `npm run check` — **passed**: typecheck, lint, formatting, Knip, metadata, module boundaries, architecture guards, production reachability report and typed lint. Lint warnings remain reported; typed lint had zero errors. - `npm run docs:check` — **passed**, including all nine README consistency tests. - `git diff --check d7df9df3393f77c78a76a06144ff4f515d5db928` — passed. **Hosted CI:** [run 41772420229](https://github.com/morluto/rea/actions/runs/41772420229) **completed successfully on `a225dd7`**: all eight built-test shards, source tests, static checks, documentation, package build, bundled Windows-controls build, Linux native package verification, Portable tests and CI required passed. The complete run has **17 successful jobs, 23 intentionally skipped jobs and no failures or cancellations**. The selected run did not execute the skipped real-provider/conformance lanes; it is not fresh PSP/Ghidra runtime evidence. The previous [run 41354850495](https://github.com/morluto/rea/actions/runs/41354850495) failed on the older `418c037` revision with baseline formatting issues and a JavaScript runtime-observation failure; it does not qualify the current revision. ## Compatibility, safety, and release - **Breaking changes / migration:** none; inline record-pair input remains supported. - **Real provider / OS coverage:** local Linux CLI, MCP and filesystem tests ran. Real Hopper/Ghidra execution is not applicable to this offline parser change; the current-head hosted run passed its selected standard lanes, including the bundled Windows-controls build and Linux native package verification. Skipped real-provider and Windows-capability lanes remain unexecuted. - **Package / release metadata:** unchanged. - **Security / privacy / containment:** existing caller-selected, bounded file reading; no new network or target-execution authority. ## Author readiness Human owner: @jaelliot - [x] I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work. - [x] I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps. - [x] I declare this PR ready for initial maintainer review. ## Before merge - [x] This PR addresses a concrete problem and follows up on #5107. - [x] Scope is limited to ordinary file input without new target authority. - [x] The PR has one focused outcome and a Conventional Commit title. - [x] Related issue #5107 is linked. - [x] Tests cover changed observable behavior and the meaningful missing-file failure. - [x] Owning docs are updated; schema and generated metadata changes are unnecessary. - [x] User-visible CLI behavior and representative failure output are described above. - [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>
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#6782
No description provided.