[PR #1080] [MERGED] fix(process): name the reason two captures cannot be compared #2628

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

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/1080
Author: @kaoru0822-kitauji
Created: 10/8/2026
Status: ✅ Merged
Merged: 10/8/2026
Merged by: @N0zoM1z0

Base: main ← Head: fix/process-comparison-diagnostics


📝 Commits (5)

  • ef59138 fix(process): name the reason two captures cannot be compared
  • 6528fab fix(process): report CLI trace-spec issues under the MCP input path
  • 3ba3164 Merge remote-tracking branch 'origin/main' into fix/process-comparison-diagnostics
  • 429963b fix(process): name the side and constraint for unusable capture Evidence
  • 6a6007e Merge remote-tracking branch 'origin/main' into fix/process-comparison-diagnostics

📊 Changes

7 files changed (+381 additions, -75 deletions)

View changed files

📝 docs/process-capture.md (+7 -2)
📝 src/application/process/ProcessCli.ts (+11 -6)
📝 src/domain/process/processCapture.validation.test.ts (+24 -2)
📝 src/domain/process/processComparison.ts (+51 -10)
📝 src/server/registerProcessComparisonTool.ts (+75 -54)
📝 src/server/runDerivedOperation.ts (+3 -1)
➕ tests/boundary/mcp/processComparisonDiagnosticsMcp.test.ts (+210 -0)

📄 Description

Problem

compare_process_captures and rea compare-process-captures refuse to compare captures whose comparison contracts differ, or (MCP only) captures older than max_capture_age_ms. Refusing is correct, but the reason never reached the caller.

I reproduced this on macOS 26 with two real captures of /bin/sh scenarios that differed only in their working directory and observation path:

  • CLI: the domain TypeError reached the generic fallback:
    {"error":"Process command failed","category":"execution_failure","message":"Process command could not complete. Check the input files and run `rea doctor`, then try again."}
    
    rea doctor is unrelated to this failure.
  • MCP: runDerivedOperation wraps any thrown error in new AnalysisInputError(operation, { cause }) with no issues. The caller saw "Analysis input is invalid. Check the arguments and try again." with nothing identifying which argument was wrong.

Change

  • assertComparable now throws an AnalysisInputError with one issue:
    • Contract mismatch: path: ["right"], reason: "invalid_value", a message naming the differing top-level fields, and those fields in expected. Each capture manifest already stores its full comparison_contract; fields are compared by canonical JSON.
    • Stale capture: path: ["max_capture_age_ms"], reason: "out_of_range", naming each stale side with its completed_at and age.
  • runDerivedOperation returns an AnalysisInputError thrown by the computation unchanged, as it already did for AnalysisCancelledError. Other derived tools keep their current behavior unless they throw typed input errors.
  • The CLI's optional trace-specification file reported its issues under operation compare-process-captures with root-relative paths such as ["events"], while MCP reports compare_process_captures and trace_spec.events. The CLI now uses the MCP operation name and the trace_spec prefix.
  • Adjacent failures now name their side and constraint too. Over MCP, Evidence from another workflow, tampered Evidence and an invalid capture result all became "Evidence is invalid or has changed", and the CLI said only "Capture evidence is malformed". Each side is now parsed separately:
    • Evidence from another workflow is an invalid_request issue on left/right naming the operation and predicate it has.
    • Tampered Evidence and invalid capture results stay evidence_integrity_mismatch, and the message now carries the validation detail, for example "The right Evidence failed validation (Evidence semantic identifier does not match its record)". The CLI's malformed-capture message includes the same detail.
  • docs/process-capture.md now says what the comparison contract covers: working directory, explicit environment, observation paths, terminal, scripted events, timeouts, limits and normalization. The executable and arguments may differ.

Sanitized result for the real reproduction:

{"code":"invalid_request","category":"invalid_input","details":{"operation":"compare_process_captures","issues":[{"path":["right"],"reason":"invalid_value","message":"Process captures have incompatible comparison contracts; these scenario fields differ: filesystem_observation_paths, working_directory. Capture both scenarios with the same values for these fields, then compare them.","expected":["filesystem_observation_paths","working_directory"]}]}}

No schemas change.

Verification

  • npm run test:focused -- tests/boundary/mcp/processComparisonDiagnosticsMcp.test.ts src/domain/process/processCapture.validation.test.ts: covers MCP and the CLI workflow (contract mismatch) and MCP max_capture_age_ms. These assertions, plus the new MCP and CLI wrong-kind, tampered and invalid-result cases, fail with the source change reverted.
  • All 18 test files that reference process comparison, ProcessCli or runDerivedOperation: 118 passed. All MCP boundary tests: 197 passed, 2 skipped.
  • tests/boundary/cli/processCli.test.ts and processTraceAdaptersParity.test.ts still pass, including the real CLI capture workflow.
  • npm run check:fast, npm run docs:check
  • Ran the real rea capture-process twice on macOS 26.7.1 arm64, then rea compare-process-captures, which produced the output above.

No real Hopper or Ghidra verification was run, because this change does not touch those providers.

🤖 Generated with Claude Code


🔄 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/1080 **Author:** [@kaoru0822-kitauji](https://github.com/kaoru0822-kitauji) **Created:** 10/8/2026 **Status:** ✅ Merged **Merged:** 10/8/2026 **Merged by:** [@N0zoM1z0](https://github.com/N0zoM1z0) **Base:** `main` ← **Head:** `fix/process-comparison-diagnostics` --- ### 📝 Commits (5) - [`ef59138`](https://github.com/morluto/rea/commit/ef591383bf94a0eb34938a75bb00fe706c7237ae) fix(process): name the reason two captures cannot be compared - [`6528fab`](https://github.com/morluto/rea/commit/6528fab8d80125fb09183ce684225ceb976b5933) fix(process): report CLI trace-spec issues under the MCP input path - [`3ba3164`](https://github.com/morluto/rea/commit/3ba3164cb24a26601b243df723ad71e366e6424f) Merge remote-tracking branch 'origin/main' into fix/process-comparison-diagnostics - [`429963b`](https://github.com/morluto/rea/commit/429963bcfae1a0ceb4b8fea4fa3911f6cdd894a5) fix(process): name the side and constraint for unusable capture Evidence - [`6a6007e`](https://github.com/morluto/rea/commit/6a6007eea5807e9391663f89aaa0dfa33e30e854) Merge remote-tracking branch 'origin/main' into fix/process-comparison-diagnostics ### 📊 Changes **7 files changed** (+381 additions, -75 deletions) <details> <summary>View changed files</summary> 📝 `docs/process-capture.md` (+7 -2) 📝 `src/application/process/ProcessCli.ts` (+11 -6) 📝 `src/domain/process/processCapture.validation.test.ts` (+24 -2) 📝 `src/domain/process/processComparison.ts` (+51 -10) 📝 `src/server/registerProcessComparisonTool.ts` (+75 -54) 📝 `src/server/runDerivedOperation.ts` (+3 -1) ➕ `tests/boundary/mcp/processComparisonDiagnosticsMcp.test.ts` (+210 -0) </details> ### 📄 Description ## Problem `compare_process_captures` and `rea compare-process-captures` refuse to compare captures whose comparison contracts differ, or (MCP only) captures older than `max_capture_age_ms`. Refusing is correct, but the reason never reached the caller. I reproduced this on macOS 26 with two real captures of `/bin/sh` scenarios that differed only in their working directory and observation path: - **CLI:** the domain `TypeError` reached the generic fallback: ```json {"error":"Process command failed","category":"execution_failure","message":"Process command could not complete. Check the input files and run `rea doctor`, then try again."} ``` `rea doctor` is unrelated to this failure. - **MCP:** `runDerivedOperation` wraps any thrown error in `new AnalysisInputError(operation, { cause })` with no issues. The caller saw "Analysis input is invalid. Check the arguments and try again." with nothing identifying which argument was wrong. ## Change - `assertComparable` now throws an `AnalysisInputError` with one issue: - **Contract mismatch:** `path: ["right"]`, `reason: "invalid_value"`, a message naming the differing top-level fields, and those fields in `expected`. Each capture manifest already stores its full `comparison_contract`; fields are compared by canonical JSON. - **Stale capture:** `path: ["max_capture_age_ms"]`, `reason: "out_of_range"`, naming each stale side with its `completed_at` and age. - `runDerivedOperation` returns an `AnalysisInputError` thrown by the computation unchanged, as it already did for `AnalysisCancelledError`. Other derived tools keep their current behavior unless they throw typed input errors. - The CLI's optional trace-specification file reported its issues under operation `compare-process-captures` with root-relative paths such as `["events"]`, while MCP reports `compare_process_captures` and `trace_spec.events`. The CLI now uses the MCP operation name and the `trace_spec` prefix. - Adjacent failures now name their side and constraint too. Over MCP, Evidence from another workflow, tampered Evidence and an invalid capture result all became "Evidence is invalid or has changed", and the CLI said only "Capture evidence is malformed". Each side is now parsed separately: - Evidence from another workflow is an `invalid_request` issue on `left`/`right` naming the operation and predicate it has. - Tampered Evidence and invalid capture results stay `evidence_integrity_mismatch`, and the message now carries the validation detail, for example "The right Evidence failed validation (Evidence semantic identifier does not match its record)". The CLI's malformed-capture message includes the same detail. - `docs/process-capture.md` now says what the comparison contract covers: working directory, explicit environment, observation paths, terminal, scripted events, timeouts, limits and normalization. The executable and arguments may differ. Sanitized result for the real reproduction: ```json {"code":"invalid_request","category":"invalid_input","details":{"operation":"compare_process_captures","issues":[{"path":["right"],"reason":"invalid_value","message":"Process captures have incompatible comparison contracts; these scenario fields differ: filesystem_observation_paths, working_directory. Capture both scenarios with the same values for these fields, then compare them.","expected":["filesystem_observation_paths","working_directory"]}]}} ``` No schemas change. ## Verification - `npm run test:focused -- tests/boundary/mcp/processComparisonDiagnosticsMcp.test.ts src/domain/process/processCapture.validation.test.ts`: covers MCP and the CLI workflow (contract mismatch) and MCP `max_capture_age_ms`. These assertions, plus the new MCP and CLI wrong-kind, tampered and invalid-result cases, fail with the source change reverted. - All 18 test files that reference process comparison, `ProcessCli` or `runDerivedOperation`: 118 passed. All MCP boundary tests: 197 passed, 2 skipped. - `tests/boundary/cli/processCli.test.ts` and `processTraceAdaptersParity.test.ts` still pass, including the real CLI capture workflow. - `npm run check:fast`, `npm run docs:check` - Ran the real `rea capture-process` twice on macOS 26.7.1 arm64, then `rea compare-process-captures`, which produced the output above. No real Hopper or Ghidra verification was run, because this change does not touch those providers. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-17 21:08:23 +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#2628
No description provided.