[GH-ISSUE #3375] [Bug] Repeated process captures create a duplicate obligation definition #1240

Closed
opened 2026-10-16 21:03:13 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @coygeek on GitHub (Oct 14, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/3375

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Evidence, artifacts, or reconstruction

Observed behavior

Adding two ordinary capture-process results for the same executable and scenario to an Evidence bundle causes rea build-reconstruction-obligation-ledger to report duplicate-definition on the generated process obligation. The bundle has two distinct, authenticated observation records and no reviewed obligation definitions. The single-capture control has the same obligation ID without that diagnostic. Repeated observations therefore create an extra closure blocker because the same generated claim was observed twice.

Both process captures completed successfully, printed the selected fixed string, and reported completed cleanup. Both ledger requests succeeded. Their executable and scenario commitments match, and their Evidence IDs differ. The combined request returns one generated obligation with two authority references and the additional duplicate-definition diagnostic.

Both observed ledgers are already unknown because process captures retain unavailable-authority facts. The defect is the extra duplicate-definition blocker; the reproduction does not establish that one of these captures alone closed the lifecycle obligation.

Reproduction

  1. Start from a clean checkout of morluto/rea at 8dde6370d0809ad04cda3342d4e6f290f48aa063. Install the locked dependencies and build the runtime from the repository root.
npm ci
npm run build:cached
  1. Use a supported macOS or Linux process-capture environment with its native PTY backend and host process-inspection prerequisites. Run the following commands from the repository root. They create every input inline, capture the selected Node.js executable twice while it prints a fixed string, and build single-capture and repeated-capture ledger requests.
export REPRO_DIR="${REPRO_DIR:-$(mktemp -d)}"
mkdir -p "$REPRO_DIR/home"
node --input-type=module - <<'JS'
import fs from 'node:fs';
fs.writeFileSync(`${process.env.REPRO_DIR}/scenario.json`, JSON.stringify({
  executable: process.execPath,
  arguments: ['-e', 'console.log("sample")'],
  working_directory: process.env.REPRO_DIR,
  timeout_ms: 5000
}));
JS
HOME="$REPRO_DIR/home" node scripts/rea.mjs capture-process \
  "$REPRO_DIR/scenario.json" --json > "$REPRO_DIR/capture-one.json"
HOME="$REPRO_DIR/home" node scripts/rea.mjs capture-process \
  "$REPRO_DIR/scenario.json" --json > "$REPRO_DIR/capture-two.json"
node --input-type=module - <<'JS'
import fs from 'node:fs';
import { createEvidenceBundle } from './dist/domain/evidenceBundle.js';
const one = JSON.parse(fs.readFileSync(`${process.env.REPRO_DIR}/capture-one.json`));
const two = JSON.parse(fs.readFileSync(`${process.env.REPRO_DIR}/capture-two.json`));
console.log(JSON.stringify({ distinct_records: one.evidence_id !== two.evidence_id,
  same_executable: one.normalized_result.manifest.executable_sha256 ===
    two.normalized_result.manifest.executable_sha256,
  same_scenario: one.normalized_result.manifest.full_scenario_sha256 ===
    two.normalized_result.manifest.full_scenario_sha256 }));
for (const [name, records] of [['single', [one]], ['repeated', [one, two]]]) {
  fs.writeFileSync(`${process.env.REPRO_DIR}/${name}-request.json`, JSON.stringify({
    evidence_bundle: createEvidenceBundle(records), reviewed_obligations: [],
    manifest: { bindings: [], contradictions: [] }
  }));
}
JS
for variant in single repeated; do
  HOME="$REPRO_DIR/home" node scripts/rea.mjs build-reconstruction-obligation-ledger \
    "$REPRO_DIR/$variant-request.json" --json > "$REPRO_DIR/$variant-ledger.json"
done
node --input-type=module - <<'JS'
import fs from 'node:fs';
const ledgers = ['single', 'repeated'].map(name => JSON.parse(
  fs.readFileSync(`${process.env.REPRO_DIR}/${name}-ledger.json`)).normalized_result);
console.log(JSON.stringify({ same_obligation_id:
  ledgers[0].obligations[0].obligation_id === ledgers[1].obligations[0].obligation_id,
  single_duplicate_definition: ledgers[0].obligations[0].diagnostics.some(
    d => d.code === 'duplicate-definition'),
  repeated_duplicate_definition: ledgers[1].obligations[0].diagnostics.some(
    d => d.code === 'duplicate-definition'),
  repeated_authority_references: ledgers[1].obligations[0].authority_references.length }, null, 2));
JS
  1. Compare the printed results. The captures have distinct Evidence IDs and matching executable and full-scenario commitments. Both ledgers retain the same obligation ID; only the repeated-capture ledger reports duplicate-definition, and it retains two authority references.

Expected behavior

Two distinct observations of the same process scenario should contribute Evidence to the same generated lifecycle obligation without inventing a duplicate claim definition. Real duplicate reviewed definitions must still remain closure blockers. Other capture uncertainty and missing-proof diagnostics must remain visible in both requests.

docs/reconstruction-obligation-ledgers.md:47 directs callers to use an exported session Evidence bundle and says process capture records generate conservative candidates. The opening contract at docs/reconstruction-obligation-ledgers.md:10 distinguishes candidate obligations from duplicate definitions that block closure. The Compare two captures section at docs/process-capture.md:68 documents repeated scenario observations with their own Evidence commitments.

Impact and scope

P2, supported. Normal repeated observations produce a spurious reconstruction closure blocker. This affects bundles containing more than one capture of the same executable and full scenario; distinct scenarios are not shown to fail. The reproduced ledgers remain unknown for independently valid unavailable-authority facts, so this result does not establish otherwise complete reconstruction closure.

A workaround is available: keep the original complete Evidence bundle and build a separate ledger input using one representative capture per executable and full scenario. The executed single-capture control avoids the duplicate-definition diagnostic while retaining the independently valid uncertainty diagnostics.

REA version

6.4.0 (main at 8dde6370d0)

Runtime and platform

Node.js v26.10.0, macOS 27.0.1. The observed runs used the native PTY process-capture backend and the macOS process-inspection helper. Architecture was not recorded.

Target and artifact context

The selected Node.js executable runs console.log("sample") twice under the same scenario with a 5000 ms timeout. Two distinct authenticated process-capture records form the repeated Evidence bundle. Both requests have an empty reviewed_obligations array and a manifest with empty bindings and contradictions. The single-capture request is the discriminating control.

Interface

CLI

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence

The locally reproduced public CLI control and repeated-capture requests produced:

{"distinct_records":true,"same_executable":true,"same_scenario":true}
{
  "same_obligation_id": true,
  "single_duplicate_definition": false,
  "repeated_duplicate_definition": true,
  "repeated_authority_references": 2
}

The reproduction was locally executed and reported as complete.

Typed outcome or recovery expected

Repeat the two captures and both ledger requests. They must retain one stable lifecycle obligation ID, preserve both observation references, and produce no duplicate-definition diagnostic solely because the observation repeated. Preserve the other uncertainty diagnostics. Separately supply two reviewed definitions with the same obligation ID and verify that actual duplicate definitions still prevent verification. The single-capture control must continue to avoid the spurious diagnostic.

Analysis or suspected cause

Source-derived reasoning: src/application/ReconstructionObligationCandidates.ts:416 increments the definition count when merging observations into an existing candidate. src/application/ReconstructionObligationLedgerEvaluation.ts:180 then emits the duplicate-definition diagnostic when that count exceeds one. This conflates repeated observations with duplicate claim definitions; the CLI results above establish the additional diagnostic, while this explanation comes from source inspection.

Additional context

Related open report #3005 concerns MCP fixture-authority admission and unknown-update revision integrity; this report concerns an extra duplicate-definition diagnostic from authenticated repeated process observations.

Related open report #3219 concerns error classification for non-canonical bundle ordering; this report uses bundles created by createEvidenceBundle and successfully returns ledgers with an incorrect per-obligation diagnostic.

Related completed feature #405 introduced reconstruction obligation ledgers and fail-closed duplicate ownership; this report identifies repeated observations counted as duplicate definitions rather than an intentional duplicate ownership check.

Related completed report #2622 concerns environment compatibility across imported multi-source process comparisons; this report concerns merging process observations into a generated obligation and does not perform comparison verification.

Related open report #3354 concerns missing transitive dependencies in reconstruction coverage evaluation; this report concerns a spurious duplicate-definition diagnostic in obligation-ledger construction.

Related completed report #796 concerns application-graph unknown nodes omitted from candidate qualification; this report concerns repeated process observations counted as duplicate claim definitions.

Related completed feature #406 defines broad reconstruction readiness conformance with repeated scenarios; this report identifies a specific definition-counting defect in generated process obligations.

Originally created by @coygeek on GitHub (Oct 14, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/3375 ### Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ### Area Evidence, artifacts, or reconstruction ### Observed behavior Adding two ordinary `capture-process` results for the same executable and scenario to an Evidence bundle causes `rea build-reconstruction-obligation-ledger` to report `duplicate-definition` on the generated process obligation. The bundle has two distinct, authenticated observation records and no reviewed obligation definitions. The single-capture control has the same obligation ID without that diagnostic. Repeated observations therefore create an extra closure blocker because the same generated claim was observed twice. Both process captures completed successfully, printed the selected fixed string, and reported completed cleanup. Both ledger requests succeeded. Their executable and scenario commitments match, and their Evidence IDs differ. The combined request returns one generated obligation with two authority references and the additional `duplicate-definition` diagnostic. Both observed ledgers are already unknown because process captures retain unavailable-authority facts. The defect is the extra duplicate-definition blocker; the reproduction does not establish that one of these captures alone closed the lifecycle obligation. ### Reproduction 1. Start from a clean checkout of `morluto/rea` at `8dde6370d0809ad04cda3342d4e6f290f48aa063`. Install the locked dependencies and build the runtime from the repository root. ```sh npm ci npm run build:cached ``` 2. Use a supported macOS or Linux process-capture environment with its native PTY backend and host process-inspection prerequisites. Run the following commands from the repository root. They create every input inline, capture the selected Node.js executable twice while it prints a fixed string, and build single-capture and repeated-capture ledger requests. ```sh export REPRO_DIR="${REPRO_DIR:-$(mktemp -d)}" mkdir -p "$REPRO_DIR/home" node --input-type=module - <<'JS' import fs from 'node:fs'; fs.writeFileSync(`${process.env.REPRO_DIR}/scenario.json`, JSON.stringify({ executable: process.execPath, arguments: ['-e', 'console.log("sample")'], working_directory: process.env.REPRO_DIR, timeout_ms: 5000 })); JS HOME="$REPRO_DIR/home" node scripts/rea.mjs capture-process \ "$REPRO_DIR/scenario.json" --json > "$REPRO_DIR/capture-one.json" HOME="$REPRO_DIR/home" node scripts/rea.mjs capture-process \ "$REPRO_DIR/scenario.json" --json > "$REPRO_DIR/capture-two.json" node --input-type=module - <<'JS' import fs from 'node:fs'; import { createEvidenceBundle } from './dist/domain/evidenceBundle.js'; const one = JSON.parse(fs.readFileSync(`${process.env.REPRO_DIR}/capture-one.json`)); const two = JSON.parse(fs.readFileSync(`${process.env.REPRO_DIR}/capture-two.json`)); console.log(JSON.stringify({ distinct_records: one.evidence_id !== two.evidence_id, same_executable: one.normalized_result.manifest.executable_sha256 === two.normalized_result.manifest.executable_sha256, same_scenario: one.normalized_result.manifest.full_scenario_sha256 === two.normalized_result.manifest.full_scenario_sha256 })); for (const [name, records] of [['single', [one]], ['repeated', [one, two]]]) { fs.writeFileSync(`${process.env.REPRO_DIR}/${name}-request.json`, JSON.stringify({ evidence_bundle: createEvidenceBundle(records), reviewed_obligations: [], manifest: { bindings: [], contradictions: [] } })); } JS for variant in single repeated; do HOME="$REPRO_DIR/home" node scripts/rea.mjs build-reconstruction-obligation-ledger \ "$REPRO_DIR/$variant-request.json" --json > "$REPRO_DIR/$variant-ledger.json" done node --input-type=module - <<'JS' import fs from 'node:fs'; const ledgers = ['single', 'repeated'].map(name => JSON.parse( fs.readFileSync(`${process.env.REPRO_DIR}/${name}-ledger.json`)).normalized_result); console.log(JSON.stringify({ same_obligation_id: ledgers[0].obligations[0].obligation_id === ledgers[1].obligations[0].obligation_id, single_duplicate_definition: ledgers[0].obligations[0].diagnostics.some( d => d.code === 'duplicate-definition'), repeated_duplicate_definition: ledgers[1].obligations[0].diagnostics.some( d => d.code === 'duplicate-definition'), repeated_authority_references: ledgers[1].obligations[0].authority_references.length }, null, 2)); JS ``` 3. Compare the printed results. The captures have distinct Evidence IDs and matching executable and full-scenario commitments. Both ledgers retain the same obligation ID; only the repeated-capture ledger reports `duplicate-definition`, and it retains two authority references. ### Expected behavior Two distinct observations of the same process scenario should contribute Evidence to the same generated lifecycle obligation without inventing a duplicate claim definition. Real duplicate reviewed definitions must still remain closure blockers. Other capture uncertainty and missing-proof diagnostics must remain visible in both requests. `docs/reconstruction-obligation-ledgers.md:47` directs callers to use an exported session Evidence bundle and says process capture records generate conservative candidates. The opening contract at `docs/reconstruction-obligation-ledgers.md:10` distinguishes candidate obligations from duplicate definitions that block closure. The Compare two captures section at `docs/process-capture.md:68` documents repeated scenario observations with their own Evidence commitments. ### Impact and scope P2, supported. Normal repeated observations produce a spurious reconstruction closure blocker. This affects bundles containing more than one capture of the same executable and full scenario; distinct scenarios are not shown to fail. The reproduced ledgers remain unknown for independently valid unavailable-authority facts, so this result does not establish otherwise complete reconstruction closure. A workaround is available: keep the original complete Evidence bundle and build a separate ledger input using one representative capture per executable and full scenario. The executed single-capture control avoids the `duplicate-definition` diagnostic while retaining the independently valid uncertainty diagnostics. ### REA version 6.4.0 (main at 8dde6370d0809ad04cda3342d4e6f290f48aa063) ### Runtime and platform Node.js v26.10.0, macOS 27.0.1. The observed runs used the native PTY process-capture backend and the macOS process-inspection helper. Architecture was not recorded. ### Target and artifact context The selected Node.js executable runs `console.log("sample")` twice under the same scenario with a 5000 ms timeout. Two distinct authenticated process-capture records form the repeated Evidence bundle. Both requests have an empty `reviewed_obligations` array and a manifest with empty bindings and contradictions. The single-capture request is the discriminating control. ### Interface CLI ### Earliest failure stage Native analysis or reconstruction ### Relevant output or evidence The locally reproduced public CLI control and repeated-capture requests produced: ```text {"distinct_records":true,"same_executable":true,"same_scenario":true} { "same_obligation_id": true, "single_duplicate_definition": false, "repeated_duplicate_definition": true, "repeated_authority_references": 2 } ``` The reproduction was locally executed and reported as complete. ### Typed outcome or recovery expected Repeat the two captures and both ledger requests. They must retain one stable lifecycle obligation ID, preserve both observation references, and produce no `duplicate-definition` diagnostic solely because the observation repeated. Preserve the other uncertainty diagnostics. Separately supply two reviewed definitions with the same obligation ID and verify that actual duplicate definitions still prevent verification. The single-capture control must continue to avoid the spurious diagnostic. ### Analysis or suspected cause Source-derived reasoning: `src/application/ReconstructionObligationCandidates.ts:416` increments the definition count when merging observations into an existing candidate. `src/application/ReconstructionObligationLedgerEvaluation.ts:180` then emits the `duplicate-definition` diagnostic when that count exceeds one. This conflates repeated observations with duplicate claim definitions; the CLI results above establish the additional diagnostic, while this explanation comes from source inspection. ### Additional context Related open report [#3005](https://github.com/morluto/rea/issues/3005) concerns MCP fixture-authority admission and unknown-update revision integrity; this report concerns an extra duplicate-definition diagnostic from authenticated repeated process observations. Related open report [#3219](https://github.com/morluto/rea/issues/3219) concerns error classification for non-canonical bundle ordering; this report uses bundles created by `createEvidenceBundle` and successfully returns ledgers with an incorrect per-obligation diagnostic. Related completed feature [#405](https://github.com/morluto/rea/issues/405) introduced reconstruction obligation ledgers and fail-closed duplicate ownership; this report identifies repeated observations counted as duplicate definitions rather than an intentional duplicate ownership check. Related completed report [#2622](https://github.com/morluto/rea/issues/2622) concerns environment compatibility across imported multi-source process comparisons; this report concerns merging process observations into a generated obligation and does not perform comparison verification. Related open report [#3354](https://github.com/morluto/rea/issues/3354) concerns missing transitive dependencies in reconstruction coverage evaluation; this report concerns a spurious duplicate-definition diagnostic in obligation-ledger construction. Related completed report [#796](https://github.com/morluto/rea/issues/796) concerns application-graph unknown nodes omitted from candidate qualification; this report concerns repeated process observations counted as duplicate claim definitions. Related completed feature [#406](https://github.com/morluto/rea/issues/406) defines broad reconstruction readiness conformance with repeated scenarios; this report identifies a specific definition-counting defect in generated process obligations.
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#1240
No description provided.