Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion plugins/discovery/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
"name": "discovery",
"version": "0.19.8",
"version": "0.19.9",
"description": "Structured discovery before changes: explore the local codebase, run disciplined multi-source external research, and reconstruct why a past decision was made from evidence outside the code \u2014 each dispatching a purpose-built subagent by default so the reading stays out of the main conversation, with source tiers, falsification, recency gates, an intent-evidence tier, and a corpus-coverage ledger \u2014 persisting EXPLORE.md / RESEARCH.md / INTENT.md index-plus-sidecar handoff artifacts.",
"author": {
"name": "Melodic Software",
Expand Down
17 changes: 17 additions & 0 deletions plugins/discovery/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
# Changelog — discovery plugin

## [0.19.9]

### Fixed

- **`explorer`, `explore`:** the explore lane now carries the same preload-miss recovery the
research and trace-intent lanes have. `agents/explorer.md` tells a dispatched explorer to confirm
the skill body is in context before any exploration work and otherwise Read
`skills/explore/SKILL.md` from disk, and its payload gains the `preload: fired | fallback`
provenance field. Previously the agent's only instruction on a miss was to set
`preload_token: MISSING` and stop, and a run that looked for the token in the dispatch prompt or
the memory slice instead ran undisciplined and wrote an artifact shaped like the prompt's
description of the deliverable rather than `EXPLORE.md` plus sidecars. `skills/explore/SKILL.md`
now demotes a matching token to file-identity, grades `preload:` in gate step 1, and treats a
payload without the field as an out-of-date agent definition; `reference/dispatch.md` carries
the rationale; `contract.test.sh` section 11 pins the explore lane beside the other two; the
explore evals gain the fallback-recovery case.

## [0.19.8]

### Added
Expand Down
31 changes: 23 additions & 8 deletions plugins/discovery/agents/explorer.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ of exploration — file reads, Glob results, Grep output, git archaeology — ne
orchestrator's context window. You start with no conversation history by design. Everything you
need arrives in your dispatch prompt.

The `/discovery:explore` skill is preloaded into your context at startup. Its exploration
dimensions, output format, and outcome gate are your procedure. It names a sibling
The `/discovery:explore` skill reaches you through your `skills:` preload, and a preload that fails
is skipped silently, so "Preload liveness" below is the first thing you do. Its exploration
dimensions, output format, and outcome gate are your procedure, not a suggestion. It names a sibling
ecosystem-discovery reference — Read that at the dimension that needs it rather than up front.
That reference composes `/toolchain:check`'s covered-ecosystem set and root
adjacency when the `toolchain` plugin is installed (fallback table when it is
Expand Down Expand Up @@ -72,14 +73,27 @@ downstream edit lands against the project's declared direction.

A `skills:` entry that fails to resolve is skipped **silently**: Claude Code logs a warning to the
debug log and starts you anyway. An undisciplined run that still writes an artifact is
indistinguishable from a good one at every other seam. The dated record for that harness behavior
indistinguishable from a good one at every other seam, which is exactly the failure the token exists
to prevent. The dated record for that harness behavior
is [`${CLAUDE_PLUGIN_ROOT}/reference/parent-contract.md`](${CLAUDE_PLUGIN_ROOT}/reference/parent-contract.md),
"Harness facts the dispatch design rests on".

The preloaded skill declares a **preload token**. Echo it verbatim into `preload_token` in your
return payload. If no skill content reached you — no exploration dimensions, no outcome gate, no
token — set `preload_token: MISSING` and stop with `status: truncated`. Do not reconstruct the
workflow from memory.
Before any exploration work, confirm the skill body is already in your context — its exploration
dimensions, its output format, its outcome gate, and the token it declares. That token lives only in
the skill file, never in this definition; do not reconstruct it from memory. If the body is not in
context, **Read** `${CLAUDE_PLUGIN_ROOT}/skills/explore/SKILL.md` and work under it. The scope, the
slice path, and the reason still come only from your dispatch prompt: a body you Read from disk is
no more a source of them than a preloaded one.

The skill file declares a **preload token**. Echo it verbatim into `preload_token` in your return
payload, and set `preload:` to how the skill body reached you: `fired` if it was already in context
at startup and you did not Read the skill file, `fallback` if you Read it from disk. A matching
token is file-identity evidence that the body reached you, **not** proof that preload fired; the
parent grades `preload:` for that, and `fallback` is the accepted recovery. If no skill content
reached you by either route — no exploration dimensions, no outcome gate, no token — set
`preload_token: MISSING`, omit a fabricated `preload:` value, and stop with `status: truncated`. Do
not reconstruct the workflow from memory. Never treat a token you found by Reading the skill file as
`fired`.

## Tool honesty

Expand Down Expand Up @@ -190,7 +204,8 @@ findings. The 7-section report is what the artifact is for. Your file reads and
here; that is the entire point of dispatching you.

```yaml
preload_token: <echoed verbatim from the preloaded skill, or MISSING>
preload_token: <echoed verbatim from the skill file, or MISSING>
preload: fired # fired | fallback — how the skill body reached you; never inferred from the token

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Set preload provenance in early payloads

When a fallback run is interrupted after following the early-emission instructions at lines 237–242, that checklist tells it to set preload_token but omits preload:; copying this template can therefore leave the default fired value in place, while omitting it makes the newly strengthened gate reject the payload as out-of-date. This defeats the early payload's purpose and can report false provenance precisely on the preload-miss path, so require preload: to be set in the early-emission checklist as the researcher and intent-tracer definitions do.

Useful? React with 👍 / 👎.

scope_as_received: <the scope from your dispatch prompt, verbatim>
status: complete # complete | truncated
persistence: written # written | by-value
Expand Down
21 changes: 21 additions & 0 deletions plugins/discovery/scripts/contract.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,27 @@ assert_present 'research dispatch contract forbids inferring fired from the toke
'skills/research/context/dispatch.md' 'MUST NOT infer'
assert_present 'research evals grade matching-token-is-not-preload-proof' \
'skills/research/evals/evals.json' 'matching-token-is-file-identity-not-preload-proof'
if grep -qE 'discovery-explore-preload-8e2b7d' "$PLUGIN_ROOT/agents/explorer.md"; then
fail 'agents/explorer.md does not embed the preload token'
else
pass 'agents/explorer.md does not embed the preload token'
fi
assert_present 'explorer reads the skill body from disk when preload did not deliver it' \
'agents/explorer.md' 'skills/explore/SKILL\.md'
assert_present 'explorer payload contract carries preload: fired|fallback' \
'agents/explorer.md' 'preload: fired'
assert_present 'explorer never reports a token it Read from disk as fired' \
'agents/explorer.md' 'Never treat a token you found by'
assert_present 'explore SKILL.md demotes the token to file-identity' \
'skills/explore/SKILL.md' 'file-identity, \*\*not\*\* proof that preload fired'
assert_present 'explore SKILL.md requires the structured preload field' \
'skills/explore/SKILL.md' 'preload: fired \| fallback'
assert_present 'explore SKILL.md gate treats a missing preload field as out-of-date' \
'skills/explore/SKILL.md' 'A missing or unrecognized `preload:` field is an out-of-date agent definition'
assert_present 'explore dispatch contract forbids inferring fired from the token' \
'skills/explore/reference/dispatch.md' 'MUST NOT infer'
assert_present 'explore evals grade matching-token-is-not-preload-proof' \
'skills/explore/evals/evals.json' 'matching-token-is-file-identity-not-preload-proof'
if grep -qE 'discovery-trace-intent-preload-7b3e2d' "$PLUGIN_ROOT/agents/intent-tracer.md"; then
fail 'agents/intent-tracer.md does not embed the discipline-liveness token'
else
Expand Down
6 changes: 3 additions & 3 deletions plugins/discovery/skills/explore/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,19 +44,19 @@ These values orient this session only. The project root is an absolute machine p

**One named alternative:** the **built-in Explore subagent**, for raw "where is X / how does Y work" search. Fast, read-only, context-isolated. It skips project memory (convention-blind) and neither runs this 6-dimension workflow nor writes `EXPLORE.md`. Pass key constraints in the prompt when conventions matter, and expect to write the artifact yourself. Scale 1→N by dispatching more, each owning a disjoint area.

**Preload-liveness sentinel.** A dispatched agent receives this body through its `skills:` preload, and a preload that fails to resolve is skipped **silently**. Logged to the debug log and nowhere else. The dated record for that harness behavior is [`${CLAUDE_PLUGIN_ROOT}/reference/parent-contract.md`](${CLAUDE_PLUGIN_ROOT}/reference/parent-contract.md), "Harness facts the dispatch design rests on". A dispatched run therefore echoes this token verbatim as `preload_token` in its return payload:
**Preload-liveness sentinel.** A dispatched agent receives this body through its `skills:` preload, and a preload that fails to resolve is skipped **silently**. Logged to the debug log and nowhere else. The dated record for that harness behavior is [`${CLAUDE_PLUGIN_ROOT}/reference/parent-contract.md`](${CLAUDE_PLUGIN_ROOT}/reference/parent-contract.md), "Harness facts the dispatch design rests on". A dispatched run therefore echoes this token verbatim as `preload_token` in its return payload. The disk fallback Reads this same file, so a matching `preload_token` is file-identity, **not** proof that preload fired:

```text
discovery-explore-preload-8e2b7d
```

A missing or mismatched token is a **hard failure: the parent discards the run**, never downgrades or accepts the artifact. Without it, a preload miss produces an undisciplined run that still writes an artifact. Indistinguishable from success at every other seam.
A missing or mismatched token is a **hard failure: the parent discards the run**, never downgrades or accepts the artifact. Without it, a preload miss produces an undisciplined run that still writes an artifact. Indistinguishable from success at every other seam. Provenance is `preload: fired | fallback`; `fallback` is the accepted recovery, not a discard. Rationale and the parent-side contract: [`${CLAUDE_PLUGIN_ROOT}/skills/explore/reference/dispatch.md`](${CLAUDE_PLUGIN_ROOT}/skills/explore/reference/dispatch.md), "Discipline liveness".

**Post-dispatch acceptance gate. Parent-side, before the payload is believed.** `status: complete` is the agent's claim about its own run, and a claim is not evidence. Grade the run **off disk**, against the memory-slice path from the parent's own pre-dispatch envelope, **carry that path across the dispatch, because it is this gate's input**, and never a path read out of the payload, because the failure this gate exists to catch is a payload that comes back carrying no pointer at all. In order:

**Pre-dispatch:** create the memory slice and touch `<that slice>/.explore-dispatch` as the gate's freshness baseline, then hand that file to the gate as `--newer-than`. Without it a slice that already holds an earlier run's artifact set passes every on-disk check even when this dispatch wrote nothing at all. **Both shell forms of that one command are in [`${CLAUDE_PLUGIN_ROOT}/reference/parent-contract.md`](${CLAUDE_PLUGIN_ROOT}/reference/parent-contract.md) ("The pre-dispatch baseline"). Copy the one matching this session's shell, because the POSIX form's `touch` is not a command in PowerShell and its directory flag is a parameter error there. Same file carries the envelope template this dispatch also owes.** The memory root's self-ignoring `.gitignore` guard is a separate obligation this gate does not grade. Same file, "What this gate does not grade".

1. **The payload is well-formed**. `preload_token` matches the sentinel verbatim, and an `artifact:` pointer is present. Missing either is a **failed dispatch** whatever the `status` field says; a missing token is a discard, per the rule above.
1. **The payload is well-formed**. `preload_token` matches the sentinel verbatim, `preload:` is `fired` or `fallback`, and an `artifact:` pointer is present. Missing token or artifact is a **failed dispatch** whatever the `status` field says; a missing token is a discard, per the rule above. A missing or unrecognized `preload:` field is an out-of-date agent definition, not a pass. A matching token does not prove preload fired; `preload: fallback` is not a discard.

**And `scope_as_received` matches the scope the parent actually sent**. Compared against the envelope the parent wrote, not against what it meant. It is the only check here that fires on an input that is present and wrong. A mismatch is a **failed dispatch**: re-dispatch with the scope restated in a form that survives the trip (see the caveat under **Scope**); do not accept the artifact and mentally translate it. A well-formed payload carrying no `scope_as_received` is an out-of-date agent definition, not a pass.
2. **The artifact set is actually on disk, and this run put it there:**
Expand Down
15 changes: 15 additions & 0 deletions plugins/discovery/skills/explore/evals/evals.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,21 @@
"The payload is treated as a FAILED dispatch, the same class as a by-value payload returning findings instead of artifact bodies, and the ladder continues from the resume or discard rung",
"The response identifies why this path is the sensitive one: the parent holds wider write permission than the sandboxed worker"
]
},
{
"id": 13,
"name": "matching-token-is-file-identity-not-preload-proof",
"prompt": "Explore the item-service command and query handlers before I unify them. [The dispatched discovery:explorer returns a well-formed payload: preload_token matching discovery-explore-preload-8e2b7d, preload: fallback, scope_as_received matching what you sent, status: complete, persistence: written, coverage: complete, artifact: <the slice>/EXPLORE.md, sidecars: 4. check-dispatch-artifact.sh --index-name EXPLORE.md exits 0 against the slice. open_questions includes: 'The token is echoed because I read the skill file from disk, not because it was preloaded.']",
"files": [],
"expected_output": "Accepts the run as a successful fallback recovery. The matching token is file-identity evidence that the skill body reached the agent, not proof that skills: preload fired. The parent grades preload: fallback as provenance and does not infer fired from the token. Does not discard the run, does not warn as if preload succeeded, and does not treat the open_questions prose as the provenance seam. Proceeds to the sibling verifier as on any accepted run.",
"expectations": [
"The matching preload_token is treated as file-identity evidence only — the skill body reached the agent — and is NOT treated as proof that preload fired",
"preload: fallback is graded as the structured provenance field and is accepted; fallback is the recovery, not a failed dispatch",
"The parent does not infer preload: fired from a matching token, even when the agent also discloses the fallback in open_questions prose",
"The run is NOT discarded on the strength of a matching token plus a fallback disclosure; missing or mismatched token remains the discard condition",
"A payload that echoed the token but omitted preload: is an out-of-date agent definition, not a pass, the same class as a missing scope_as_received",
"The artifact set is still graded off disk against the parent's own slice path; fallback provenance changes nothing about the gate's remaining steps"
]
}
]
}
26 changes: 26 additions & 0 deletions plugins/discovery/skills/explore/reference/dispatch.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,32 @@ and what to do when it cannot run, and the resume-before-discard ordering — is
[`${CLAUDE_PLUGIN_ROOT}/reference/parent-contract.md`](${CLAUDE_PLUGIN_ROOT}/reference/parent-contract.md).
This file does not restate it.

## Discipline liveness — why a token at all

A `skills:` entry that is missing or disabled is **skipped silently**: the harness logs a warning to
the debug log and starts the agent regardless. The dated record for that harness behavior is
[`${CLAUDE_PLUGIN_ROOT}/reference/parent-contract.md`](${CLAUDE_PLUGIN_ROOT}/reference/parent-contract.md),
"Harness facts the dispatch design rests on". The resulting run has no exploration dimensions, no
output format, and no outcome gate — and it still reads the tree, still writes an artifact, and
still returns a payload with `status: complete`. At every seam this design builds, that failure is
indistinguishable from success, and the artifact it produces is shaped by the dispatch prompt's
description of the deliverable rather than by the contract.

So the skill file carries a token, the agent echoes it verbatim, and **the parent discards any run
whose `preload_token` is missing or mismatched**. Not downgrade, not warn, not accept-with-a-note:
the artifact of an undisciplined run is worse than no artifact, because it will be read as though
the workflow ran.

The token lives in `SKILL.md` and nowhere in the agent definition. An agent that never received the
skill has no way to produce it. That is **file-identity** evidence: the skill body reached the agent
by some route.

It is **not** preload evidence. The agent's disk fallback Reads this same file before any exploration
work, so a recovered agent echoes the same token a preloaded agent would. Provenance is the
structured `preload: fired | fallback` field. The parent grades that field and MUST NOT infer `fired`
from a matching token. `fallback` is the accepted recovery, not a discard. A missing or unrecognized
`preload:` field is an out-of-date agent definition, the same class as a missing `scope_as_received`.

## Why the gate reads the slice path, not the payload

A dispatched `explorer` can return `status: complete` with a mid-stream narration line as its whole
Expand Down
Loading