Skip to content

A prediction is only a prediction if it was chained first - #69

Merged
StepenkoAnatoli merged 2 commits into
mainfrom
feat/registered-prior
Sep 22, 2026
Merged

StepenkoAnatoli merged 2 commits into
mainfrom
feat/registered-prior

Conversation

@StepenkoAnatoli

Copy link
Copy Markdown
Owner

Step 4: make the oracle habit explicit — registering a verifiable prediction before collecting.

Why it needed a mechanism

Three corpora here carry a prior written before collection, and each is worth more than the finding it precedes. The EUDR one was a year wrong on both dates — the only reason that brief can claim the corpus supplied something the reviewer could not have. The Tavily one held, which is the only reason that brief can say so without it reading as a boast.

The habit was mine and unenforced. Its failure mode is not forgetting — it is writing the prediction afterwards, once the answer is known, and remembering it as foresight. Nobody has to be dishonest for that; "I thought that" is a memory, and memories reshape themselves around what turned out to be true.

An unenforced prior is not weak evidence of foresight. It is none — the honest version and the reconstructed version are the same file.

The guarantee is ordering, and it is cryptographic

research/PRIOR.md holds the text. Registering it chains an op: 'prior' ledger entry carrying its sha256. Two things stop being editable at once, and neither needed new machinery:

  • the text — verifyLedger already hashes whatever a ledger entry names
  • the position — every later entry's prev links to it

Three dishonest paths, each measured on a real corpus

path result
Edit PRIOR.md after registering fail provenance/body-unmodified
Register late via bin/prior.mjs refused, exit 2, nothing written
Chain one late by hand, every hash correct chain verifies — and prior-precedes-collection fails it

The third is why the check exists at all. appendFetch is a public export and will happily chain a prior after the evidence with a perfectly valid chain, so the gate verifies the order itself rather than trusting the CLI was used. Without it, the first two refusals are a fence with a gate left open beside it.

What is deliberately not checked

Nothing grades the prediction — not specificity, not reasonableness, and above all not whether it was right. This is ADR-0013 applied where breaking it would be most tempting: a gate that preferred correct priors would reward hedging and predicting the safe thing. A prior that was wrong has done its job.

The one content rule is a length floor, stated as a floor. It stops "fine". It cannot stop padded nothing, and does not claim to.

Absence is silent — no warning, no passing finding. A warning on every project that skipped an optional step is one nobody reads; partial-render already taught that here. The nudge goes where it can still be acted on: one line from bin/research.mjs before a spending run.

The second commit is the one that matters

Checked before shipping, not after: the remote collector scaffolds a fresh project on the runner, with an empty ledger. A prior registered locally cannot reach the corpus that comes back.

Every corpus in this repository since collect-remote shipped came from that route — including both of the ones that motivated this. So the first commit alone was a discipline for a path nobody takes.

The prediction is now a dispatch input registered on the runner between the map and the collection: through env then an argv array, never the expression engine (ADR-0020), with the topic's measured disclosure profile (ADR-0035) — no run name, no artifact name, absent from every unauthenticated response. collect-remote takes --prior; the MCP tool takes prior; the artifact already carries research/PRIOR.md because it walks research/ rather than a declared file list, checked rather than assumed.

The ordering test is the real guard: if the registration step ever drifts below collect, bin/prior.mjs refuses and the feature stops working silently, on a workflow CI never runs because it spends money. Confirmed red by moving the step.

Honest limits

  • One prior per corpus. A prior you can re-register is one you can retry until it is right. Under ADR-0030 each decision is its own nested project, so each gets its own prediction.
  • It cannot be applied retroactively. The corpora that already exist have no registered prior and never will — which is the whole point. Their priors stay in prose and should be read as the weaker thing they are.
  • The floor is 80 characters and that number is a judgement call, not a measurement.

Verification

  • 888 passed, 0 failed (offline suite)
  • 12 new tests in prior.test.mjs, 2 in collector-workflow.test.mjs; both guards confirmed red before the fix
  • ADR-0039 records the decision and the three measurements

🤖 Generated with Claude Code

StepenkoAnatoli and others added 2 commits September 22, 2026 19:53
Three corpora here carry a prior written before collection, and in each case it
is worth more than the finding it precedes. The EUDR one was a year wrong on
both dates - that is the only reason its brief can say the corpus supplied
something the reviewer could not have. The Tavily one held, which is the only
reason that brief can say so without it reading as a boast.

The habit was mine and it was unenforced, and its failure mode is not
forgetting. It is writing the prediction afterwards, once the answer is known,
and remembering it as foresight. Nobody has to be dishonest for that: "I thought
that" is a memory. An unenforced prior is not weak evidence of foresight, it is
none, because the honest version and the reconstructed version are the same file.

So the guarantee is ordering, and it is cryptographic. The text lives in
research/PRIOR.md; registering it chains an `op: 'prior'` ledger entry carrying
its sha256. Two things stop being editable at once, and neither needed new
machinery - the text, because verifyLedger already hashes whatever an entry
names, and the position, because every later `prev` links to it.

Three dishonest paths, each measured on a real corpus rather than argued:

  edit PRIOR.md after registering    fail provenance/body-unmodified
  register late via bin/prior.mjs    refused, exit 2, nothing written
  chain one late BY HAND, hashes ok  chain verifies, and prior-precedes-
                                     collection fails it

The third is why the check exists. appendFetch is a public export and will
cheerfully chain a prior after the evidence with a valid chain, so the gate
verifies the order itself instead of trusting that the CLI was used. Without it
the first two refusals are a fence with a gate left open beside it.

Nothing grades the prediction. Not its specificity, not its reasonableness, and
above all not whether it was right - ADR-0013 applied where breaking it would be
most tempting, since a gate that preferred correct priors would reward hedging
and predicting the safe thing. The one content rule is a length floor, stated as
a floor: it stops "fine" and cannot stop padded nothing, and does not claim to.

Absence is silent. A warning on every project that skipped an optional step is
one nobody reads - partial-render already taught that here. The nudge goes where
it can still be acted on: one line from bin/research.mjs before a spending run.

The brief quotes it above Intent, because a prior nobody reads next to the
answer is a file nobody opens - and because an author who has just learned they
were wrong should not get to decide whether to mention it.

886 passed, 0 failed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Checked before shipping, not after: the remote collector scaffolds a fresh
project on the runner, with an empty ledger. A prior registered on this laptop
cannot reach the corpus that comes back - the two have nothing in common.

Every corpus in this repository since collect-remote shipped was collected that
way, including both of the ones whose priors motivated the mechanism. So what
landed in the previous commit was a discipline for a route nobody takes.

The prediction is now a dispatch input, registered on the runner between the map
and the collection. It travels through env and then an argv array, never the
expression engine (ADR-0020), and its disclosure profile is the topic's,
measured in ADR-0035: no run name, no artifact name, absent from every
unauthenticated response. It is a sentence about what you expect and must never
carry a credential.

collect-remote takes --prior, the MCP tool takes `prior`, and the artifact
already carries research/PRIOR.md because it walks research/ rather than a
declared file list - checked rather than assumed, since a dropped file would
have come back as raw-missing.

Two tests. The ordering one is the real guard: if the registration step ever
drifts below collect, bin/prior.mjs refuses and the feature silently stops
working on a workflow CI never runs because it spends money. Confirmed red by
moving the step.

888 passed, 0 failed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@StepenkoAnatoli
StepenkoAnatoli merged commit 62ae508 into main Sep 22, 2026
3 checks passed
@StepenkoAnatoli
StepenkoAnatoli deleted the feat/registered-prior branch September 22, 2026 16:56
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.

1 participant