feat(cli): closure fingerprint, canonical proof states, journal accounting #28
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "refs/pull/28/head"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What & why
Three CLI observability / reproducibility follow-ups reported from the grounded
two-machine FLF run, where the harness had to reconstruct each of these by hand
with bespoke
jq | shasumpipelines and hard-coded SIDs.Closes #20 — canonical semantic closure fingerprint
A first-class, versioned fingerprint so two replicas (or a clean replay)
can check they reached the same semantic closure without ad-hoc hashing.
src/core/fingerprint.rs—elephant.closure.v1/ sha256 over everynon-membership conclusion's proof tag. Excludes everything
identity-/deployment-specific (membership, local aliases, theory id, signers,
timestamps). Byte framing is fully specified and tested: LF-joined
{tag} {literal}lines, sorted by(literal, tag), de-duplicated, noterminal LF.
elephant closure fingerprint [--sequence],elephant status --fingerprint(same digest, embedded), and
elephant closure compare a.json b.json—recomputes each
status --jsonfile's fingerprint offline; exit 0 onmatch, exit 10 on mismatch.
changed proof tag → different digest.
Closes #26 — canonical plain-language proof states
closure::proof_state, top-levelproof_state_map) from the compact+D/+d/-D/-dtags to{proof_state, positive, level}, applied instatus,trace, andwhat-ifJSON.-vnames the state in text output without making thedefault noisy. Names follow the engine's own
ConclusionTypevariants, sothe mapping is authoritative, not a paraphrase.
Closes #22 — journal accounting + log filters
elephant theory inspect <theory>breaks the single journal total intoactive / retracted assertions, retraction entries, and setup (meta/member)
vs. content, from the same status semantics
loguses.elephant loggains composable (AND) filters:--status,--performative,--signer,--sid,--retracts. An empty match is avalid empty structured result.
#17 — defeater polarity docs
Already resolved on
mainby834d4e7(polarity section + executable fixture;the enumerated files live in the out-of-scope Spindle repo). No change here.
Contract note
Adds exit code 10 (
Predicate: a checked condition ran cleanly but did nothold) to the pinned exit-code contract — used by
closure compareand reusableby the deferred sync-wait barrier (#24).
Tests
tests/observability_cli.rsdrives all three features end-to-end(proof-state fields, fingerprint agreement across surfaces,
identity-independence, match/mismatch exit codes,
theory inspectcounts,composable
logfilters).src/core/fingerprint.rsunit tests cover order-independence, memberexclusion, tag-sensitivity, and the exact byte framing.
cargo clippyclean on all touchedfiles (one pre-existing warning in
src/p2p/sync.rs, untouched).Deferred follow-ups (not in this PR)
Left as separate work; several build on the fingerprint landed here:
#21 idempotent
assert --ensure, #23 SPL lint, #24sync waitbarriers (can reuse the fingerprint + exit 10), #25
explain --all --provenance, #27theory export/replay(can reuse the fingerprint andtheory inspectaccounting).🤖 Generated with Claude Code
Addressed all seven review findings in
31bdb55:[P2] Reject malformed status rows —
of_status_jsonnow returnsResultand rejects any row missing a stringtag/literalor carrying a tag outside+D/+d/-D/-d, naming the offending index. No more silent drop → no false convergence. Unit testmalformed_rows_are_rejected_not_dropped.[P2] Exclude negated member conclusions —
is_memberunwraps a single(not …)and checks membership on both the literal and its inner form, so(not (member …))is excluded too. Testmembers_excluded_both_polarities.[P2] Classify setup from parsed SPL —
is_setup_assertparses the payload and checksmetadata()/predicate_metadata()/predicate_declarations()and member facts via the head literal's name, so all membership/meta spellings count as setup. Testmembership_fact_counts_as_setup.[P2] Account for retracted non-assert acts — retracted commits/requests now increment
other_retracted; the total is fully explained. Testretracted_commit_is_accounted.[P2] Include malformed corpus elements in totals —
journal_entriesnow addsstore.entries().1.len(), matchingtheory list; exposed as amalformedfield.[P2] Reject invalid closed-set log filters —
--status/--performativeare now clapValueEnums, so--status activis a parse error (exit 1). Testinvalid_closed_set_filters_are_rejected.[P3] No store for offline compare —
closure compareis routed beforePaths::resolve()and takes onlyjson; works with every home var unset. Testcompare_needs_no_store(env_clear()).Full suite: 234 passed.