Skip to content

Render why/2 proof terms as an audit tree instead of a flattened term - #5

Merged
vbergeron merged 3 commits into
mainfrom
claude/why-proof-audit-tree-1cd2ot
Aug 5, 2026
Merged

vbergeron merged 3 commits into
mainfrom
claude/why-proof-audit-tree-1cd2ot

Conversation

@vbergeron

Copy link
Copy Markdown
Owner

Manifold.Prolog.AuditTree recognizes the shape a why/2-style proof comes
back as (fact/1, rule/2, either/2, builtin/1, or a flat list of them for
a conjunction's body) and draws it as a tree instead of leaving it to
flatten into one opaque Prolog term like every other query answer.

Manifold.Turn catches this for both routes a goal can reach a query
result from: question mode's own ?- why(...) and a goal the model
generated itself. Neither path knows or cares which produced the
proof; both now log it as an audit tree via the same helper.

Pure unit coverage in test/manifold/prolog/audit_tree_test.exs (no
swipl needed). test/integration/why_audit_test.exs exercises the
question-mode path end to end against the shipped prelude.

claude added 3 commits August 5, 2026 17:39
Manifold.Prolog.AuditTree recognizes the shape a why/2-style proof comes
back as (fact/1, rule/2, either/2, builtin/1, or a flat list of them for
a conjunction's body) and draws it as a tree instead of leaving it to
flatten into one opaque Prolog term like every other query answer.

Manifold.Turn catches this for both routes a goal can reach a query
result from: question mode's own `?- why(...)` and a goal the model
generated itself. Neither path knows or cares which produced the
proof; both now log it as an audit tree via the same helper.

Pure unit coverage in test/manifold/prolog/audit_tree_test.exs (no
swipl needed). test/integration/why_audit_test.exs exercises the
question-mode path end to end against the shipped prelude.
Kernel.node/1 (the BIF reporting the local Erlang node) is auto-imported
into every module, so the private node/1 building a proof's
{label, tag, children} tuple failed to compile: 'imported Kernel.node/1
conflicts with local function'. Renamed to proof_node/1.
The integration test asserted on captured Logger.info output, but
config/test.exs deliberately sets `level: :warning` to keep the suite
quiet — so the audit tree was computed and immediately discarded by the
logger, and the test saw an empty log.

Rather than fight that (documented, deliberate) policy, attach the
audit tree to the `query` message itself as an additive `:audit` field
— visible to any consumer (UI, log, test), not just a log line, and
absent whenever a query's answer isn't why/2-shaped. Documented in
docs/PROTOCOL.md alongside the existing `answer` field.

test/integration/why_audit_test.exs now asserts on the emitted message's
payload instead of captured logs.
@vbergeron
vbergeron merged commit f385c91 into main Aug 5, 2026
1 check passed
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.

2 participants