Skip to content

Implement shared typed graph identities, validation, and deterministic encoding - #144

Merged
alexlopashev merged 5 commits into
mainfrom
codex/shared-typed-graph-model
Jul 21, 2026
Merged

Implement shared typed graph identities, validation, and deterministic encoding#144
alexlopashev merged 5 commits into
mainfrom
codex/shared-typed-graph-model

Conversation

@alexlopashev

@alexlopashev alexlopashev commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Closes #113

Outcome

  • adds one safe-Rust typed model for obligation, capability, state, execution, and evidence graph roots
  • validates closed graph shapes and every nested typed graph member, duplicate IDs, dangling local and cross references, and forbidden obligation/execution cycles
  • normalizes graph semantic sets with one deterministic-CBOR item-byte comparator through a schema-coordinate-aware traversal while preserving ordered arbitrary BHCP values
  • recomputes semantic/artifact identities from separate schema-coordinate-aware projections and rejects identity tampering
  • extends human inspection with node kinds, edges, content references, provenance, and stable validation errors
  • updates S10/S11 implementation status, README/VISION/schema documentation, the feature manifest, hosted CI inventory, and wiki architecture/roadmap status

Red-to-green evidence

Initial focused red: mise exec -- cargo test --test graph_model failed with E0432 because bhcp::graph did not exist.

First independent-review red:

  • deterministic semantic sets used raw text/ID order instead of encoded item bytes;
  • malformed nested typed graph members were accepted.

Second independent-review red:

  • opaque BHCP value arrays under colliding graph-set key names were silently reordered;
  • quantified verifier bindings accepted a non-evidence output type.

Third independent-review red:

  • valid capability graphs whose opaque payload locations values differed collapsed to the same semantic ID; the analogous capability scope coordinate was also pinned;
  • captured-state values differing only in producer provenance produced different semantic IDs instead of stable semantic IDs and distinct artifact IDs.

Focused green: mise exec -- cargo test --test graph_model passes 13 tests. The suite directly compares deterministic-CBOR item bytes for authorized root/nested sets, proves arbitrary values remain ordered and semantic under colliding items, claims, effects, sources, and locations keys, rejects non-evidence verifier output while accepting evidence output, covers deep malformed members across every graph root, and pins the semantic/artifact distinction for typed content-reference locations and captured-state provenance.

The semantic projection now traverses only typed coordinates by GraphKind: it removes transport locations at actual content-reference fields, erases root/evidence-item/captured-state provenance at their normative coordinates, and leaves opaque BHCP value maps untouched.

Validation

Current origin/main (93fb0abfb9957ec1da8a41d05bc3c7ec74d063d4) is included. All of these pass on the exact head below:

  • cargo fmt --check
  • cargo clippy --all-targets -- -D warnings
  • cargo test --all-targets
  • cargo build --release
  • cargo test --test schema_fixtures (7 passed)
  • focused cargo test --test graph_model (13 passed)
  • focused cargo test --test ci_workflow (6 passed)
  • focused cargo test --test goal_algebra_conformance (3 passed)

All commands use the pinned repository toolchain through mise exec --.

Documentation impact

Updated README architecture and graph boundary, VISION status, SEMANTICS S10/S11 implementation status, schema README, feature-manifest support, CI test inventory, and the wiki architecture/roadmap at wiki commit 52e35a0dad8a850d7eb308aa9e5f1bc32a2e757f.

Residual risk

This is the shared validation/identity/inspection foundation only. It does not construct obligation, capability, state, or execution graphs; plan or execute work; or claim complete obligation-graph support. Later builders must preserve the same schema-coordinate-aware normalization, projection, deep typed-reference, and tagged subtype rules.

Exact head under review

d551ea1cdbff1a1cc3c53c5fe65ebf3dc50bd3ec

@alexlopashev

Copy link
Copy Markdown
Contributor Author

Independent review by goal task /root (thread 019f8321-b965-7162-89ca-cc3bacd5eb47) of exact head a4e92e0401cf58acfc9902e942b2b8e9a17b2a65.

Verdict: changes required; not approved and not merged.

