Orchestrata Ultimate › Plans › prolog-tabling-restraint-plan

Plan: Prolog bounded tabling, tnot/1 safety audit, CLIPS-vs-SWI spike

Source: plans/prolog-tabling-restraint-plan.md at 8a2cb42ad · last changed 2026-07-27 · first committed 2026-07-10 · 131 lines.

Prose pending.

Plan text

Plan: Prolog bounded tabling, tnot/1 safety audit, CLIPS-vs-SWI spike

Worktree: /home/mohamed/workspace/orchestrata-kimi-wt3
Branch: kimi/prolog-tabling off c717bfcb (current master)
Scope: P-1 bounded tabling on knowledge.pl:ownership_chain/3, P-2 tnot/1 safety audit around constitutional.pl:assess_harm/3, C1 standalone CLIPS-vs-SWI-tabling micro-benchmark.


1. Context (from plans/swi-tabling-capabilities.md)


2. P-1 — Bounded tabling on knowledge.pl:ownership_chain/3

File changes

  1. src/orchestrata_ultimate/prolog/knowledge.pl
    • Change :- dynamic owns/2. → :- dynamic owns/2 as incremental. so a tabled ownership_chain/3 can be incremental.
    • Add directive before the predicate:
      :- table ownership_chain/3 as (incremental, max_answers(20)).
      
    • Add a comment explaining:
      • why max_answers is needed (cycles, unbounded list growth);
      • that answers beyond the cap are marked undefined (answer_count_restraint);
      • call-site policy: undefined/capped results ⇒ deny + escalate.
    • Keep the existing base/recursion clauses unchanged (no semantic drift).

Test design — new tests/knowledge_graph/test_ownership_chain_tabling.py

Use the existing real_prolog fixture + test_id prefixes for parallel safety.

Verification

PYTHONPATH=/home/mohamed/workspace/orchestrata-kimi-wt3/src uv run pytest tests/knowledge_graph/test_ownership_chain_tabling.py -v

3. P-2 — tnot/1 safety audit: do not table constitutional.pl:assess_harm/3

File changes

  1. src/orchestrata_ultimate/prolog/constitutional.pl
    • Add a comment block directly above assess_harm/3 documenting:
      • the self-referential \+ assess_harm(...) in the default clause;
      • that tabling would require converting \+ to tnot/1 and accepting WFS/undefined answers;
      • that the predicate is deliberately left untabled because it is a cheap ground-fact lookup and harm decisions must not be three-valued.
  2. tests/governance/test_tabling_safety.py (new)
    • test_assess_harm_is_not_tabled: load constitutional.pl via a real PrologBridge and assert predicate_property(constitutional:assess_harm(_,_,_), tabled) is false.
    • test_no_self_negated_predicate_is_tabled (audit): enumerate src/orchestrata_ultimate/prolog/*.pl, for each :- table directive verify the tabled predicate does not contain tnot/1 or self-referential \+ in its body (lightweight static audit).

Verification

PYTHONPATH=/home/mohamed/workspace/orchestrata-kimi-wt3/src uv run pytest tests/governance/test_tabling_safety.py -v

4. C1 — Standalone CLIPS-vs-SWI-tabling micro-benchmark

File

scripts/benchmark_prolog_clips.py

Design

Verification

PYTHONPATH=/home/mohamed/workspace/orchestrata-kimi-wt3/src python scripts/benchmark_prolog_clips.py --nodes 50 --edges 100 --queries 10

5. File targets summary

File Change
src/orchestrata_ultimate/prolog/knowledge.pl owns/2 as incremental; table ownership_chain/3 as (incremental, max_answers(20)); comments
src/orchestrata_ultimate/prolog/constitutional.pl Document why assess_harm/3 must stay untabled
tests/knowledge_graph/test_ownership_chain_tabling.py Cycle-termination + bounded-answer janus tests
tests/governance/test_tabling_safety.py assess_harm/3 not tabled + static tabling audit
scripts/benchmark_prolog_clips.py Standalone CLIPS vs SWI-tabling benchmark
plans/prolog-tabling-restraint-plan.md This plan

6. Test / gate plan

  1. Run the two new test modules in isolation.
  2. Run python scripts/gate_parallel_safety.py and python scripts/audit_test_purity.py for changed test files.
  3. Run the full regression via python scripts/run_tests.py --skip-gates before final commit.
  4. Do not commit until the plan is reviewed and ACK'd on #agents.

7. Risks / open questions