Canonicalize recursive-plan fingerprints before cycle detection #135

Merged
lost-rob0t merged 5 commits from agent/42-canonical-recursive-fingerprints into main 2026-08-20 21:47:02 +00:00
lost-rob0t commented 2026-08-20 21:18:54 +00:00 (Migrated from github.com)

Closes #42.

What changed

Recursive-plan cycle/duplicate fingerprints now come from a stable canonical executable representation instead of hashing the raw SWI term.

  • anonymous/representation-only SWI dict tags are normalized to a stable sentinel before hashing;
  • genuinely non-ground executable values fail closed as non_ground_recursive_plan;
  • cyclic Prolog terms still fail closed as recursive cycles;
  • duplicate recursive calls remain rejected;
  • child capability validation remains unchanged and still exposes the real denied operation after fingerprint validation succeeds.

Regression coverage

  • proves an anonymous-tag dict makes the raw recursive child representation non-ground and leaves raw term_hash/2 unbound;
  • proves recursive stats accept that representation without a false ancestor cycle and emit integer fingerprints;
  • proves the end-to-end validator reaches the real child_capability_denied(tool(secret_tool)) result;
  • proves genuinely non-ground plan data is rejected;
  • proves a genuine cyclic recursive plan is still rejected;
  • preserves the existing duplicate-recursive-call regression.

TDD / CI note

The initial regression-only exact head unexpectedly reported green instead of providing a trustworthy red checkpoint. Investigation found a separate pre-existing CI integrity bug: test/load_all.pl can emit a real SWI production-module load ERROR while the deterministic job still exits green. That defect is now tracked explicitly in #136.

The implementation itself is therefore validated by the focused behavioral regressions plus the exact final-head suites, but this PR will remain draft and will not be merged while the repository's production static-load merge oracle is known to be unsound.

Exact-head validation

Head: 6fef2c8889be4bb1bf15ce917580be9c16fa169b

  • Deterministic unit and load checks: PASS
  • Tree-sitter FFI: PASS
  • REAL OpenRouter core suite: PASS
  • REAL OpenRouter structured repair suite: PASS
  • REAL OpenRouter benchmark suite: PASS
  • REAL depth 0/1/2 recursion experiment: PASS
  • one-command REAL RLM CLI smoke: PASS

The deterministic gate's static-load substep is not being treated as trustworthy evidence until #136 is repaired.

Non-goals

No weakening of duplicate/cycle protection, no JSON parser rewrite, no capability expansion, and no unrelated recursion-policy redesign.

Closes #42. ## What changed Recursive-plan cycle/duplicate fingerprints now come from a stable canonical executable representation instead of hashing the raw SWI term. - anonymous/representation-only SWI dict tags are normalized to a stable sentinel before hashing; - genuinely non-ground executable values fail closed as `non_ground_recursive_plan`; - cyclic Prolog terms still fail closed as recursive cycles; - duplicate recursive calls remain rejected; - child capability validation remains unchanged and still exposes the real denied operation after fingerprint validation succeeds. ## Regression coverage - proves an anonymous-tag dict makes the raw recursive child representation non-ground and leaves raw `term_hash/2` unbound; - proves recursive stats accept that representation without a false ancestor cycle and emit integer fingerprints; - proves the end-to-end validator reaches the real `child_capability_denied(tool(secret_tool))` result; - proves genuinely non-ground plan data is rejected; - proves a genuine cyclic recursive plan is still rejected; - preserves the existing duplicate-recursive-call regression. ## TDD / CI note The initial regression-only exact head unexpectedly reported green instead of providing a trustworthy red checkpoint. Investigation found a separate pre-existing CI integrity bug: `test/load_all.pl` can emit a real SWI production-module load `ERROR` while the deterministic job still exits green. That defect is now tracked explicitly in #136. The implementation itself is therefore validated by the focused behavioral regressions plus the exact final-head suites, but this PR will remain draft and will not be merged while the repository's production static-load merge oracle is known to be unsound. ## Exact-head validation Head: `6fef2c8889be4bb1bf15ce917580be9c16fa169b` - Deterministic unit and load checks: PASS - Tree-sitter FFI: PASS - REAL OpenRouter core suite: PASS - REAL OpenRouter structured repair suite: PASS - REAL OpenRouter benchmark suite: PASS - REAL depth 0/1/2 recursion experiment: PASS - one-command REAL RLM CLI smoke: PASS The deterministic gate's static-load substep is not being treated as trustworthy evidence until #136 is repaired. ## Non-goals No weakening of duplicate/cycle protection, no JSON parser rewrite, no capability expansion, and no unrelated recursion-policy redesign.
Sign in to join this conversation.
No description provided.