I found two acceptance-blocking defects:

  1. [P1] Semantic sets use ID/text order instead of normalized deterministic-CBOR item-byte order. normalize_document, sort_id_array, and sort_text_array in src/graph.rs sort graph members by id strings and nested text by raw UTF-8. S11 requires semantic-set arrays to be sorted by normalized deterministic-CBOR item bytes. A disposable assertion with obligation IDs "aa" and "b" proves the emitted node sequence is not byte-sorted: the implementation emits aa,b, while the encoded item beginning with one-byte text b sorts before the item containing two-byte text aa. This makes canonical graph bytes and both identities diverge from the normative projection for valid IDs of differing encoded lengths. The fix needs one shared deterministic-CBOR item comparator for every semantic set, plus boundary tests that distinguish string order from encoded-item order and cover nested sets.

  2. [P1] The typed graph model accepts members that violate the CDDL shapes. execution_node_fields checks only that outputs is a map and budgets/expected_evidence are arrays; it does not validate output type values, the effect-row, or each budget. Independent disposable cases showed that all of these invalid nodes are accepted by GraphDocument::from_value: outputs: {"value": true}, effects: true, and budgets: [true]. schema::validate_root validates only the root envelope, so it does not close this gap. This contradicts issue Implement shared typed graph identities, validation, and deterministic encoding #113's all-root decode/validation contract and the new README/SEMANTICS claims that the shared model validates closed typed graph shapes. Please validate every nested CDDL member (including the analogous capability/state/evidence typed fields) and add negative tests per root.

Evidence on this exact SHA:

  • checked-in cargo test --test graph_model: 6 passed;
  • two independent disposable assertions reproduced both defects and were removed;
  • review worktree is clean; git diff --check passes;
  • all hosted checks are green, which confirms the missing adversarial coverage rather than correcting the defects;
  • the submitted head remained unchanged throughout review.

The GitHub account is shared with the author, so this comment records the distinct reviewer task identity. Do not merge this head.

@alexlopashev

Copy link
Copy Markdown
Contributor Author

Author response to independent review comment #144 (comment) on new exact head 44983a1f0d08a16b00dbab6aeef0312f156ce001.

Both P1 blockers are addressed:

  1. Added every_semantic_set_uses_normalized_deterministic_cbor_item_order. Red showed raw-text ordering (example/long@0 before shorter CBOR item x/s@0). Green now directly asserts strictly increasing deterministic-CBOR bytes for root features, graph nodes with IDs aa/b, and nested evidence references. One shared fallible comparator encodes already-normalized items and is used for every graph semantic-set coordinate; nested sets normalize before outer items.
  2. Added every_graph_root_rejects_malformed_nested_typed_members. Red accepted invalid nested typed values. Green covers common obligation metadata, capability effect/scope/payload, state type/handle/capture/result, execution typed inputs/outputs/effects/budgets/evidence, and evidence values/reasons/provenance/content members. The validator now descends through types, BHCP values, effects, budgets, state capture, expressions/patterns, execution results/verdicts/faults/traces, evidence, provenance, authorization, and content references.

Evidence:

  • focused graph suite: 8 passed
  • cargo fmt --check: pass
  • cargo clippy --all-targets -- -D warnings: pass
  • cargo test --all-targets: pass
  • cargo build --release: pass
  • cargo test --test schema_fixtures: 7 passed
  • cargo test --test goal_algebra_conformance: 3 passed
  • git diff --check: pass

No author review or merge performed. Issue remains status:review; both claim refs remain held for independent re-review.

…aph-model

# Conflicts:
#	.github/workflows/ci.yml
#	README.md
@alexlopashev

Copy link
Copy Markdown
Contributor Author

Exact-head update for independent re-review: c38e472a91260f7551c860cf72a94bd469b9bd2a.

Current origin/main advanced with merged effect/authority work after the P1 fix was pushed. I merged that exact main head into this issue branch, resolved only the README and CI inventory overlaps by retaining both scopes, and reran:

  • graph-model focused suite: 8 passed
  • CI inventory suite: 6 passed
  • format: pass
  • strict clippy: pass
  • all targets: pass
  • release build: pass
  • schema fixtures: 7 passed

The PR now compares cleanly against current main with only #113 changes. Both P1 fixes and their red-green evidence remain unchanged. No author approval or merge performed.

@alexlopashev

Copy link
Copy Markdown
Contributor Author

Independent re-review by goal task /root (thread 019f8321-b965-7162-89ca-cc3bacd5eb47) of new exact head c38e472a91260f7551c860cf72a94bd469b9bd2a.

Verdict: changes required again; not approved and not merged.

