sum-engine 0.5.0__tar.gz → 0.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {sum_engine-0.5.0/sum_engine.egg-info → sum_engine-0.7.0}/PKG-INFO +57 -12
- {sum_engine-0.5.0 → sum_engine-0.7.0}/README.md +51 -8
- {sum_engine-0.5.0 → sum_engine-0.7.0}/pyproject.toml +14 -5
- sum_engine-0.7.0/sum_cli/audit_log.py +171 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_cli/main.py +777 -1
- {sum_engine-0.5.0 → sum_engine-0.7.0/sum_engine.egg-info}/PKG-INFO +57 -12
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine.egg-info/SOURCES.txt +52 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine.egg-info/requires.txt +6 -3
- sum_engine-0.7.0/sum_engine_internal/agent_surface/__init__.py +22 -0
- sum_engine-0.7.0/sum_engine_internal/agent_surface/bind.py +138 -0
- sum_engine-0.7.0/sum_engine_internal/agent_surface/mcp_bind.py +677 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/algorithms/syntactic_sieve.py +9 -1
- sum_engine-0.7.0/sum_engine_internal/compliance/__init__.py +48 -0
- sum_engine-0.7.0/sum_engine_internal/compliance/_predicates.py +86 -0
- sum_engine-0.7.0/sum_engine_internal/compliance/eu_ai_act_article_12.py +197 -0
- sum_engine-0.7.0/sum_engine_internal/compliance/gdpr_article_30.py +207 -0
- sum_engine-0.7.0/sum_engine_internal/compliance/hipaa_164_312_b.py +230 -0
- sum_engine-0.7.0/sum_engine_internal/compliance/iso_27001_8_15.py +160 -0
- sum_engine-0.7.0/sum_engine_internal/compliance/pci_dss_4_req_10.py +264 -0
- sum_engine-0.7.0/sum_engine_internal/compliance/report.py +77 -0
- sum_engine-0.7.0/sum_engine_internal/compliance/soc_2_cc_7_2.py +153 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/ensemble/live_llm_adapter.py +217 -8
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/ensemble/llm_dispatch.py +203 -16
- sum_engine-0.7.0/sum_engine_internal/evidence/__init__.py +45 -0
- sum_engine-0.7.0/sum_engine_internal/evidence/chain.py +160 -0
- sum_engine-0.7.0/sum_engine_internal/graph_store/__init__.py +26 -0
- sum_engine-0.7.0/sum_engine_internal/graph_store/base.py +105 -0
- sum_engine-0.7.0/sum_engine_internal/graph_store/egglog_store.py +360 -0
- sum_engine-0.7.0/sum_engine_internal/graph_store/unionfind_store.py +206 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/infrastructure/akashic_ledger.py +34 -11
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/infrastructure/canonical_codec.py +374 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/infrastructure/jose_envelope.py +101 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/mcp_server/server.py +23 -1
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/render_receipt/verifier.py +11 -1
- sum_engine-0.7.0/sum_engine_internal/research/bootstrap/__init__.py +41 -0
- sum_engine-0.7.0/sum_engine_internal/research/bootstrap/multiplier_bootstrap.py +181 -0
- sum_engine-0.7.0/sum_engine_internal/research/conformal/__init__.py +44 -0
- sum_engine-0.7.0/sum_engine_internal/research/conformal/entropy_baseline.py +182 -0
- sum_engine-0.7.0/sum_engine_internal/research/conformal/split_conformal.py +184 -0
- sum_engine-0.7.0/sum_engine_internal/research/lsh/__init__.py +19 -0
- sum_engine-0.7.0/sum_engine_internal/research/lsh/bundle_index.py +179 -0
- sum_engine-0.7.0/sum_engine_internal/research/mmd/__init__.py +54 -0
- sum_engine-0.7.0/sum_engine_internal/research/mmd/baseline.py +328 -0
- sum_engine-0.7.0/sum_engine_internal/research/mmd/mmd.py +184 -0
- sum_engine-0.7.0/sum_engine_internal/research/robust_pca/__init__.py +35 -0
- sum_engine-0.7.0/sum_engine_internal/research/robust_pca/axiom_embedding.py +69 -0
- sum_engine-0.7.0/sum_engine_internal/research/robust_pca/pcp.py +173 -0
- sum_engine-0.7.0/sum_engine_internal/research/sequential/__init__.py +21 -0
- sum_engine-0.7.0/sum_engine_internal/research/sequential/sprt.py +183 -0
- sum_engine-0.7.0/sum_engine_internal/research/sheaf_laplacian_v2.py +649 -0
- sum_engine-0.7.0/sum_engine_internal/research/sheaf_laplacian_v3.py +509 -0
- sum_engine-0.7.0/sum_engine_internal/research/sheaf_laplacian_v32.py +170 -0
- sum_engine-0.7.0/sum_engine_internal/research/smt_consistency/__init__.py +34 -0
- sum_engine-0.7.0/sum_engine_internal/research/smt_consistency/consistency.py +188 -0
- sum_engine-0.7.0/sum_engine_internal/research/smt_consistency/predicate_library.py +77 -0
- sum_engine-0.7.0/sum_engine_internal/research/spectral_entropy/__init__.py +41 -0
- sum_engine-0.7.0/sum_engine_internal/research/spectral_entropy/vn_entropy.py +141 -0
- sum_engine-0.7.0/sum_engine_internal/transform_receipt/__init__.py +55 -0
- sum_engine-0.7.0/sum_engine_internal/transform_receipt/format.py +215 -0
- sum_engine-0.7.0/sum_engine_internal/transform_receipt/sign.py +50 -0
- sum_engine-0.7.0/sum_engine_internal/transform_receipt/verifier.py +132 -0
- sum_engine-0.7.0/sum_engine_internal/transforms/__init__.py +104 -0
- sum_engine-0.7.0/sum_engine_internal/transforms/_base.py +203 -0
- sum_engine-0.7.0/sum_engine_internal/transforms/compose.py +304 -0
- sum_engine-0.7.0/sum_engine_internal/transforms/extract.py +406 -0
- sum_engine-0.7.0/sum_engine_internal/transforms/share.py +231 -0
- sum_engine-0.7.0/sum_engine_internal/transforms/slider.py +380 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/LICENSE +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/setup.cfg +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_cli/__init__.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine.egg-info/dependency_links.txt +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine.egg-info/entry_points.txt +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine.egg-info/top_level.txt +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/__init__.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/adapters/__init__.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/adapters/format_pivot.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/algorithms/__init__.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/algorithms/causal_discovery.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/algorithms/chunked_corpus.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/algorithms/minhash.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/algorithms/predicate_canon.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/algorithms/semantic_arithmetic.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/algorithms/zk_semantics.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/ensemble/__init__.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/ensemble/automated_scientist.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/ensemble/autonomous_agent.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/ensemble/causal_triggers.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/ensemble/confidence_calibrator.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/ensemble/data/__init__.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/ensemble/data/common_english_2000.txt +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/ensemble/data/common_english_5000.txt +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/ensemble/epistemic_arbiter.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/ensemble/epistemic_loop.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/ensemble/extraction_validator.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/ensemble/gauge_orchestrator.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/ensemble/llm_entailment.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/ensemble/mass_semantic_engine.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/ensemble/ouroboros.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/ensemble/s25_interventions.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/ensemble/semantic_dedup.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/ensemble/slider_renderer.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/ensemble/tome_generator.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/ensemble/tome_sliders.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/ensemble/vector_bridge.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/ensemble/venn_abers.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/infrastructure/__init__.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/infrastructure/jcs.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/infrastructure/key_manager.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/infrastructure/p2p_mesh.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/infrastructure/prov_o.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/infrastructure/provenance.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/infrastructure/rate_limiter.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/infrastructure/resource_guards.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/infrastructure/scheme_registry.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/infrastructure/state_encoding.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/infrastructure/telemetry.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/infrastructure/tome_parser.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/infrastructure/verifiable_credential.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/infrastructure/zig_bridge.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/mcp_server/__init__.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/mcp_server/__main__.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/mcp_server/errors.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/merkle_sidecar/__init__.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/merkle_sidecar/tree.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/render_receipt/__init__.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/research/__init__.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/research/sheaf_laplacian.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/trust_root/__init__.py +0 -0
- {sum_engine-0.5.0 → sum_engine-0.7.0}/sum_engine_internal/trust_root/verifier.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sum-engine
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: SUM — bidirectional knowledge distillation with optional cryptographic attestation. Pipe prose, get a CanonicalBundle (HMAC / Ed25519 / W3C VC 2.0), verify anywhere.
|
|
5
5
|
Author: ototao
|
|
6
6
|
License: Apache-2.0
|
|
@@ -25,9 +25,11 @@ Requires-Dist: cryptography>=41.0.0
|
|
|
25
25
|
Requires-Dist: sympy>=1.12
|
|
26
26
|
Provides-Extra: sieve
|
|
27
27
|
Requires-Dist: spacy>=3.7.0; extra == "sieve"
|
|
28
|
+
Provides-Extra: openai
|
|
29
|
+
Requires-Dist: openai<3.0.0,>=1.40.0; extra == "openai"
|
|
30
|
+
Requires-Dist: pydantic>=2.0.0; extra == "openai"
|
|
28
31
|
Provides-Extra: llm
|
|
29
|
-
Requires-Dist: openai
|
|
30
|
-
Requires-Dist: pydantic>=2.0.0; extra == "llm"
|
|
32
|
+
Requires-Dist: sum-engine[openai]; extra == "llm"
|
|
31
33
|
Provides-Extra: anthropic
|
|
32
34
|
Requires-Dist: anthropic>=0.97.0; extra == "anthropic"
|
|
33
35
|
Requires-Dist: pydantic>=2.0.0; extra == "anthropic"
|
|
@@ -51,7 +53,7 @@ Requires-Dist: build>=1.0.0; extra == "dev"
|
|
|
51
53
|
Requires-Dist: hypothesis>=6.0.0; extra == "dev"
|
|
52
54
|
Provides-Extra: all
|
|
53
55
|
Requires-Dist: sum-engine[sieve]; extra == "all"
|
|
54
|
-
Requires-Dist: sum-engine[
|
|
56
|
+
Requires-Dist: sum-engine[openai]; extra == "all"
|
|
55
57
|
Requires-Dist: sum-engine[anthropic]; extra == "all"
|
|
56
58
|
Requires-Dist: sum-engine[receipt-verify]; extra == "all"
|
|
57
59
|
Requires-Dist: sum-engine[mcp]; extra == "all"
|
|
@@ -66,9 +68,15 @@ Dynamic: license-file
|
|
|
66
68
|
[](https://www.python.org/downloads/)
|
|
67
69
|
[](LICENSE)
|
|
68
70
|
|
|
69
|
-
> **
|
|
71
|
+
> **SUM lets people and agents transform knowledge without losing the ability to verify what changed, what stayed the same, who signed it, and what remains unproven.**
|
|
70
72
|
|
|
71
|
-
|
|
73
|
+
Every transformation — extract triples from prose, render a tome at a controlled slider position, compose bundles across documents, share a render — emits a cryptographically-signed receipt that any third party can verify offline. The receipt attests *that the transformation happened and what its inputs were*. Separate per-axis benchmarks attest *how much the transformation preserved meaning*. Both are kept honest by separate proof discipline — and the project never blurs the line between them.
|
|
74
|
+
|
|
75
|
+
*Live trust loop:* https://sum-demo.ototao.workers.dev — three runtimes (Python, Node, modern browsers) produce byte-identical Ed25519 signatures over the same JCS-canonical bytes; verify offline against `/.well-known/jwks.json`. Mechanically proven; locked in CI on every PR.
|
|
76
|
+
|
|
77
|
+
**Built for:** journalists working under deepfake-era citation requirements, academic survey writers who need provenance back to source PDFs, agentic-AI builders who need their agents to pass verifiable evidence and not just messages, and regulated-domain content (EU AI Act Article 12, FTC AI disclosure, HIPAA, SOC 2, PCI DSS) where "we say it's true" isn't enough.
|
|
78
|
+
|
|
79
|
+
The cryptographic side is **mechanically proven** — three independent verifier implementations agreeing byte-for-byte on every signed bundle, locked in CI on every PR. The semantic side (extraction quality, slider fact preservation) is **empirically measured** with explicit per-corpus numbers and explicit per-corpus boundaries. [`docs/PROOF_BOUNDARY.md`](docs/PROOF_BOUNDARY.md) is the arbiter.
|
|
72
80
|
|
|
73
81
|
Headline supporting numbers (each links to its source of truth):
|
|
74
82
|
|
|
@@ -110,14 +118,29 @@ A minimal Node verifier using `jose` + `canonicalize` is in [`docs/RENDER_RECEIP
|
|
|
110
118
|
| Surface | Status | Verifies |
|
|
111
119
|
|---|---|---|
|
|
112
120
|
| `pip install 'sum-engine[sieve]'` — `sum attest` / `sum verify` / `sum render` / `sum resolve` / `sum ledger` / `sum inspect` / `sum schema` | shipped on PyPI ≥ 0.4.1 | structural reconstruction; HMAC-SHA256 + Ed25519 signatures (W3C VC 2.0 `eddsa-jcs-2022`); bidirectional `sum attest` ↔ `sum render` symmetry from the shell |
|
|
113
|
-
| Cloudflare Worker at `sum-demo.ototao.workers.dev` | shipped | `/api/render` → tome + `render_receipt`;
|
|
121
|
+
| Cloudflare Worker at `sum-demo.ototao.workers.dev` | shipped | `/api/render` → tome + `render_receipt`; `/api/transform` → generic transform-registry dispatch + `sum.transform_receipt.v1`; `/api/complete` → LLM proxy; `/api/qid` → Wikidata resolver; `/.well-known/jwks.json` + `/.well-known/revoked-kids.json` → trust-loop endpoints. Public LLM-axis routes are rate-limited per IP — see [`docs/PUBLIC_API_RATE_LIMITS.md`](docs/PUBLIC_API_RATE_LIMITS.md) (5/day operator-keyed demo; 100/hr with BYO key via `X-Render-LLM-Key-Anthropic` / `-OpenAI`). |
|
|
114
122
|
| Single-file browser demo (`single_file_demo/index.html`) | shipped | paste prose → in-browser attest → CanonicalBundle JSON; same bytes verify under `node standalone_verifier/verify.js` (Chrome / Firefox / Safari with WebCrypto Ed25519 support) |
|
|
115
123
|
| Cross-runtime trust triangle | locked by CI (`make xruntime`) | K1 / K1-mw / K2 / K3 / K4 — Python ↔ Node ↔ Browser agree byte-for-byte on valid bundles. `make xruntime-adversarial` adds A1–A6 rejection-class equivalence. |
|
|
116
|
-
| 5-axis slider rendering surface | density actioned deterministically; length / formality / audience / perspective LLM-conditioned
|
|
124
|
+
| 5-axis slider rendering surface | density actioned deterministically; length / formality / audience / perspective LLM-conditioned. Two dispatch paths: Worker `/api/render` (Anthropic + Cloudflare AI Gateway optional) producing `sum.render_receipt.v1`, OR Python `sum transform apply slider` (OpenAI via `OPENAI_API_KEY`) producing `sum.transform_receipt.v1` | bench: median LLM-axis fact preservation 1.000, p10 0.769 (long, n=16) / 0.818 (short, n=8), order preservation 1.000 wherever measurable. Tightening worktrail at [`docs/BENCH_HARDENING_FROM_QCVV.md`](docs/BENCH_HARDENING_FROM_QCVV.md) adds iteration-stability + DKW worst-case bounds + capability-region headlines |
|
|
117
125
|
| MCP server (`sum-mcp` console script) | shipped | five tools (`extract` / `attest` / `verify` / `inspect` / `schema`) exposed over stdio; bundles attested via MCP verify byte-identically through the CLI / Node / browser verifiers |
|
|
126
|
+
| Transform substrate (`sum.transform_receipt.v1` + registry) | shipped (CLI in repo HEAD; PyPI catch-up tag pending) | `sum transform list` / `sum transform apply <name>` — three registered transforms (`slider` / `extract` / `compose`); receipts via Ed25519 / JCS / detached JWS just like render-receipts; 20-fixture cross-runtime K-matrix locks accept + reject across Python ↔ Node ↔ browser; T4 `source_chain_hash` binds receipts to source byte ranges; T5 `ShareableRender` round-trips signed renders for offline verification; T6 multi-school extract runs two extractors in tandem for adversarial-divergence detection. Wire spec at [`docs/TRANSFORM_RECEIPT_FORMAT.md`](docs/TRANSFORM_RECEIPT_FORMAT.md); design at [`docs/TRANSFORM_REGISTRY.md`](docs/TRANSFORM_REGISTRY.md). |
|
|
127
|
+
| Replay-defense window (`signed_at_out_of_window`) | shipped | opt-in `max_age_seconds` parameter across all four verifier surfaces (Python render / Python transform / JS render / JS transform). Default-off preserves archival use; receivers opt in per use-case (agent-swarm 60s, real-time 600s, newsletter 1d, legal-discovery no window). |
|
|
128
|
+
| `sum verify --explain` layered output | shipped | Per-dimension report (`sum.verify_explained.v1`): cryptographic integrity / canonical reconstruction / axiom consistency / extraction provenance / source evidence coverage / semantic preservation / truth of content. Each carries `epistemic_status` (`provable` / `certified` / `empirical-benchmark` / `not-asserted`). Truth of content is ALWAYS `not_asserted` — locked by test. |
|
|
129
|
+
| Negative-control corpus (T5 of bench-hardening) | shipped | 20 hand-authored documents across 5 failure modes (ambiguous coref / predicate-alias / contradictions / entity-resolution-adversarial / non-extractable). Runner exits 1 if observed failures don't match annotations. Baseline at [`fixtures/bench_receipts/negative_control_2026-05-17.json`](fixtures/bench_receipts/negative_control_2026-05-17.json). |
|
|
130
|
+
| Compliance validators (six regimes) | shipped | `sum compliance check --regime <id> --audit-log <path>` — EU AI Act Article 12, GDPR Article 30, HIPAA § 164.312(b), ISO/IEC 27001 A.8.15, SOC 2 CC 7.2, PCI DSS v4.0 Req 10. All six produce the same `sum.compliance_report.v1` schema; per-regime docs at `docs/COMPLIANCE_*.md`. |
|
|
118
131
|
|
|
119
132
|
The slider's product claim — *axis changes do not lose facts* — is the load-bearing empirical result. It is verified by NLI audit on every embedding-flagged "loss" cell; full attribution in [`docs/SLIDER_CONTRACT.md`](docs/SLIDER_CONTRACT.md).
|
|
120
133
|
|
|
134
|
+
## Strategic context
|
|
135
|
+
|
|
136
|
+
The operational compass — read in this order if you want the project's intent + how it operates + where it's going:
|
|
137
|
+
|
|
138
|
+
- [`docs/CHARTER_2026-05-17.md`](docs/CHARTER_2026-05-17.md) — intent, the Why, strategy, objectives, success criteria, constraints, and the operational loop. The compass every other doc resolves to.
|
|
139
|
+
- [`docs/PRODUCT_DELIBERATION_2026-05-14.md`](docs/PRODUCT_DELIBERATION_2026-05-14.md) — three-option strategic analysis + grant-outcome decision tree.
|
|
140
|
+
- [`docs/ZENITH_FRAMING_2026-05-16.md`](docs/ZENITH_FRAMING_2026-05-16.md) — destination framing (SUM as chain-of-custody for AI-transformed knowledge) plus three new concepts (Perspective Receipts, Trust Profiles, Epistemic Nutrition Label) on the design queue.
|
|
141
|
+
- [`docs/BENCH_HARDENING_FROM_QCVV.md`](docs/BENCH_HARDENING_FROM_QCVV.md) — five-task empirical-benchmark hardening plan (T1–T5; T5 shipped, T1–T4 queued).
|
|
142
|
+
- [`docs/DOGFOOD_QUICKSTART.md`](docs/DOGFOOD_QUICKSTART.md) — five-minute guide to running SUM on your own writing.
|
|
143
|
+
|
|
121
144
|
### LLM narrative round-trip — closed across measured corpora (2026-04-28)
|
|
122
145
|
|
|
123
146
|
The hardest measurement in `PROOF_BOUNDARY.md` is the full LLM narrative round-trip (`text → LLM-extract → axioms → LLM-generate → prose' → LLM-extract → axioms'`). The unprompted-pipeline baseline on `seed_v1` was **drift = 107.75% / exact-match recall = 0.12** — facts preserved, keys not.
|
|
@@ -165,7 +188,7 @@ The reverse direction also runs under explicit slider control. The local path ac
|
|
|
165
188
|
sum render --density 0.5 < bundle.json
|
|
166
189
|
# → keeps the lex-prefix half of the axioms; @sliders header records what was requested
|
|
167
190
|
|
|
168
|
-
sum render --length 0.9 --use-worker https://sum.ototao.
|
|
191
|
+
sum render --length 0.9 --use-worker https://sum-demo.ototao.workers.dev --json < bundle.json
|
|
169
192
|
# → LLM-conditioned tome + signed render_receipt (sum.render_receipt.v1) on stdout
|
|
170
193
|
```
|
|
171
194
|
|
|
@@ -192,7 +215,7 @@ pip install 'sum-engine[mcp,sieve]'
|
|
|
192
215
|
|
|
193
216
|
### Calling SUM over HTTP
|
|
194
217
|
|
|
195
|
-
The hosted Worker at `https://sum.ototao.
|
|
218
|
+
The hosted Worker at `https://sum-demo.ototao.workers.dev` exposes `/api/render`, `/api/complete`, `/api/qid`, and the `/.well-known/{jwks,revoked-kids}.json` verification surfaces. [`docs/API_REFERENCE.md`](docs/API_REFERENCE.md) is the wire spec — request/response shapes, error codes, the six-step receipt-verification flow, working Node + Python examples. Use this when the caller is a web app, mobile app, or server-side service; use the MCP server when the caller is a local LLM client.
|
|
196
219
|
|
|
197
220
|
---
|
|
198
221
|
|
|
@@ -228,7 +251,29 @@ Below the slider sits the substrate that earlier phases shipped and verified. Po
|
|
|
228
251
|
- **Bundle public-key attestation (provable).** Ed25519-signed CanonicalBundles are tamper-detectable by any third party in any of the three runtimes. [`docs/PROOF_BOUNDARY.md`](docs/PROOF_BOUNDARY.md) §1.3.1.
|
|
229
252
|
- **Merkle hash-chain integrity (provable, including under concurrent writers).** [`docs/PROOF_BOUNDARY.md`](docs/PROOF_BOUNDARY.md) §1.7.
|
|
230
253
|
- **Extraction F1 (empirical-benchmark).** 1.000 on `seed_v1` (50 simple-SVO docs); 0.762 with precision 1.000 on `seed_v2` (20-doc difficulty corpus). Every remaining `seed_v2` failure is a recall miss, not a truth inversion. [`docs/PROOF_BOUNDARY.md`](docs/PROOF_BOUNDARY.md) §2.1.
|
|
231
|
-
- **
|
|
254
|
+
- **168 numbered features**, each with a reproducible verification command, in [`docs/FEATURE_CATALOG.md`](docs/FEATURE_CATALOG.md).
|
|
255
|
+
|
|
256
|
+
### Research substrate (under `sum_engine_internal/research/`)
|
|
257
|
+
|
|
258
|
+
Less-surfaced but shipped:
|
|
259
|
+
|
|
260
|
+
- **MinHash-LSH bundle similarity index** (`research/lsh/`) — near-duplicate bundle detection at scale.
|
|
261
|
+
- **Robust PCA corruption score** (`research/robust_pca/`) — `corruption_score` field in bundle metadata; flags adversarially-perturbed bundles.
|
|
262
|
+
- **Sequential & conformal-prediction** (`research/sequential/`, `research/conformal/`) — bench-side confidence bounds with documented coverage guarantees.
|
|
263
|
+
- **MMD distribution distance** (`research/mmd/`) — `axiom_distribution_mmd` field on bundles; surfaces when an attested bundle is structurally unlike its baseline corpus.
|
|
264
|
+
- **Spectral entropy** (`research/spectral_entropy/`) — axiom-graph entropy on every bundle, with confidence interval.
|
|
265
|
+
- **Bootstrap multiplier spike detection** (`research/bootstrap/`) — see [`docs/MULTIPLIER_BOOTSTRAP_SPIKE_FINDINGS.md`](docs/MULTIPLIER_BOOTSTRAP_SPIKE_FINDINGS.md).
|
|
266
|
+
- **SMT consistency checking** (`research/smt_consistency/`) — z3-backed `axiom_consistency_check` on every bundle.
|
|
267
|
+
- **Sheaf-Laplacian hallucination detection** — see [`docs/SHEAF_HALLUCINATION_DETECTOR.md`](docs/SHEAF_HALLUCINATION_DETECTOR.md) (research direction).
|
|
268
|
+
|
|
269
|
+
### Other substrate-adjacent surfaces
|
|
270
|
+
|
|
271
|
+
- **Trust-root manifest** (`sum_engine_internal/trust_root/`) — operator-issued signed manifest binding kid lifecycle, revocation policy, and verifier expectations.
|
|
272
|
+
- **Merkle sidecar format** (`sum_engine_internal/merkle_sidecar/`) — see [`docs/MERKLE_SIDECAR_FORMAT.md`](docs/MERKLE_SIDECAR_FORMAT.md).
|
|
273
|
+
- **Evidence-chain layer** (`sum_engine_internal/evidence/`) — substrate behind `source_chain_hash` (T4).
|
|
274
|
+
- **Algorithm registry** — see [`docs/ALGORITHM_REGISTRY.md`](docs/ALGORITHM_REGISTRY.md) (the in-tree list of permitted signing algs; crypto-agility gate).
|
|
275
|
+
- **Audit log format** — every CLI operation can emit `sum.audit_log.v1` events; see [`docs/AUDIT_LOG_FORMAT.md`](docs/AUDIT_LOG_FORMAT.md).
|
|
276
|
+
- **Agent surface** (`sum_engine_internal/agent_surface/`) — see [`docs/AGENT_SURFACE_FINDINGS.md`](docs/AGENT_SURFACE_FINDINGS.md).
|
|
232
277
|
|
|
233
278
|
---
|
|
234
279
|
|
|
@@ -275,7 +320,7 @@ Source anchoring in the bundle schema, bundle explorer / viewer, `sum verify --e
|
|
|
275
320
|
|
|
276
321
|
```bash
|
|
277
322
|
make install # editable install with sieve + dev extras
|
|
278
|
-
make test # full pytest run (
|
|
323
|
+
make test # full pytest run (2000+ tests)
|
|
279
324
|
make xruntime # cross-runtime K1/K1-mw/K2/K3/K4 (Python ↔ Node)
|
|
280
325
|
make xruntime-adversarial # rejection-matrix A1–A6
|
|
281
326
|
make fortress # 21-check pure-math invariants
|
|
@@ -5,9 +5,15 @@
|
|
|
5
5
|
[](https://www.python.org/downloads/)
|
|
6
6
|
[](LICENSE)
|
|
7
7
|
|
|
8
|
-
> **
|
|
8
|
+
> **SUM lets people and agents transform knowledge without losing the ability to verify what changed, what stayed the same, who signed it, and what remains unproven.**
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Every transformation — extract triples from prose, render a tome at a controlled slider position, compose bundles across documents, share a render — emits a cryptographically-signed receipt that any third party can verify offline. The receipt attests *that the transformation happened and what its inputs were*. Separate per-axis benchmarks attest *how much the transformation preserved meaning*. Both are kept honest by separate proof discipline — and the project never blurs the line between them.
|
|
11
|
+
|
|
12
|
+
*Live trust loop:* https://sum-demo.ototao.workers.dev — three runtimes (Python, Node, modern browsers) produce byte-identical Ed25519 signatures over the same JCS-canonical bytes; verify offline against `/.well-known/jwks.json`. Mechanically proven; locked in CI on every PR.
|
|
13
|
+
|
|
14
|
+
**Built for:** journalists working under deepfake-era citation requirements, academic survey writers who need provenance back to source PDFs, agentic-AI builders who need their agents to pass verifiable evidence and not just messages, and regulated-domain content (EU AI Act Article 12, FTC AI disclosure, HIPAA, SOC 2, PCI DSS) where "we say it's true" isn't enough.
|
|
15
|
+
|
|
16
|
+
The cryptographic side is **mechanically proven** — three independent verifier implementations agreeing byte-for-byte on every signed bundle, locked in CI on every PR. The semantic side (extraction quality, slider fact preservation) is **empirically measured** with explicit per-corpus numbers and explicit per-corpus boundaries. [`docs/PROOF_BOUNDARY.md`](docs/PROOF_BOUNDARY.md) is the arbiter.
|
|
11
17
|
|
|
12
18
|
Headline supporting numbers (each links to its source of truth):
|
|
13
19
|
|
|
@@ -49,14 +55,29 @@ A minimal Node verifier using `jose` + `canonicalize` is in [`docs/RENDER_RECEIP
|
|
|
49
55
|
| Surface | Status | Verifies |
|
|
50
56
|
|---|---|---|
|
|
51
57
|
| `pip install 'sum-engine[sieve]'` — `sum attest` / `sum verify` / `sum render` / `sum resolve` / `sum ledger` / `sum inspect` / `sum schema` | shipped on PyPI ≥ 0.4.1 | structural reconstruction; HMAC-SHA256 + Ed25519 signatures (W3C VC 2.0 `eddsa-jcs-2022`); bidirectional `sum attest` ↔ `sum render` symmetry from the shell |
|
|
52
|
-
| Cloudflare Worker at `sum-demo.ototao.workers.dev` | shipped | `/api/render` → tome + `render_receipt`;
|
|
58
|
+
| Cloudflare Worker at `sum-demo.ototao.workers.dev` | shipped | `/api/render` → tome + `render_receipt`; `/api/transform` → generic transform-registry dispatch + `sum.transform_receipt.v1`; `/api/complete` → LLM proxy; `/api/qid` → Wikidata resolver; `/.well-known/jwks.json` + `/.well-known/revoked-kids.json` → trust-loop endpoints. Public LLM-axis routes are rate-limited per IP — see [`docs/PUBLIC_API_RATE_LIMITS.md`](docs/PUBLIC_API_RATE_LIMITS.md) (5/day operator-keyed demo; 100/hr with BYO key via `X-Render-LLM-Key-Anthropic` / `-OpenAI`). |
|
|
53
59
|
| Single-file browser demo (`single_file_demo/index.html`) | shipped | paste prose → in-browser attest → CanonicalBundle JSON; same bytes verify under `node standalone_verifier/verify.js` (Chrome / Firefox / Safari with WebCrypto Ed25519 support) |
|
|
54
60
|
| Cross-runtime trust triangle | locked by CI (`make xruntime`) | K1 / K1-mw / K2 / K3 / K4 — Python ↔ Node ↔ Browser agree byte-for-byte on valid bundles. `make xruntime-adversarial` adds A1–A6 rejection-class equivalence. |
|
|
55
|
-
| 5-axis slider rendering surface | density actioned deterministically; length / formality / audience / perspective LLM-conditioned
|
|
61
|
+
| 5-axis slider rendering surface | density actioned deterministically; length / formality / audience / perspective LLM-conditioned. Two dispatch paths: Worker `/api/render` (Anthropic + Cloudflare AI Gateway optional) producing `sum.render_receipt.v1`, OR Python `sum transform apply slider` (OpenAI via `OPENAI_API_KEY`) producing `sum.transform_receipt.v1` | bench: median LLM-axis fact preservation 1.000, p10 0.769 (long, n=16) / 0.818 (short, n=8), order preservation 1.000 wherever measurable. Tightening worktrail at [`docs/BENCH_HARDENING_FROM_QCVV.md`](docs/BENCH_HARDENING_FROM_QCVV.md) adds iteration-stability + DKW worst-case bounds + capability-region headlines |
|
|
56
62
|
| MCP server (`sum-mcp` console script) | shipped | five tools (`extract` / `attest` / `verify` / `inspect` / `schema`) exposed over stdio; bundles attested via MCP verify byte-identically through the CLI / Node / browser verifiers |
|
|
63
|
+
| Transform substrate (`sum.transform_receipt.v1` + registry) | shipped (CLI in repo HEAD; PyPI catch-up tag pending) | `sum transform list` / `sum transform apply <name>` — three registered transforms (`slider` / `extract` / `compose`); receipts via Ed25519 / JCS / detached JWS just like render-receipts; 20-fixture cross-runtime K-matrix locks accept + reject across Python ↔ Node ↔ browser; T4 `source_chain_hash` binds receipts to source byte ranges; T5 `ShareableRender` round-trips signed renders for offline verification; T6 multi-school extract runs two extractors in tandem for adversarial-divergence detection. Wire spec at [`docs/TRANSFORM_RECEIPT_FORMAT.md`](docs/TRANSFORM_RECEIPT_FORMAT.md); design at [`docs/TRANSFORM_REGISTRY.md`](docs/TRANSFORM_REGISTRY.md). |
|
|
64
|
+
| Replay-defense window (`signed_at_out_of_window`) | shipped | opt-in `max_age_seconds` parameter across all four verifier surfaces (Python render / Python transform / JS render / JS transform). Default-off preserves archival use; receivers opt in per use-case (agent-swarm 60s, real-time 600s, newsletter 1d, legal-discovery no window). |
|
|
65
|
+
| `sum verify --explain` layered output | shipped | Per-dimension report (`sum.verify_explained.v1`): cryptographic integrity / canonical reconstruction / axiom consistency / extraction provenance / source evidence coverage / semantic preservation / truth of content. Each carries `epistemic_status` (`provable` / `certified` / `empirical-benchmark` / `not-asserted`). Truth of content is ALWAYS `not_asserted` — locked by test. |
|
|
66
|
+
| Negative-control corpus (T5 of bench-hardening) | shipped | 20 hand-authored documents across 5 failure modes (ambiguous coref / predicate-alias / contradictions / entity-resolution-adversarial / non-extractable). Runner exits 1 if observed failures don't match annotations. Baseline at [`fixtures/bench_receipts/negative_control_2026-05-17.json`](fixtures/bench_receipts/negative_control_2026-05-17.json). |
|
|
67
|
+
| Compliance validators (six regimes) | shipped | `sum compliance check --regime <id> --audit-log <path>` — EU AI Act Article 12, GDPR Article 30, HIPAA § 164.312(b), ISO/IEC 27001 A.8.15, SOC 2 CC 7.2, PCI DSS v4.0 Req 10. All six produce the same `sum.compliance_report.v1` schema; per-regime docs at `docs/COMPLIANCE_*.md`. |
|
|
57
68
|
|
|
58
69
|
The slider's product claim — *axis changes do not lose facts* — is the load-bearing empirical result. It is verified by NLI audit on every embedding-flagged "loss" cell; full attribution in [`docs/SLIDER_CONTRACT.md`](docs/SLIDER_CONTRACT.md).
|
|
59
70
|
|
|
71
|
+
## Strategic context
|
|
72
|
+
|
|
73
|
+
The operational compass — read in this order if you want the project's intent + how it operates + where it's going:
|
|
74
|
+
|
|
75
|
+
- [`docs/CHARTER_2026-05-17.md`](docs/CHARTER_2026-05-17.md) — intent, the Why, strategy, objectives, success criteria, constraints, and the operational loop. The compass every other doc resolves to.
|
|
76
|
+
- [`docs/PRODUCT_DELIBERATION_2026-05-14.md`](docs/PRODUCT_DELIBERATION_2026-05-14.md) — three-option strategic analysis + grant-outcome decision tree.
|
|
77
|
+
- [`docs/ZENITH_FRAMING_2026-05-16.md`](docs/ZENITH_FRAMING_2026-05-16.md) — destination framing (SUM as chain-of-custody for AI-transformed knowledge) plus three new concepts (Perspective Receipts, Trust Profiles, Epistemic Nutrition Label) on the design queue.
|
|
78
|
+
- [`docs/BENCH_HARDENING_FROM_QCVV.md`](docs/BENCH_HARDENING_FROM_QCVV.md) — five-task empirical-benchmark hardening plan (T1–T5; T5 shipped, T1–T4 queued).
|
|
79
|
+
- [`docs/DOGFOOD_QUICKSTART.md`](docs/DOGFOOD_QUICKSTART.md) — five-minute guide to running SUM on your own writing.
|
|
80
|
+
|
|
60
81
|
### LLM narrative round-trip — closed across measured corpora (2026-04-28)
|
|
61
82
|
|
|
62
83
|
The hardest measurement in `PROOF_BOUNDARY.md` is the full LLM narrative round-trip (`text → LLM-extract → axioms → LLM-generate → prose' → LLM-extract → axioms'`). The unprompted-pipeline baseline on `seed_v1` was **drift = 107.75% / exact-match recall = 0.12** — facts preserved, keys not.
|
|
@@ -104,7 +125,7 @@ The reverse direction also runs under explicit slider control. The local path ac
|
|
|
104
125
|
sum render --density 0.5 < bundle.json
|
|
105
126
|
# → keeps the lex-prefix half of the axioms; @sliders header records what was requested
|
|
106
127
|
|
|
107
|
-
sum render --length 0.9 --use-worker https://sum.ototao.
|
|
128
|
+
sum render --length 0.9 --use-worker https://sum-demo.ototao.workers.dev --json < bundle.json
|
|
108
129
|
# → LLM-conditioned tome + signed render_receipt (sum.render_receipt.v1) on stdout
|
|
109
130
|
```
|
|
110
131
|
|
|
@@ -131,7 +152,7 @@ pip install 'sum-engine[mcp,sieve]'
|
|
|
131
152
|
|
|
132
153
|
### Calling SUM over HTTP
|
|
133
154
|
|
|
134
|
-
The hosted Worker at `https://sum.ototao.
|
|
155
|
+
The hosted Worker at `https://sum-demo.ototao.workers.dev` exposes `/api/render`, `/api/complete`, `/api/qid`, and the `/.well-known/{jwks,revoked-kids}.json` verification surfaces. [`docs/API_REFERENCE.md`](docs/API_REFERENCE.md) is the wire spec — request/response shapes, error codes, the six-step receipt-verification flow, working Node + Python examples. Use this when the caller is a web app, mobile app, or server-side service; use the MCP server when the caller is a local LLM client.
|
|
135
156
|
|
|
136
157
|
---
|
|
137
158
|
|
|
@@ -167,7 +188,29 @@ Below the slider sits the substrate that earlier phases shipped and verified. Po
|
|
|
167
188
|
- **Bundle public-key attestation (provable).** Ed25519-signed CanonicalBundles are tamper-detectable by any third party in any of the three runtimes. [`docs/PROOF_BOUNDARY.md`](docs/PROOF_BOUNDARY.md) §1.3.1.
|
|
168
189
|
- **Merkle hash-chain integrity (provable, including under concurrent writers).** [`docs/PROOF_BOUNDARY.md`](docs/PROOF_BOUNDARY.md) §1.7.
|
|
169
190
|
- **Extraction F1 (empirical-benchmark).** 1.000 on `seed_v1` (50 simple-SVO docs); 0.762 with precision 1.000 on `seed_v2` (20-doc difficulty corpus). Every remaining `seed_v2` failure is a recall miss, not a truth inversion. [`docs/PROOF_BOUNDARY.md`](docs/PROOF_BOUNDARY.md) §2.1.
|
|
170
|
-
- **
|
|
191
|
+
- **168 numbered features**, each with a reproducible verification command, in [`docs/FEATURE_CATALOG.md`](docs/FEATURE_CATALOG.md).
|
|
192
|
+
|
|
193
|
+
### Research substrate (under `sum_engine_internal/research/`)
|
|
194
|
+
|
|
195
|
+
Less-surfaced but shipped:
|
|
196
|
+
|
|
197
|
+
- **MinHash-LSH bundle similarity index** (`research/lsh/`) — near-duplicate bundle detection at scale.
|
|
198
|
+
- **Robust PCA corruption score** (`research/robust_pca/`) — `corruption_score` field in bundle metadata; flags adversarially-perturbed bundles.
|
|
199
|
+
- **Sequential & conformal-prediction** (`research/sequential/`, `research/conformal/`) — bench-side confidence bounds with documented coverage guarantees.
|
|
200
|
+
- **MMD distribution distance** (`research/mmd/`) — `axiom_distribution_mmd` field on bundles; surfaces when an attested bundle is structurally unlike its baseline corpus.
|
|
201
|
+
- **Spectral entropy** (`research/spectral_entropy/`) — axiom-graph entropy on every bundle, with confidence interval.
|
|
202
|
+
- **Bootstrap multiplier spike detection** (`research/bootstrap/`) — see [`docs/MULTIPLIER_BOOTSTRAP_SPIKE_FINDINGS.md`](docs/MULTIPLIER_BOOTSTRAP_SPIKE_FINDINGS.md).
|
|
203
|
+
- **SMT consistency checking** (`research/smt_consistency/`) — z3-backed `axiom_consistency_check` on every bundle.
|
|
204
|
+
- **Sheaf-Laplacian hallucination detection** — see [`docs/SHEAF_HALLUCINATION_DETECTOR.md`](docs/SHEAF_HALLUCINATION_DETECTOR.md) (research direction).
|
|
205
|
+
|
|
206
|
+
### Other substrate-adjacent surfaces
|
|
207
|
+
|
|
208
|
+
- **Trust-root manifest** (`sum_engine_internal/trust_root/`) — operator-issued signed manifest binding kid lifecycle, revocation policy, and verifier expectations.
|
|
209
|
+
- **Merkle sidecar format** (`sum_engine_internal/merkle_sidecar/`) — see [`docs/MERKLE_SIDECAR_FORMAT.md`](docs/MERKLE_SIDECAR_FORMAT.md).
|
|
210
|
+
- **Evidence-chain layer** (`sum_engine_internal/evidence/`) — substrate behind `source_chain_hash` (T4).
|
|
211
|
+
- **Algorithm registry** — see [`docs/ALGORITHM_REGISTRY.md`](docs/ALGORITHM_REGISTRY.md) (the in-tree list of permitted signing algs; crypto-agility gate).
|
|
212
|
+
- **Audit log format** — every CLI operation can emit `sum.audit_log.v1` events; see [`docs/AUDIT_LOG_FORMAT.md`](docs/AUDIT_LOG_FORMAT.md).
|
|
213
|
+
- **Agent surface** (`sum_engine_internal/agent_surface/`) — see [`docs/AGENT_SURFACE_FINDINGS.md`](docs/AGENT_SURFACE_FINDINGS.md).
|
|
171
214
|
|
|
172
215
|
---
|
|
173
216
|
|
|
@@ -214,7 +257,7 @@ Source anchoring in the bundle schema, bundle explorer / viewer, `sum verify --e
|
|
|
214
257
|
|
|
215
258
|
```bash
|
|
216
259
|
make install # editable install with sieve + dev extras
|
|
217
|
-
make test # full pytest run (
|
|
260
|
+
make test # full pytest run (2000+ tests)
|
|
218
261
|
make xruntime # cross-runtime K1/K1-mw/K2/K3/K4 (Python ↔ Node)
|
|
219
262
|
make xruntime-adversarial # rejection-matrix A1–A6
|
|
220
263
|
make fortress # 21-check pure-math invariants
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "sum-engine"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.7.0"
|
|
8
8
|
description = "SUM — bidirectional knowledge distillation with optional cryptographic attestation. Pipe prose, get a CanonicalBundle (HMAC / Ed25519 / W3C VC 2.0), verify anywhere."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "Apache-2.0" }
|
|
@@ -39,10 +39,19 @@ dependencies = [
|
|
|
39
39
|
[project.optional-dependencies]
|
|
40
40
|
# Dependency-injection extras. Users pick the extractor they want:
|
|
41
41
|
# pip install sum-engine[sieve] # deterministic, offline spaCy path
|
|
42
|
-
# pip install sum-engine[
|
|
43
|
-
# pip install sum-engine[
|
|
42
|
+
# pip install sum-engine[openai] # OpenAI structured-output path
|
|
43
|
+
# pip install sum-engine[llm] # alias for [openai] (legacy name)
|
|
44
|
+
# pip install sum-engine[all] # everything, plus dev tooling
|
|
44
45
|
sieve = ["spacy>=3.7.0"]
|
|
45
|
-
|
|
46
|
+
# `[openai]` is the canonical, vendor-named extra; `[llm]` is kept as a
|
|
47
|
+
# back-compat alias because it predates the multi-provider dispatcher
|
|
48
|
+
# (Anthropic and OpenAI now have their own named extras). Both install
|
|
49
|
+
# identical dependencies — the openai SDK plus pydantic for structured
|
|
50
|
+
# outputs. The vendor adapter is at
|
|
51
|
+
# sum_engine_internal/ensemble/llm_dispatch.py::OpenAIAdapter; the
|
|
52
|
+
# render-path TS companion is worker/src/routes/render.ts::callOpenAI.
|
|
53
|
+
openai = ["openai>=1.40.0,<3.0.0", "pydantic>=2.0.0"]
|
|
54
|
+
llm = ["sum-engine[openai]"]
|
|
46
55
|
# Anthropic Messages-API adapter (Claude family). Installed alongside
|
|
47
56
|
# [llm] for the §2.5 frontier-LLM benchmark runs that compare
|
|
48
57
|
# generator-side interventions across providers. The runner picks
|
|
@@ -107,7 +116,7 @@ dev = [
|
|
|
107
116
|
]
|
|
108
117
|
all = [
|
|
109
118
|
"sum-engine[sieve]",
|
|
110
|
-
"sum-engine[
|
|
119
|
+
"sum-engine[openai]",
|
|
111
120
|
"sum-engine[anthropic]",
|
|
112
121
|
"sum-engine[receipt-verify]",
|
|
113
122
|
"sum-engine[mcp]",
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"""sum_cli.audit_log — universal audit-log streaming for compliance.
|
|
2
|
+
|
|
3
|
+
When the ``SUM_AUDIT_LOG`` environment variable is set to a file path,
|
|
4
|
+
every ``sum attest`` / ``sum verify`` / ``sum render`` operation
|
|
5
|
+
appends a single JSONL row to that file describing what was done.
|
|
6
|
+
|
|
7
|
+
This is the regime-agnostic foundation of the compliance primitives
|
|
8
|
+
direction (Path 3). A specific regime (GDPR-Art-30, HIPAA-164.514,
|
|
9
|
+
EU AI Act Annex IV, etc.) can be implemented as a downstream
|
|
10
|
+
consumer of this audit log: tail the file, validate per-regime
|
|
11
|
+
required fields, raise on policy violation. The audit log itself
|
|
12
|
+
makes no regime-specific assumptions — it records *what happened*
|
|
13
|
+
verbatim so any auditor can reconstruct the operation.
|
|
14
|
+
|
|
15
|
+
Schema: ``sum.audit_log.v1`` — additive; new optional fields may
|
|
16
|
+
appear in future minor versions; consumers should ignore unknown
|
|
17
|
+
keys.
|
|
18
|
+
|
|
19
|
+
Required fields per row:
|
|
20
|
+
- ``schema`` = ``"sum.audit_log.v1"``
|
|
21
|
+
- ``timestamp`` (ISO 8601 UTC, e.g. ``"2026-05-01T18:35:14.123Z"``)
|
|
22
|
+
- ``operation`` ∈ ``{"attest", "verify", "render"}``
|
|
23
|
+
- ``cli_version`` (the ``sum-cli`` version that produced the row)
|
|
24
|
+
|
|
25
|
+
Operation-specific optional fields:
|
|
26
|
+
- attest: ``source_uri``, ``state_integer_digits``, ``axiom_count``,
|
|
27
|
+
``extractor``, ``signed`` (bool — Ed25519 attached?),
|
|
28
|
+
``hmac`` (bool), ``branch``
|
|
29
|
+
- verify: ``state_integer_digits``, ``axiom_count``, ``signatures``
|
|
30
|
+
``{ed25519, hmac}``, ``branch``, ``ok`` (bool)
|
|
31
|
+
- render: ``axiom_count_input``, ``mode`` (``"local-deterministic"``
|
|
32
|
+
or ``"worker"``), ``sliders``, ``render_receipt_kid`` (if
|
|
33
|
+
worker), ``worker_url`` (if worker)
|
|
34
|
+
|
|
35
|
+
Failures (exit code != 0) emit a row with ``error`` field describing
|
|
36
|
+
the failure class. Audit-log writes themselves never fail loudly —
|
|
37
|
+
if ``SUM_AUDIT_LOG`` points at a non-writable path, the operation
|
|
38
|
+
proceeds and the failure is reported on stderr only when ``--verbose``
|
|
39
|
+
is set; the audit semantics fail-open by design (a non-functional
|
|
40
|
+
audit destination should not break the trust loop).
|
|
41
|
+
|
|
42
|
+
Env var precedence:
|
|
43
|
+
1. ``SUM_AUDIT_LOG`` env var (path to JSONL file; appended to)
|
|
44
|
+
2. unset → no audit logging
|
|
45
|
+
|
|
46
|
+
The path may be ``-`` for stdout (rare; mostly useful for piping
|
|
47
|
+
into another tool); otherwise treated as a file path with append-mode
|
|
48
|
+
open.
|
|
49
|
+
|
|
50
|
+
Concurrency: writes are O_APPEND on POSIX, so multiple sum
|
|
51
|
+
processes writing to the same audit log produce a serialised
|
|
52
|
+
ordering (atomic per write() up to PIPE_BUF on most systems —
|
|
53
|
+
single-line JSONL records well under that bound). We write each
|
|
54
|
+
row in one ``f.write()`` call to maximise atomicity.
|
|
55
|
+
"""
|
|
56
|
+
from __future__ import annotations
|
|
57
|
+
|
|
58
|
+
import json
|
|
59
|
+
import os
|
|
60
|
+
import sys
|
|
61
|
+
from datetime import datetime, timezone
|
|
62
|
+
from typing import Any
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
_AUDIT_LOG_SCHEMA = "sum.audit_log.v1"
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _audit_log_path() -> str | None:
|
|
69
|
+
"""Return the configured audit-log destination, or None if unset."""
|
|
70
|
+
p = os.environ.get("SUM_AUDIT_LOG")
|
|
71
|
+
if p is None or p == "":
|
|
72
|
+
return None
|
|
73
|
+
return p
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _identity_fields() -> dict[str, Any]:
|
|
77
|
+
"""Optional identity fields populated from env vars.
|
|
78
|
+
|
|
79
|
+
Sprint 4 of the intensification path to arXiv (PR #140). Closes
|
|
80
|
+
the PCI DSS Req 10.2.2 user-identification gap named in
|
|
81
|
+
``docs/COMPLIANCE_PCI_DSS_4_REQ_10.md``. Three env vars are
|
|
82
|
+
consulted; each populated value becomes an optional field on
|
|
83
|
+
the audit-log row:
|
|
84
|
+
|
|
85
|
+
- ``SUM_AUDIT_USER_ID`` → ``user_id`` field. Per PCI Req 10.2.2,
|
|
86
|
+
"user identification" is the FIRST required field for each
|
|
87
|
+
audit-log event. Operators running SUM behind an
|
|
88
|
+
authenticating proxy populate this from the proxy's session
|
|
89
|
+
identity at process start.
|
|
90
|
+
- ``SUM_AUDIT_HOST_ID`` → ``host_id`` field. Multi-host
|
|
91
|
+
deployments (clusters, k8s pods, container fleets) use this
|
|
92
|
+
to attribute events to specific compute units.
|
|
93
|
+
- ``SUM_AUDIT_IP_ADDRESS`` → ``ip_address`` field. Network-
|
|
94
|
+
layer origination, useful for incident-response / forensic
|
|
95
|
+
analysis under PCI Req 10.2.2's "origination of event"
|
|
96
|
+
requirement.
|
|
97
|
+
|
|
98
|
+
All three are *optional*. An unset env var produces an absent
|
|
99
|
+
field (not a null value). The audit-log schema stays at
|
|
100
|
+
``sum.audit_log.v1``; these are additive optional fields under
|
|
101
|
+
the existing schema's "consumers should ignore unknown keys"
|
|
102
|
+
convention. Backward compat: rows without these fields still
|
|
103
|
+
pass every existing validator.
|
|
104
|
+
|
|
105
|
+
PCI DSS validator R7 (``pci-dss-4-req-10.user-identification-
|
|
106
|
+
recommended``, added in the same PR as this function) treats
|
|
107
|
+
a missing ``user_id`` as a Req 10.2.2 violation in compliance-
|
|
108
|
+
mode runs.
|
|
109
|
+
"""
|
|
110
|
+
out: dict[str, Any] = {}
|
|
111
|
+
for env_var, field in (
|
|
112
|
+
("SUM_AUDIT_USER_ID", "user_id"),
|
|
113
|
+
("SUM_AUDIT_HOST_ID", "host_id"),
|
|
114
|
+
("SUM_AUDIT_IP_ADDRESS", "ip_address"),
|
|
115
|
+
):
|
|
116
|
+
value = os.environ.get(env_var)
|
|
117
|
+
if value: # non-empty (skips both None and empty string)
|
|
118
|
+
out[field] = value
|
|
119
|
+
return out
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def emit_audit_event(operation: str, payload: dict[str, Any]) -> None:
|
|
123
|
+
"""Append a single JSONL row to the audit log if configured.
|
|
124
|
+
|
|
125
|
+
Fail-open: if the audit destination is unwritable, the operation
|
|
126
|
+
proceeds normally; the failure is silent unless verbose stderr
|
|
127
|
+
is enabled by the caller. Audit logging is *advisory* — the
|
|
128
|
+
canonical bundle / receipt still carries the load-bearing trust
|
|
129
|
+
properties; the audit log is for downstream compliance tools
|
|
130
|
+
to ingest.
|
|
131
|
+
|
|
132
|
+
Identity fields (``user_id`` / ``host_id`` / ``ip_address``) are
|
|
133
|
+
populated from env vars by :func:`_identity_fields`. They appear
|
|
134
|
+
on the row only when the corresponding env var is set; absent
|
|
135
|
+
env vars produce absent fields (not null values). The
|
|
136
|
+
``payload`` argument takes precedence over identity fields if
|
|
137
|
+
a caller passes overlapping keys — useful for tests that want
|
|
138
|
+
to pin specific identity values without touching the
|
|
139
|
+
environment.
|
|
140
|
+
"""
|
|
141
|
+
path = _audit_log_path()
|
|
142
|
+
if path is None:
|
|
143
|
+
return
|
|
144
|
+
|
|
145
|
+
from sum_cli import __version__
|
|
146
|
+
|
|
147
|
+
row = {
|
|
148
|
+
"schema": _AUDIT_LOG_SCHEMA,
|
|
149
|
+
"timestamp": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.")
|
|
150
|
+
+ f"{datetime.now(timezone.utc).microsecond // 1000:03d}Z",
|
|
151
|
+
"operation": operation,
|
|
152
|
+
"cli_version": __version__,
|
|
153
|
+
# Identity fields from env, then payload last so the caller
|
|
154
|
+
# wins on overlap (intentional for test seams).
|
|
155
|
+
**_identity_fields(),
|
|
156
|
+
**payload,
|
|
157
|
+
}
|
|
158
|
+
line = json.dumps(row, separators=(",", ":")) + "\n"
|
|
159
|
+
|
|
160
|
+
try:
|
|
161
|
+
if path == "-":
|
|
162
|
+
sys.stdout.write(line)
|
|
163
|
+
sys.stdout.flush()
|
|
164
|
+
else:
|
|
165
|
+
with open(path, "a", encoding="utf-8") as f:
|
|
166
|
+
f.write(line)
|
|
167
|
+
except OSError:
|
|
168
|
+
# Fail-open: audit destination unavailable; do not block
|
|
169
|
+
# the operation. The canonical bundle / receipt remains the
|
|
170
|
+
# load-bearing trust artifact.
|
|
171
|
+
pass
|