[GH-ISSUE #796] Preserve uncertainty when complete application graphs contain admitted unknown nodes #346

Closed
opened 2026-10-15 18:24:09 +00:00 by bsakaguchi · 1 comment
Owner

Originally created by @zhukoff777 on GitHub (Oct 6, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/796

Summary

The reconstruction-obligation candidate generator can silently omit an admitted unknown application-graph node when graph coverage is marked complete.

This was reproduced against exact REA commit 6d1f39b250f8a1c6f924b1a6b9d26d56dff4beee using an external hosted execution probe.

The observed boundary is:

  • application graph coverage: complete
  • one obligation-bearing known node is present
  • an admitted unknown node is also present
  • unknown is absent from generated candidates
  • generation limitations are empty

This means structural coverage completeness can erase an unresolved semantic uncertainty from downstream qualification.

Evidence

Frozen REA source:

src/application/ReconstructionObligationCandidates.ts iterates graph nodes and does:

const candidatePolicy = applicationObligationPolicy(node.kind);
if (candidatePolicy === undefined) continue;

The same file only adds the generic generation limitation when:

if (source.graph.coverage.status !== "complete") {
  limitations.add(...);
}

The policy table in src/application/ReconstructionObligationPolicies.ts admits a partial application-node policy map; unknown/unmapped kinds have no policy.

The downstream ledger evaluator only adds the explicit zero-candidate protection when candidateCount === 0. Therefore a mixed graph with visible obligation-bearing candidates can carry an omitted unknown without that generic protection firing.

The readiness layer separately requires a non-empty, ready obligation ledger, so this report does not claim that the single mixed-vector run proves a false ready result. The demonstrated defect is the loss of the uncertainty frontier at candidate-generation/qualification.

Reproduction

Exact external source:

6d1f39b250f8a1c6f924b1a6b9d26d56dff4beee

Hosted execution:

  • repository: nz-genesis/ci-probe
  • workflow: REA Ledger Comparison
  • run: 37521295208
  • probe commit: 632bf24a153203cd1b3b456b27b7a958734d5c01
  • result: 8/8 probe vectors passed
  • mixed-vector observation:
MIXED_UNKNOWN_BOUNDARY {"graphCoverage":"complete","knownCandidateCount":6,"unknownPresent":false,"limitations":[],"ledgerStatus":"open"}

The probe expected explicit preservation of the unresolved member and independently checked the returned candidate set/limitations.

Why this matters

REA's own reconstruction/readiness documentation says that unknown, incomplete, unsupported and truncated evidence must remain explicit and that incomplete reconstruction must not aggregate to pass.

The ambiguity is semantic: perhaps complete is intentionally defined as "complete with respect to obligation-bearing semantic kinds", in which case the current behavior may be by design. However, the current source does not make that distinction explicit at the candidate-generation boundary.

Suggested remediation

Please consider one of these explicit contracts:

  1. Preserve an explicit generation limitation/unknown when an admitted graph member has no obligation policy, even when structural graph coverage is complete; or
  2. Define and enforce a schema-level distinction between structural coverage completeness and semantic/obligation coverage completeness, so that policy-less admitted members cannot disappear silently.

A regression test should cover a complete graph containing both:

  • at least one obligation-bearing known node; and
  • at least one admitted unknown/unmapped node.

Expected result: the unresolved member remains represented as an explicit uncertainty/limitation, or the graph contract explicitly proves that it is outside the qualification scope.

This report intentionally does not prescribe turning every unknown node into a reconstruction obligation. The minimum concern is loss of uncertainty at a downstream qualification boundary.

Originally created by @zhukoff777 on GitHub (Oct 6, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/796 ## Summary The reconstruction-obligation candidate generator can silently omit an admitted `unknown` application-graph node when graph coverage is marked `complete`. This was reproduced against exact REA commit `6d1f39b250f8a1c6f924b1a6b9d26d56dff4beee` using an external hosted execution probe. The observed boundary is: - application graph coverage: `complete` - one obligation-bearing known node is present - an admitted `unknown` node is also present - `unknown` is absent from generated candidates - generation limitations are empty This means structural coverage completeness can erase an unresolved semantic uncertainty from downstream qualification. ## Evidence Frozen REA source: `src/application/ReconstructionObligationCandidates.ts` iterates graph nodes and does: ```ts const candidatePolicy = applicationObligationPolicy(node.kind); if (candidatePolicy === undefined) continue; ``` The same file only adds the generic generation limitation when: ```ts if (source.graph.coverage.status !== "complete") { limitations.add(...); } ``` The policy table in `src/application/ReconstructionObligationPolicies.ts` admits a partial application-node policy map; unknown/unmapped kinds have no policy. The downstream ledger evaluator only adds the explicit zero-candidate protection when `candidateCount === 0`. Therefore a mixed graph with visible obligation-bearing candidates can carry an omitted unknown without that generic protection firing. The readiness layer separately requires a non-empty, ready obligation ledger, so this report does **not** claim that the single mixed-vector run proves a false `ready` result. The demonstrated defect is the loss of the uncertainty frontier at candidate-generation/qualification. ## Reproduction Exact external source: `6d1f39b250f8a1c6f924b1a6b9d26d56dff4beee` Hosted execution: - repository: `nz-genesis/ci-probe` - workflow: REA Ledger Comparison - run: `37521295208` - probe commit: `632bf24a153203cd1b3b456b27b7a958734d5c01` - result: 8/8 probe vectors passed - mixed-vector observation: ```text MIXED_UNKNOWN_BOUNDARY {"graphCoverage":"complete","knownCandidateCount":6,"unknownPresent":false,"limitations":[],"ledgerStatus":"open"} ``` The probe expected explicit preservation of the unresolved member and independently checked the returned candidate set/limitations. ## Why this matters REA's own reconstruction/readiness documentation says that unknown, incomplete, unsupported and truncated evidence must remain explicit and that incomplete reconstruction must not aggregate to pass. The ambiguity is semantic: perhaps `complete` is intentionally defined as "complete with respect to obligation-bearing semantic kinds", in which case the current behavior may be by design. However, the current source does not make that distinction explicit at the candidate-generation boundary. ## Suggested remediation Please consider one of these explicit contracts: 1. Preserve an explicit generation limitation/unknown when an admitted graph member has no obligation policy, even when structural graph coverage is `complete`; or 2. Define and enforce a schema-level distinction between structural coverage completeness and semantic/obligation coverage completeness, so that policy-less admitted members cannot disappear silently. A regression test should cover a complete graph containing both: - at least one obligation-bearing known node; and - at least one admitted unknown/unmapped node. Expected result: the unresolved member remains represented as an explicit uncertainty/limitation, or the graph contract explicitly proves that it is outside the qualification scope. This report intentionally does not prescribe turning every unknown node into a reconstruction obligation. The minimum concern is loss of uncertainty at a downstream qualification boundary.
Author
Owner

@kaoru0822-kitauji commented on GitHub (Oct 7, 2026):

Fixed on main (#815), after 4.1.0. When an admitted application-graph node has kind unknown, candidate generation now adds this limitation whatever the graph's coverage status:

Application graph <graph_id> contains unresolved node <node_id>; reconstruction obligations remain unknown.

A complete graph that mixes obligation-bearing nodes with an unknown node therefore keeps the uncertainty explicit and no longer drops it silently. This is the first remediation suggested above. src/application/ReconstructionObligationCandidates.test.ts covers this mixed vector: candidates are generated for the known nodes, none target the unknown node, and the limitations are exactly one entry per unknown node.

This ships in the next release (release PR #771).

<!-- gh-comment-id:6041899768 --> @kaoru0822-kitauji commented on GitHub (Oct 7, 2026): Fixed on `main` (#815), after 4.1.0. When an admitted application-graph node has kind `unknown`, candidate generation now adds this limitation whatever the graph's coverage status: > Application graph `<graph_id>` contains unresolved node `<node_id>`; reconstruction obligations remain unknown. A `complete` graph that mixes obligation-bearing nodes with an unknown node therefore keeps the uncertainty explicit and no longer drops it silently. This is the first remediation suggested above. `src/application/ReconstructionObligationCandidates.test.ts` covers this mixed vector: candidates are generated for the known nodes, none target the unknown node, and the limitations are exactly one entry per unknown node. This ships in the next release (release PR #771).
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#346
No description provided.