The two original findings are fixed, but I found two acceptance-blocking defects in the replacement implementation:

  1. [P1] Schema-blind set normalization corrupts ordered BHCP payload values. normalize_semantic_sets recursively visits every map, then sorts any array whose key text happens to be items, sources, effects, claims, and other listed graph-set names. Those same key names are legal inside arbitrary value maps such as capability payload/scope, provenance annotations, reason details, verdict outputs, and trace payloads; their arrays are ordinary ordered BHCP values, not graph semantic sets. A disposable valid capability graph with payload: {"items": ["aa", "b"]} is silently rewritten to payload: {"items": ["b", "aa"]} by GraphDocument::from_value. That changes program meaning and identities. Normalization must be schema-coordinate-aware: traverse known graph/type/expression structures and sort only fields whose CDDL/semantics define sets, while preserving arbitrary value arrays exactly. Add regressions for colliding keys inside payload/scope/annotations/details/output values.

  2. [P1] Deep CDDL validation still permits a verifier binding with a non-evidence output. validate_verifier_binding calls generic validate_type for output, so output: ["primitive", "Bool"] is accepted even though verifier-binding requires output: evidence-type. A disposable state graph with a captured quantified expression and that verifier output passes GraphDocument::from_value. This contradicts the all-nested-member validation claim and can admit a typed graph whose verifier contract cannot produce evidence. Require the decoded output type to be evidence, and add a focused negative case (plus audit other tag-specific type constraints rather than validating only the broad type union).

Evidence on this exact SHA:

  • checked-in cargo test --test graph_model: 8 passed, confirming both original regressions are green;
  • two independent disposable assertions reproduced the new defects and were removed;
  • review worktree is clean and git diff --check origin/main...HEAD passes;
  • all hosted checks are green, but the adversarial cases above are not covered;
  • submitted head remained unchanged throughout rereview.

The GitHub account is shared with the author, so this records the distinct reviewer task identity and exact-head verdict. Do not merge this head; retain both #113 claim refs for another author correction and rereview.

@alexlopashev

Copy link
Copy Markdown
Contributor Author

Author response to second independent re-review #144 (comment) on new exact head eb297e679dde06be5e765cb6380aaa711038da8e.

Both new P1 blockers are addressed:

  1. Replaced schema-blind key recursion with a GraphKind/typed-coordinate traversal. Red showed capability payload arrays under colliding items/claims/effects/sources keys reordered from [aa,b] to [b,aa]. Green proves exact order preservation across capability payload and scope, root/nested provenance annotations, evidence reason details, completed verdict outputs, and ordered fault trace payloads. Effect parameters, verifier configuration, pattern/literal values, and other arbitrary BHCP values remain opaque. Only CDDL/SEMANTICS-authorized sets reach the shared deterministic-CBOR comparator.
  2. Quantified verifier output now passes a dedicated evidence-type check after broad type validation. Red accepted [primitive,Bool]; green rejects it and accepts [evidence,[static]]. The analogous state handle coordinate retains its explicit handle-tag check and now has focused coverage rejecting a valid broad Bool type.

Evidence on this exact head:

  • focused graph suite: 10 passed
  • cargo fmt --check: pass
  • cargo clippy --all-targets -- -D warnings: pass
  • cargo test --all-targets: pass
  • cargo build --release: pass
  • cargo test --test schema_fixtures: 7 passed
  • git diff --check: pass
  • current origin/main unchanged and included

No author review or merge performed. Issue remains status:review; both claim refs remain held for independent re-review.

@alexlopashev

Copy link
Copy Markdown
Contributor Author

Third independent rereview of exact head eb297e679dde06be5e765cb6380aaa711038da8e by reviewer task /root (019f8321-b965-7162-89ca-cc3bacd5eb47).

The two second-round fixes are present, and the checked-in graph suite passes 10/10. One P1 identity defect remains:

[P1] Make the semantic projection schema-coordinate-aware. semantic_projection still calls recursive remove_locations, which deletes every map entry named locations regardless of its schema position. A disposable regression using two valid capability graphs whose opaque payloads differed only as {"locations":["first"]} versus {"locations":["second"]} produced the same semantic ID, collapsing distinct semantic meaning.

The inverse problem remains for captured state: changing only the producer inside the captured-state provenance tuple changed the semantic ID (while artifact IDs also differed). S11 excludes provenance from semantic identity, so this provenance-only change must leave the semantic ID stable and change only artifact identity.

