Runnable AGENT.md compile loop for scriptorium: drives `scrip` via subprocess + Claude. Not part of the deterministic scrip core.
Project description
scrip-harness — the runnable compile loop
The deterministic scrip keeper does staleness, provenance, and queries. It never
calls a model. scrip-harness is the optional judgment layer that makes the
AGENT.md COMPILE step runnable: it asks Claude to synthesize a wiki
page from a source, then hands every verifiable step back to scrip.
The dependency points one way only: the harness depends on scrip (and the
Anthropic SDK); scrip depends on neither. Removing this directory leaves a fully
valid, fully deterministic vault and CLI behind.
How a compile runs
scrip-harness compile <slug> (for vault/raw/<slug>.md):
- Draft — Claude (
claude-opus-4-8, adaptive thinking, structured output) returns aDraftPage: a title, markdown prose with footnote markers[^a1], [^a2], …, and one verbatim quote per marker. - Mint — each quote goes through
scrip anchor, which fails the compile if the quote isn't present in the source or isn't unique. A hallucinated or paraphrased quote cannot get past this step. - Scaffold + fill —
scrip newwrites the frontmatter; the harness fills the body with the prose + the minted footnote definitions. - Stamp + verify —
scrip stamprecords provenance hashes;scrip verifyproves every citation resolves. If verify fails, the compile errors out rather than leaving a stamped-but-broken page.
So the model owns what to say; scrip owns what is true on disk.
How an extract runs
scrip-harness extract <slug> (for vault/raw/<slug>.md):
- Draft — Claude returns a
DraftExtraction: structured claims, each with a verbatim quote, a subject/predicate/object triple, and a polarity. - Mint + append — the claims go to
scrip fact add --stdin, which verifies every quote (minting anchors), assigns ids and timestamps, skips exact duplicates, and appends all-or-nothing under the write lock. - Retry — if quotes come back BROKEN/AMBIGUOUS, the failures go back to Claude for one replacement per failure (lengthened until unique, or an empty quote to drop the claim); bounded retries, then the extract fails cleanly.
- Stamp + verify —
scrip stamp vault/facts/_meta.yaml, thenscrip verify; contradiction candidates fromscrip query contradictionsare surfaced for the operator to RECONCILE per AGENT.md.
How a promote runs
scrip-harness promote <slug> (for a compiled vault/wiki/<kind>s/<slug>.md):
- Score —
scrip similarranks existing pages by overlap (shared sources + title tokens + derived tags) with the candidate, excluding itself. - Band the top score: ≥
--merge-threshold(0.5) → merge into it, deterministically (no model); <--keep-threshold(0.25) → keep the page as its own; in between → Claude decides merge-vs-keep over the small candidate set (the only model call in PROMOTE). - Merge — append the candidate into the target (its
[^a1]..footnotes renumbered to avoid collision), union thederived-from, record the absorbed id insupersedes, delete the absorbed page, thenscrip stamp+scrip verify.--dry-runprints the decision and mutates nothing.
How an answer runs
scrip-harness answer "question" makes the ANSWER rung executable:
- Preflight —
scrip status,scrip verify, andscrip query contradictionsmust be clean by default. Stale artifacts, broken anchors, or open contradiction pairs stop the answer before any model call. - Gather — the harness ranks claims from
facts/, reads relevant compiled wiki pages as context, and falls back toscrip searchwhen compiled evidence is thin. - Draft — Claude answers from that bounded evidence packet and returns
structured citation records: either an existing
claim_idor a verbatim raw quote. - Verify citations — claim citations are resolved with
scrip span; raw quotes are minted withscrip anchor. Unsupported citations fail the answer.--savewrites a verified note underwiki/explorations/.
How a reconcile runs
scrip-harness reconcile (over every open contradiction):
- Find —
scrip query contradictionslists the candidate pairs (same subject+predicate, opposing polarity, different sources, not yet adjudicated). - Read — for each pair,
scrip span --claim <id>fetches both verbatim cited spans, and Claude decides supersede (with a winner), qualify, or keep-both, with a rationale. - Record — the decisions are written append-only with
scrip fact add --table reconciliations(existing claim rows are never rewritten), logged towiki/log.md, thenscrip stamp+scrip verify. Adjudicated pairs stop being surfaced byscrip query contradictions.--dry-runprints the decisions without recording.
Install & run
Both packages are on PyPI. scrip-harness bundles scriptoria as a dependency
and drives it through its own interpreter, so it is self-sufficient — install
scriptoria as a tool too only if you want the scrip command on PATH for
direct use:
uv tool install scrip-harness # this package → `scrip-harness` (pulls scriptoria)
uv tool install 'scriptoria[ingest]' # optional: `scrip` on PATH + HTML/PDF ingest
export ANTHROPIC_API_KEY=... # the harness calls Claude; scrip never does
scrip-harness compile article # synthesize + verify a page from raw/article
scrip-harness extract article # pull claims into facts/
scrip-harness answer "What does the corpus say about caching?"
scrip ingest <url> --slug article # bring a source in (needs the install above)
(From a checkout, uv tool install ./scrip and uv tool install ./harness
install the local versions instead.)
Develop / test
cd harness && uv run pytest # hermetic: the model is stubbed; scrip runs for real
The tests inject a stub draft function (no network, no API key) and drive the real
scrip subcommands over a temp vault, asserting the result is stamped and verified.
Scope & limits (v1)
- Covers COMPILE (one source → one wiki page), EXTRACT (one source →
claims in
facts/, with the bounded quote-retry loop), ANSWER (fresh compiled evidence first, raw search on miss, verified citations), PROMOTE (score → merge/keep, model only in the middle band), and RECONCILE (adjudicate every contradiction → record the decision). Entities/edges go throughscrip fact add --table entities|edgesby hand. - Single source per page/extract; merge is append (not re-synthesis).
reconcilerecords the decision (supersede/qualify/keep-both); for a qualify, authoring the nuancingpolarity: qualifiesclaim + the page caveat is still operator follow-up. Multi-source synthesis, and adopting the quote-retry loop in COMPILE too, are future work.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file scrip_harness-0.6.0.tar.gz.
File metadata
- Download URL: scrip_harness-0.6.0.tar.gz
- Upload date:
- Size: 70.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.24 {"installer":{"name":"uv","version":"0.11.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ba98ef785624929b9efc1c9e774a093cd3ef6733806bb312ea7859e56da3242e
|
|
| MD5 |
f02b72f91929d19086763ba36fc238a2
|
|
| BLAKE2b-256 |
c2fd560b47e4da2fd95a4580bd1cff7df04c08592b9b4f05172555fdb78af765
|
File details
Details for the file scrip_harness-0.6.0-py3-none-any.whl.
File metadata
- Download URL: scrip_harness-0.6.0-py3-none-any.whl
- Upload date:
- Size: 25.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.24 {"installer":{"name":"uv","version":"0.11.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ae471949151d16f7e889232d20c7b3fce4bd4a1a2530d825ce4b60703692543d
|
|
| MD5 |
d45b42c794c760f7c455761455ea2dec
|
|
| BLAKE2b-256 |
5621c612f85611bac29c5cf76b3f2f3f44ee64e22c82aa88f296c1c91900bd0b
|