[GH-ISSUE #3370] [Bug] Reconstruction obligation ledgers lose semantic unknowns and report complete coverage #1238

Closed
opened 2026-10-16 21:03:11 +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/3370

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

rea build-reconstruction-obligation-ledger loses unresolved semantic facts from authentic JavaScript application Evidence. An analysis with an unresolved dynamic event name reports semantic coverage as unknown. The ledger creates an event obligation for the affected semantic node but gives it no residual unknowns, reports no residual unknown IDs or limitations, and declares its coverage complete.

Both public CLI commands succeeded. The original semantic graph contains 11 unknowns, including one attached to the exact semantic node used by the event obligation. Other missing-proof diagnostics keep this particular request open because owners and original cases are missing, but the unresolved source fact itself no longer participates in closure or appears in the ledger's unknown report. The observed ledger remains open; this reproduction does not establish a ready result.

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. Run this block from the repository root. It creates every input inline, analyzes the application, constructs an authenticated Evidence bundle, and builds the ledger. The sample application is read as inert source and is never executed.
export REPRO_DIR="${REPRO_DIR:-$(mktemp -d)}"
mkdir -p "$REPRO_DIR/home" "$REPRO_DIR/app"
cat > "$REPRO_DIR/app/package.json" <<'JSON'
{"name":"sample-app","version":"1.0.0","main":"main.js"}
JSON
cat > "$REPRO_DIR/app/main.js" <<'JS'
const events = require('node:events');
const bus = new events.EventEmitter();
bus.on(process.argv[2], () => console.log('done'));
JS
HOME="$REPRO_DIR/home" node scripts/rea.mjs analyze-javascript-application \
  "$REPRO_DIR/app" --json > "$REPRO_DIR/application.json"
node --input-type=module - <<'JS'
import fs from 'node:fs';
import { createEvidenceBundle } from './dist/domain/evidenceBundle.js';
const application = JSON.parse(fs.readFileSync(`${process.env.REPRO_DIR}/application.json`));
fs.writeFileSync(`${process.env.REPRO_DIR}/request.json`, JSON.stringify({
  evidence_bundle: createEvidenceBundle([application]), reviewed_obligations: [],
  manifest: { bindings: [], contradictions: [] }
}));
JS
HOME="$REPRO_DIR/home" node scripts/rea.mjs build-reconstruction-obligation-ledger \
  "$REPRO_DIR/request.json" --json > "$REPRO_DIR/ledger.json"
node --input-type=module - <<'JS'
import fs from 'node:fs';
const a = JSON.parse(fs.readFileSync(`${process.env.REPRO_DIR}/application.json`)).normalized_result;
const l = JSON.parse(fs.readFileSync(`${process.env.REPRO_DIR}/ledger.json`)).normalized_result;
const unknown = a.semantic_graph.unknowns.find(u => u.family === 'event');
const obligation = l.obligations.find(o => o.target.semantic_node_id === unknown.node_id);
console.log(JSON.stringify({ application_coverage: a.graph.coverage.status,
  semantic_coverage: a.semantic_graph.coverage.status,
  semantic_unknown_count: a.semantic_graph.unknowns.length,
  event_unknown: unknown.detail, matching_obligation_family: obligation.family,
  obligation_unknowns: obligation.residual_unknown_ids,
  ledger_status: l.status, ledger_coverage: l.coverage.status,
  ledger_unknowns: l.reports.residual_unknown_ids, ledger_limitations: l.limitations }, null, 2));
JS
  1. Compare the source semantic coverage and event unknown with the matching obligation and the ledger reports. The output below reports unknown semantic coverage, 11 source unknowns, and an event obligation with an empty residual list, while ledger coverage is complete and its residual-unknown report and limitations are empty.

Expected behavior

The ledger must preserve the unresolved dynamic event fact associated with the event obligation and account for the source semantic graph's incomplete coverage. The unknown may be represented through obligation diagnostics, the residual-unknown report, or explicit ledger limitations, but it must remain visible and prevent a complete coverage claim while unresolved.

AGENTS.md:19 requires omission, uncertainty, and source evidence to survive boundaries. docs/reconstruction-obligation-ledgers.md:16 states that residual unknowns keep closure open or failed. The Define the contract section at docs/tool-design.md:55 requires missing coverage to remain unknown, and the Implement and evaluate section at docs/tool-design.md:80 requires completeness to follow examined records and exhaustiveness.

Impact and scope

P2, supported. Reconstruction planning loses a concrete unresolved event boundary and gives misleading complete coverage for a supported application input. The reproduced ledger is open for other reasons; false readiness after supplying further proof was not tested.

A workaround is available: inspect the source semantic graph's coverage and unknown list alongside the ledger and retain the unresolved facts separately. The original application Evidence still contains all 11 unknowns and was not modified by ledger generation.

REA version

6.4.0 (main at 8dde6370d0)

Runtime and platform

Node.js v26.10.0, macOS 27.0.1. Architecture was not recorded in the reproduction evidence. The built CLI reported version 6.4.0. The reproduction uses the built-in static JavaScript analyzer and requires no external analysis engine.

Target and artifact context

A JavaScript application directory containing the inline package.json and main.js above, with a Node.js EventEmitter listener whose event name is process.argv[2]. The ledger request uses authentic application Evidence wrapped by createEvidenceBundle, an empty reviewed_obligations list, and an empty manifest containing bindings and contradictions lists. No target code executes.

Interface

CLI

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence

The locally reproduced commands succeeded and produced this comparison:

{
  "application_coverage": "complete",
  "semantic_coverage": "unknown",
  "semantic_unknown_count": 11,
  "event_unknown": "Dynamic on event name remains unresolved.",
  "matching_obligation_family": "event",
  "obligation_unknowns": [],
  "ledger_status": "open",
  "ledger_coverage": "complete",
  "ledger_unknowns": [],
  "ledger_limitations": []
}

The reproduction was locally executed and complete. The event unknown belongs to the exact semantic node targeted by the generated event obligation.

Typed outcome or recovery expected

Repeat the sample analysis and ledger request. The matching event obligation's unresolved fact must remain represented, and the ledger must account for semantic coverage being unknown without claiming complete coverage. Keep all otherwise valid generated obligations. Use an authenticated application Evidence control with complete semantic coverage and no semantic unknowns to verify that complete source coverage can still produce complete ledger coverage.

Analysis or suspected cause

Source-derived reasoning: src/application/ReconstructionObligationCandidates.ts:125 derives obligations from semantic nodes without their unknown frontiers. Its coverage check at src/application/ReconstructionObligationCandidates.ts:155 examines only the application graph. Generated candidates initialize their residual unknown lists to empty. These source observations explain the missing semantic uncertainty; the CLI comparison above is the observed failure.

Additional context

Related completed report #796 fixed uncertainty loss for structural application-graph nodes whose kind is unknown; this report concerns the separate semantic graph's unknowns and unknown coverage during ledger construction.

Related completed report #2576 fixed semantic-graph validation accepting unresolved frontiers under complete coverage; this reproduction's semantic graph correctly reports unknown coverage before the ledger loses it.

Related open report #3219 concerns error classification for non-canonical Evidence bundles; this reproduction uses authentic analyzer Evidence and succeeds before losing semantic uncertainty.

Related open report #3005 concerns MCP fixture authority admission and unknown revision updates; this reproduction concerns static JavaScript Evidence projected through the CLI ledger command.

Related open report #3354 concerns missing transitive dependencies in reconstruction-coverage evaluation; this report concerns semantic unknown retention in obligation-ledger generation.

Related completed feature #405 introduced the conservative reconstruction obligation ledger and residual-unknown closure requirements.

Originally created by @coygeek on GitHub (Oct 14, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/3370 ### 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 `rea build-reconstruction-obligation-ledger` loses unresolved semantic facts from authentic JavaScript application Evidence. An analysis with an unresolved dynamic event name reports semantic coverage as `unknown`. The ledger creates an event obligation for the affected semantic node but gives it no residual unknowns, reports no residual unknown IDs or limitations, and declares its coverage complete. Both public CLI commands succeeded. The original semantic graph contains 11 unknowns, including one attached to the exact semantic node used by the event obligation. Other missing-proof diagnostics keep this particular request open because owners and original cases are missing, but the unresolved source fact itself no longer participates in closure or appears in the ledger's unknown report. The observed ledger remains `open`; this reproduction does not establish a `ready` result. ### 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. Run this block from the repository root. It creates every input inline, analyzes the application, constructs an authenticated Evidence bundle, and builds the ledger. The sample application is read as inert source and is never executed. ```sh export REPRO_DIR="${REPRO_DIR:-$(mktemp -d)}" mkdir -p "$REPRO_DIR/home" "$REPRO_DIR/app" cat > "$REPRO_DIR/app/package.json" <<'JSON' {"name":"sample-app","version":"1.0.0","main":"main.js"} JSON cat > "$REPRO_DIR/app/main.js" <<'JS' const events = require('node:events'); const bus = new events.EventEmitter(); bus.on(process.argv[2], () => console.log('done')); JS HOME="$REPRO_DIR/home" node scripts/rea.mjs analyze-javascript-application \ "$REPRO_DIR/app" --json > "$REPRO_DIR/application.json" node --input-type=module - <<'JS' import fs from 'node:fs'; import { createEvidenceBundle } from './dist/domain/evidenceBundle.js'; const application = JSON.parse(fs.readFileSync(`${process.env.REPRO_DIR}/application.json`)); fs.writeFileSync(`${process.env.REPRO_DIR}/request.json`, JSON.stringify({ evidence_bundle: createEvidenceBundle([application]), reviewed_obligations: [], manifest: { bindings: [], contradictions: [] } })); JS HOME="$REPRO_DIR/home" node scripts/rea.mjs build-reconstruction-obligation-ledger \ "$REPRO_DIR/request.json" --json > "$REPRO_DIR/ledger.json" node --input-type=module - <<'JS' import fs from 'node:fs'; const a = JSON.parse(fs.readFileSync(`${process.env.REPRO_DIR}/application.json`)).normalized_result; const l = JSON.parse(fs.readFileSync(`${process.env.REPRO_DIR}/ledger.json`)).normalized_result; const unknown = a.semantic_graph.unknowns.find(u => u.family === 'event'); const obligation = l.obligations.find(o => o.target.semantic_node_id === unknown.node_id); console.log(JSON.stringify({ application_coverage: a.graph.coverage.status, semantic_coverage: a.semantic_graph.coverage.status, semantic_unknown_count: a.semantic_graph.unknowns.length, event_unknown: unknown.detail, matching_obligation_family: obligation.family, obligation_unknowns: obligation.residual_unknown_ids, ledger_status: l.status, ledger_coverage: l.coverage.status, ledger_unknowns: l.reports.residual_unknown_ids, ledger_limitations: l.limitations }, null, 2)); JS ``` 3. Compare the source semantic coverage and event unknown with the matching obligation and the ledger reports. The output below reports unknown semantic coverage, 11 source unknowns, and an event obligation with an empty residual list, while ledger coverage is complete and its residual-unknown report and limitations are empty. ### Expected behavior The ledger must preserve the unresolved dynamic event fact associated with the event obligation and account for the source semantic graph's incomplete coverage. The unknown may be represented through obligation diagnostics, the residual-unknown report, or explicit ledger limitations, but it must remain visible and prevent a complete coverage claim while unresolved. `AGENTS.md:19` requires omission, uncertainty, and source evidence to survive boundaries. `docs/reconstruction-obligation-ledgers.md:16` states that residual unknowns keep closure open or failed. The Define the contract section at `docs/tool-design.md:55` requires missing coverage to remain unknown, and the Implement and evaluate section at `docs/tool-design.md:80` requires completeness to follow examined records and exhaustiveness. ### Impact and scope P2, supported. Reconstruction planning loses a concrete unresolved event boundary and gives misleading complete coverage for a supported application input. The reproduced ledger is open for other reasons; false readiness after supplying further proof was not tested. A workaround is available: inspect the source semantic graph's coverage and unknown list alongside the ledger and retain the unresolved facts separately. The original application Evidence still contains all 11 unknowns and was not modified by ledger generation. ### REA version 6.4.0 (main at 8dde6370d0809ad04cda3342d4e6f290f48aa063) ### Runtime and platform Node.js v26.10.0, macOS 27.0.1. Architecture was not recorded in the reproduction evidence. The built CLI reported version 6.4.0. The reproduction uses the built-in static JavaScript analyzer and requires no external analysis engine. ### Target and artifact context A JavaScript application directory containing the inline `package.json` and `main.js` above, with a Node.js EventEmitter listener whose event name is `process.argv[2]`. The ledger request uses authentic application Evidence wrapped by `createEvidenceBundle`, an empty `reviewed_obligations` list, and an empty manifest containing `bindings` and `contradictions` lists. No target code executes. ### Interface CLI ### Earliest failure stage Native analysis or reconstruction ### Relevant output or evidence The locally reproduced commands succeeded and produced this comparison: ```text { "application_coverage": "complete", "semantic_coverage": "unknown", "semantic_unknown_count": 11, "event_unknown": "Dynamic on event name remains unresolved.", "matching_obligation_family": "event", "obligation_unknowns": [], "ledger_status": "open", "ledger_coverage": "complete", "ledger_unknowns": [], "ledger_limitations": [] } ``` The reproduction was locally executed and complete. The event unknown belongs to the exact semantic node targeted by the generated event obligation. ### Typed outcome or recovery expected Repeat the sample analysis and ledger request. The matching event obligation's unresolved fact must remain represented, and the ledger must account for semantic coverage being unknown without claiming complete coverage. Keep all otherwise valid generated obligations. Use an authenticated application Evidence control with complete semantic coverage and no semantic unknowns to verify that complete source coverage can still produce complete ledger coverage. ### Analysis or suspected cause Source-derived reasoning: `src/application/ReconstructionObligationCandidates.ts:125` derives obligations from semantic nodes without their unknown frontiers. Its coverage check at `src/application/ReconstructionObligationCandidates.ts:155` examines only the application graph. Generated candidates initialize their residual unknown lists to empty. These source observations explain the missing semantic uncertainty; the CLI comparison above is the observed failure. ### Additional context Related completed report [#796](https://github.com/morluto/rea/issues/796) fixed uncertainty loss for structural application-graph nodes whose kind is unknown; this report concerns the separate semantic graph's unknowns and unknown coverage during ledger construction. Related completed report [#2576](https://github.com/morluto/rea/issues/2576) fixed semantic-graph validation accepting unresolved frontiers under complete coverage; this reproduction's semantic graph correctly reports unknown coverage before the ledger loses it. Related open report [#3219](https://github.com/morluto/rea/issues/3219) concerns error classification for non-canonical Evidence bundles; this reproduction uses authentic analyzer Evidence and succeeds before losing semantic uncertainty. Related open report [#3005](https://github.com/morluto/rea/issues/3005) concerns MCP fixture authority admission and unknown revision updates; this reproduction concerns static JavaScript Evidence projected through the CLI ledger command. Related open report [#3354](https://github.com/morluto/rea/issues/3354) concerns missing transitive dependencies in reconstruction-coverage evaluation; this report concerns semantic unknown retention in obligation-ledger generation. Related completed feature [#405](https://github.com/morluto/rea/issues/405) introduced the conservative reconstruction obligation ledger and residual-unknown closure requirements.
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#1238
No description provided.