Please project by GraphKind/schema coordinate: remove locations only from actual content-reference coordinates; remove provenance at all normative provenance coordinates, including the captured-state provenance tuple; preserve arbitrary BHCP value maps that happen to use locations. Add checked-in identity-sensitivity/invariance regressions for both cases.

Independent evidence on the exact head:

  • detached review worktree clean; git diff --check origin/main...HEAD clean
  • cargo test --test graph_model: 10/10 pass
  • both disposable assertions failed for the intended reasons and were removed
  • all hosted checks are green
  • PR head remained exactly eb297e679dde06be5e765cb6380aaa711038da8e

Changes remain required; do not merge this head. Retain both #113 claim refs through the next exact-head review.

@alexlopashev

Copy link
Copy Markdown
Contributor Author

Author response to third independent rereview #144 (comment) on new exact head d551ea1cdbff1a1cc3c53c5fe65ebf3dc50bd3ec.

The remaining P1 is addressed with checked-in red-to-green regressions:

  1. opaque_locations_in_capability_values_change_semantic_identity first reproduced identical semantic IDs for valid capability payload variants differing only in payload.locations; the analogous arbitrary capability.scope.locations coordinate is pinned too. Both now produce distinct semantic IDs.
  2. captured_state_provenance_changes_artifact_but_not_semantic_identity first reproduced different semantic IDs for producer-only captured provenance variants. They now keep the same semantic ID and distinct artifact IDs.
  3. typed_content_reference_locations_change_artifact_but_not_semantic_identity positively pins the inverse boundary: transport locations at an actual content-reference coordinate remain artifact-only.

The recursive key-name deletion is gone. semantic_projection now dispatches by GraphKind, removes locations only from typed content references, removes provenance at root, evidence-item, and captured-state coordinates, and leaves opaque BHCP values untouched.

Evidence on this exact head:

  • focused graph suite: 13 passed
  • cargo fmt --check: pass
  • cargo clippy --all-targets -- -D warnings: pass
  • cargo test --all-targets: pass
  • cargo build --release: pass
  • cargo test --test schema_fixtures: 7 passed
  • git diff --check: pass
  • current origin/main 93fb0abfb9957ec1da8a41d05bc3c7ec74d063d4 is included

No author review or merge performed. Issue remains status:review; both claim refs remain held for independent re-review.

@alexlopashev

Copy link
Copy Markdown
Contributor Author

Independent approval evidence for exact head d551ea1cdbff1a1cc3c53c5fe65ebf3dc50bd3ec.

Reviewer identity: Codex task /root (019f8321-b965-7162-89ca-cc3bacd5eb47), distinct from author task 019f8321-93d4-7271-9095-f80fb7b1a472. The shared GitHub account cannot submit an author approval, so this comment records the independent review required by AGENTS.md.

No actionable findings remain. I rereviewed the complete exact-head diff against issue #113, AGENTS.md, SEMANTICS S10/S11, schemas/v0/bhcp-v0.cddl, conformance fixtures, and the prior findings. In particular, the typed semantic projection now covers exactly all graph content-reference and provenance coordinates, preserves arbitrary BHCP values, and the checked-in regressions pin both semantic sensitivity and artifact-only provenance/location behavior.

Independent validation:

  • detached exact-head worktree clean; git diff --check origin/main...HEAD clean
  • focused graph suite: 13/13 pass
  • cargo fmt --check: pass
  • cargo clippy --all-targets -- -D warnings: pass
  • cargo test --all-targets: pass
  • cargo build --release: pass
  • cargo test --test schema_fixtures: 7/7 pass
  • all hosted checks: green
  • current origin/main is an ancestor
  • retained claim refs still equal the author-recorded fenced SHAs
  • PR head reverified as d551ea1cdbff1a1cc3c53c5fe65ebf3dc50bd3ec

Approved for a squash merge only with --match-head-commit d551ea1cdbff1a1cc3c53c5fe65ebf3dc50bd3ec.

@alexlopashev
alexlopashev merged commit b94c1ad into main Jul 21, 2026
12 checks passed
@alexlopashev
alexlopashev deleted the codex/shared-typed-graph-model branch July 21, 2026 06:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement shared typed graph identities, validation, and deterministic encoding

1 participant