External-evidence layer, and one of the two EXECUTORS (task is the other โ same shape, same rules). One research topic = one discovery-folder running Plan -> Build(opt) -> Execute -> Report, typed Search | Review | Idea; buckets 1_search/2_review/3_idea are the Execute workers, 1:1 with the types. PROBE-UNAWARE but not question-deaf: the `qa` verb (/haipipe-discovery qa "<question>") takes ONE question in general language and returns discoveries/<discovery-group>/<discovery-folder>/QA/<n>-<slug>.md โ the discovery-folder's readable digest of a direction it has explored. A QA file carries ONE mutable `state:` line (working | answered | superseded-by:): written at the qa gate's โข decision, completed at Report โ ONE WRITER, this layer, always. A `working` file means SOMEONE IS ALREADY ON IT: do not duplicate the work. Trigger: discover, find paper, lit review, ๆพidea, ๆฅๆฐ, source, verdict, landscape, qa, QA file, state, working, claim, superseded, /haipipe-discovery.
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
A direct command skips the review prompt. Inspect the source before running it.
External-evidence layer, and one of the two EXECUTORS (task is the other โ same shape, same rules). One research topic = one discovery-folder running Plan -> Build(opt) -> Execute -> Report, typed Search | Review | Idea; buckets 1_search/2_review/3_idea are the Execute workers, 1:1 with the types. PROBE-UNAWARE but not question-deaf: the `qa` verb (/haipipe-discovery qa "<question>") takes ONE question in general language and returns discoveries/<discovery-group>/<discovery-folder>/QA/<n>-<slug>.md โ the discovery-folder's readable digest of a direction it has explored. A QA file carries ONE mutable `state:` line (working | answered | superseded-by:): written at the qa gate's โข decision, completed at Report โ ONE WRITER, this layer, always. A `working` file means SOMEONE IS ALREADY ON IT: do not duplicate the work. Trigger: discover, find paper, lit review, ๆพidea, ๆฅๆฐ, source, verdict, landscape, qa, QA file, state, working, claim, superseded, /haipipe-discovery.
argument-hint
[verb|type] [discovery] [args...]
allowed-tools
Bash, Read, Write, Edit, Grep, Glob, Skill
metadata
{"version":"0.3.4","last_updated":"2026-07-19","summary":"Two-axis discovery: uniform Plan/Build/Execute/Report lifecycle x 3 folder types (Search/Review/Idea), mirroring task. Each type has a specialist skill (haipipe-discovery-search/-review/-idea) heading its bucket. Self-contained folders (no parent field); contract = discovery.yaml + evidence files + the OPTIONAL QA/ folder. v3.1 โ THE QA FILE GAINS ONE MUTABLE FIELD, a `state:` line, and becomes a TICKET THAT BECOMES A RECEIPT (JL ruling 2026-07-14; probe SKILL 8.2.0 PART 3a R19/R20/R21). THE HOLE IT CLOSES: two consumers ask the same question a week apart; the first dispatches an expensive lifecycle run; the second, while that run is STILL GOING, sees no QA file and dispatches THE SAME RUN AGAIN โ because a QA file used to be written ONCE, at Report, complete, and its EXISTENCE was the only signal. Now: `- state: working | answered | superseded-by: QA/<m>-<slug>.md` + `- started: YYYY-MM-DDTHH:MM` (MANDATORY on a working file) + optional `- by:`. Gate โข LIFECYCLE now CLAIMS FIRST (writes the QA file with `state: working` + `started:` + an EMPTY `## Answer` under `set -C` noclobber) and COMPLETES it at Report (`state: answered` + the body). Gate โ SCAN branches on the state line (answered โ path ยท working โ 'in progress since <started>', DO NOT RE-RUN ยท working+EXPIRED โ zombie, RESTART ยท superseded-by โ follow the chain to the live answer). Gate โก DIGEST still writes ONCE, complete, `answered` โ no claim, nothing to race. THE LOAD-BEARING INVARIANT IS *ONE WRITER*, NOT *WRITE-ONCE*: two writes by the same owner is fine; a CONSUMER creating/claiming/editing a QA file is the retired _ASK/ stub in a QA/ costume and is FORBIDDEN. TTL = the named constant QA_WORKING_TTL_HOURS = 24 (a `working` file with no `started:` can never expire and is a zombie by construction). RACE GUARD = `set -C` and nothing more โ the loser re-scans and defers; no lock dirs, no lease servers, no ledgers. SUPERSESSION: a re-run whose answer CHANGES writes QA/<n+1> and APPENDS `superseded-by:` to the old file's state line โ R15 (ENRICH never mutates) still holds FOR THE BODY; only the state line is mutable, and only its own owner edits it. Checker HARD-FAILs: qa-working-no-started ยท qa-working-expired ยท qa-answered-empty (+ the consumer-side read-target-working / read-target-superseded). Every field name, state value, TTL constant and flag spelling is CHARACTER-IDENTICAL to the task twin. v3.0 (Tools/plugins/haipipe-toolkit/diagram/260714-probe-qa/ v3, R2/R9/R10/R11/R17/R18): THE BANK IS PROBE-UNAWARE โ _ASK/ stubs, `answers:` and every PP id DELETED; the `qa` VERB (fn/qa.md) is the one question door โ gate โ QA SCAN โ โก DIGEST โ โข lifecycle (depth ladder: read | enrich | new folder | new group) โ ๐ซ REFUSE (task-shaped โ /haipipe-task qa), returning <discovery-folder>/QA/<n>-<slug>.md (numbered = the index, slug only, three legal reasons to exist). R17 TWO SESSION MODES: this layer's PRIMARY mode is its own autonomous lifecycle โ qa is a SIDE door, and answerability work (digests, reusable source bases) is native executor work. R18 TWO EXPLORERS: a human via the verb, and the orchestrator agent (commissioned by a probe's dispatch, or self-directed) โ both probe-unaware, same gate, same files. A Review-type verdict.md is this layer's OWN terminal and SURVIVES (it is not the retired probe 'Verdict'). v6.2/v3.2 (R19 HARDENING): gate โ now READS THE STATE LINE **BEFORE** the literally-answers test. A `working` file's ## Answer is EMPTY BY CONSTRUCTION, so testing it for an answer is a guaranteed miss that drops through to โข and RE-RUNS the job someone is already running (a new <n>, a different slug, `set -C` never fires) โ the duplicate run, executed by obeying the rules. A `working` file is matched on its `# Q โ` LINE instead. A QA file with NO `- state:` line is MALFORMED, not legacy (checker: qa-no-state): this layer OWNS it, so it REPAIRS it (tag `answered` if the Answer has a body, else RESTART as a zombie). The same-<n>/different-slug claim race is NON-FATAL BY RULING and is NOT a reviewer REVISE โ the reviewers now carry the exemption explicitly."}
Skill: haipipe-discovery (orchestrator)
Single entry for the discovery layer: what the outside world already knows (Search gather, Review analyze) and the new angles drawn from it (Idea create). Discovery is external evidence work, not a task execution stage. Durable evidence lives under discoveries/; whoever needs it references it from their own side โ this layer never references upward.
Discovery is one of the two EXECUTORS (task is the other). Same shape, same rules: it runs a lifecycle for its OWN sake, it is PROBE-UNAWARE, and it answers plain questions through its own qa verb. See "Two session modes" below.
Verbs
/haipipe-discovery -> dashboard: render this verb list + the Model line, suggest the likely next command
/haipipe-discovery <discovery> -> run full lifecycle on a folder
/haipipe-discovery <discovery-group> -> iterate/summarize children
/haipipe-discovery status [path] -> read-only status
/haipipe-discovery open <type> <question> -> scaffold a typed discovery-folder (type = Search | Review | Idea)
/haipipe-discovery open-group <slug> -> ensure discovery-group dir
/haipipe-discovery plan <discovery> -> (re)write discovery.yaml
/haipipe-discovery build <discovery> -> author the optional instrument (build/)
/haipipe-discovery execute <discovery> -> do the work, write the terminal file
/haipipe-discovery report <discovery> -> append the report block + log event
/haipipe-discovery qa "<question>" [<discovery-folder>] -> THE QUESTION DOOR: answer ONE general-language
question -> <discovery-folder>/QA/<n>-<slug>.md (see fn/qa.md)
/haipipe-discovery feedback "<text>" | list [unit] | move <file> <unit> -> skill-feedback inbox (see Feedback)
/haipipe-discovery digest ["<session-name|id>"] [--dry-run] -> harvest a session's feedback (see Feedback)
/haipipe-discovery <specialist> [args] -> one-off worker dispatch (NO folder)
/haipipe-discovery "<natural language>" -> infer + dispatch (Routing)
The qa verb โ the question door (R11)
Full contract: fn/qa.md. In one screen:
/haipipe-discovery qa "<question>" [<discovery-folder>] [--check-only]
input: ONE question, GENERAL language. NO PP id, NO paper ref, NO stake, NO claim id.
The verb never learns WHO asks or WHY. It answers questions. That is all.
โ QA SCAN grep <discovery-folder>/QA/*.md (or all discovery-folders). MATCH ON THE ANSWER, never the
topic: READ the file. Then READ ITS STATE LINE: ~0
state: answered -> return the QA file PATH
state: working -> SOMEONE IS ALREADY ON IT. Return the path +
"in progress since <started>". DO NOT RE-RUN.
working, EXPIRED past QA_WORKING_TTL_HOURS -> ๐ง zombie: RESTART it
superseded-by: X -> follow the chain, return the LIVE answer
โก DIGEST sources.md / notes.md / verdict.md / landscape.md / ideas.md already
answer it, but no readable digest exists -> write QA/<n>-<slug>.md
ONCE, COMPLETE, `state: answered`, from EXISTING artifacts. cheap
No searching, no new judgment. No claim โ nothing to race.
โข LIFECYCLE neither -> โ CLAIM FIRST (write the QA file with `state: working` +
`started:` under `set -C`), then Plan โ Build(opt) โ Execute โ Report
at the SHALLOWEST depth that answers it, and COMPLETE the same file at
Report (`state: answered` + the `## Answer` body):
depth 0 READ ยท depth 1 ENRICH (on-topic, same discovery-folder) ยท
depth 2 NEW FOLDER (in the group) ยท depth 3 NEW GROUP
๐ซ REFUSE not discovery-shaped -> the CALLER re-routes. RELEASE any claim.
task-shaped (code / runs / metrics on our own data) -> /haipipe-task qa
THREE CALLERS: a probe's DISPATCH (via the orchestrator agent) ยท a HUMAN directly ยท
the ORCHESTRATOR itself (self-directed). None of them is special.
The commission lives in the CONSUMER's own probe file; this layer only ever sees a plain
question, and nothing under discoveries/ carries a trace of who asked.
Two session modes (R17) โ the primary mode is NOT question-driven
โ๏ธ THIS LAYER (executor) ๐ the CONSUMER (paper / application)
โโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโ
just runs Plan โ Build โ Execute โ raises its questions, matches them
Report on its own research topics against this bank, commissions the gaps
โ no question needed, no ask (its probe files hold the stake; we
โ never see them)
โผ โ
the bank grows AUTONOMOUSLY โโโโโโโโโโโโโโโโโ most questions should already
discovery.yaml ยท sources.md ยท terminals be ANSWERED before anyone asks
โ
โโ ANSWERABILITY WORK (native, probe-unaware):
ยท write QA/ digests for notable findings
ยท build reusable source bases so future questions are CHEAP
it does not know WHICH questions will come. It makes the bank
EASIER TO ASK. That is discovery-native work.
The Model
Two axes, same as task: LIFECYCLE Plan -> Build(opt) -> Execute -> Report (uniform, process verbs) ร TYPE Search ยท Review ยท Idea (folder kinds; each type maps 1:1 to its bucket). The type only changes what Execute produces:
Search INPUT search + read source material -> sources.md + notes.md (reusable source base)
Review PROCESS judge a claim OR map a field -> verdict.md (judge) / landscape.md (synthesize), role: picks
Idea OUTPUT generate ideas OR check novelty -> ideas.md (idea_generation) / verdict.md (novelty_check)
The CANONICAL contract lives in ONE place โ per-stage IO and the chain: ref/lifecycle-map.md; fields, roles, terminal templates: ref/discovery-yaml-schema.md. Do not restate them here. A one-off capability call does NOT create a folder; the discovery-folder is only for durable, project-tracked topics โ the same split as a quick script vs a scaffolded task-folder.
The discovery-folder, in full โ the QA/ folder is OPTIONAL and every discovery-folder may carry one (R9):
discoveries/P01_trait-opioid-prior-art/02_agreeableness-rx-prior-art/
โโโ discovery.yaml Q โ the spec (Plan writes ยท Report appends report:)
โโโ build/ the optional instrument
โโโ sources.md A โ raw evidence โ
โโโ notes.md A โ what was read โ the layer's own terminals; a
โโโ verdict.md A โ the TERMINAL โ Review verdict.md is OURS and SURVIVES
โโโ QA/ A โ READABLE digests ๐ optional, not every discovery-folder has one
โโโ 1-trait-rx-prior-art.md
โโโ 2-dose-response-coverage.md
A QA FILE IS A TICKET THAT BECOMES A RECEIPT. It carries exactly ONE mutable field โ
the state line โ and everything below it is written once and never touched again:
# Q โ <thequestion, restatedbytheexecutorinitsownwords>- state: working | answered | superseded-by: QA/<m>-<slug>.md
- started: 2026-07-14T09:12 โ MANDATORY when state: working
- by: <runid | agent | human> โ optional provenance
## Answer EMPTY while state: working. Filled at REPORT.## Caveats## Not-done
NAMING IS THE INDEX. QA/<n>-<slug>.md, n = creation order. `ls QA/` IS the index โ
numbered, ordered, greppable. It now reads as a menu of BOTH: what this discovery-folder has
established, AND what it is establishing right now. No INDEX file until a discovery-folder's QA
count earns one.
SLUG ONLY. No PP id, no claim id, no paper ref in a bank filename โ ever.
โ ๏ธ THE LOAD-BEARING INVARIANT IS *ONE WRITER*, NOT *WRITE-ONCE*.
This layer writes the file TWICE โ the CLAIM at the qa gate's โข decision
(state: working + started:), the COMPLETION at Report (state: answered + the
## Answer body). Two writes by the SAME OWNER is fine.
โ A CONSUMER (probe / paper / application) must NEVER create, claim, edit,
complete, or supersede a QA file. A consumer-planted `working` file is the
retired _ASK/ stub wearing a QA/ costume, and it is FORBIDDEN.
WRITER: this layer. Only gate โข ever produces a `working` file, and only transiently
(gate โ writes nothing; gate โก writes once, complete). Anatomy + the three
legal reasons a QA file may exist (commissioned ยท digest-only ยท executor's
own): fn/qa.md.
THE CLAIM MUST EXPIRE. `started:` is MANDATORY on a `working` file โ a claim that
cannot expire is a zombie by construction. TTL = the named constant
QA_WORKING_TTL_HOURS = 24. Past it the claim is STALE and the next qa call may
RESTART it (fresh started:, abandoned attempt recorded in ## Not-done).
RACE GUARD. Create the claim under `set -C` (noclobber). The loser re-scans and
DEFERS. No lock dirs, no lease servers, no ledgers.
SUPERSESSION. A later run whose answer CHANGES writes QA/<n+1>-<slug>.md and APPENDS
`superseded-by:` to the OLD file's state line โ by this layer, never by a consumer.
A QA file's BODY is never edited. The state line is the ONE mutable field.
STATUS reads the STATE LINE, not mere existence:
no QA file -> not answered
state: working -> IN PROGRESS (since <started>)
state: answered -> answered
superseded-by: X -> answered, but STALE โ the live answer is X
โ ABUSE GUARD: a QA/ that mirrors every source is noise, not an index.
โ LAW 2 (bank surface): a QA file carries NO consumer vocabulary โ no C\d, no H\d,
no "claims-stage", no "the paper" meaning someone's paper. Write it for the NEXT
reader, who has a different stake, or none.
โ THE CHECKER HARD-FAILS three defects THIS layer can write:
qa-working-no-started (unexpirable `working` file) ยท qa-working-expired (zombie past
QA_WORKING_TTL_HOURS) ยท qa-answered-empty (`state: answered` with an EMPTY
## Answer โ a lying receipt).
Group letters are purpose hints, not the source of truth (type:/role: in discovery.yaml are authoritative). Three purposes, one routing question each:
S source base just building a pile of sources? (mostly Search)
L landscape understanding a field / context? (mostly Review synthesize, Idea)
P proof / prior art testing a specific claim against outside? (mostly Review judge, Search)
Buckets (Execute-stage workers)
Three buckets, 1:1 with the types, each HEADED by a type-specialist skill that owns that type's Execute procedure and output contracts (the Review Output Contract lives in haipipe-discovery-review) and picks among the workers beside it:
Bucket aliases: 1|search, 2|review, 3|idea|novelty. (Reading is part of searching โ no separate read alias.)
Routing
0. First positional is `qa` -> route to fn/qa.md BEFORE any other parsing. Everything after
it is ONE general-language question (+ an optional discovery-folder path, + --check-only). Never
re-interpret a qa question as a routing keyword.
1. First positional is a lifecycle verb (open / open-group / plan / build / execute / report / status)
-> durable operation on the folder. `feedback` and `digest` route to fn/feedback.md /
fn/digest.md BEFORE any other parsing; neither scaffolds a folder.
2. First positional is an existing path: discovery-folder -> run requested stage or full
lifecycle; discovery-group -> iterate/summarize children.
3. `open <type>` where type โ {Search, Review, Idea} -> scaffold that typed folder.
4. First positional is a specialist name -> dispatch that worker (one-off, NO folder).
5. arXiv ID / URL in args -> a 1_search read worker:
"summarize|explain" -> alphaxiv ; "section|layered" -> deepxiv ; "analyze|claims" -> paper-analyzer
bare ID, no verb -> alphaxiv
6. First positional is a bucket alias -> use that bucket.
7. Keyword scan (pick a worker for a one-off, or infer a folder type):
"preprint|arxiv" -> arxiv (Search)
"IEEE|ACM|venue|citation" -> semantic-scholar (Search)
"web|blog|news|exa" -> exa-search (Search)
"review|survey|landscape|map the field|related work" -> research-lit (Review synthesize)
"prior art|is X known|does X exist|already done" -> Review judge (verdict)
"novelty|is this idea new|ๆฅๆฐ" -> novelty-check (Idea, role novelty_check)
"brainstorm|find idea|ๆพidea|propose" -> idea-creator (Idea)
8. Bucket resolved, specialist unresolved -> bucket default
(1_search: arxiv to find, alphaxiv to read one paper | 2_review: research-lit | 3_idea: idea-creator).
9. Nothing resolves -> ask: Search (gather) / Review (judge or map) / Idea (generate or check)?
Dispatch: Skill(<specialist>, args="..."); do not auto-chain. Type-level work goes to the type specialists โ they pick workers and carry the output contracts.
Protocol (durable project work)
Walk the lifecycle stages; never hand-place a completed discovery package.
Step 0 Resolve project root = nearest ancestor with tasks/, paper/, applications/, or _haipipe/.
If ambiguous, ask (AUTO -> blocked).
Step 1 Resolve scope: folder (has discovery.yaml) -> run stage(s); group -> iterate;
open-group -> create container; open <type> <question> -> scaffold; specialist -> one-off.
Step 2 Group: purpose letter (S/L/P) + next free two-digit id (no renumbering).
Step 3 Folder: next free NN_<slug>/ in the group. One topic per folder; slug names the TOPIC.
Step 4 Run the stages (each owns its files):
Plan write discovery.yaml (type + role + question + sources + expected_outputs).
The QUESTION is the whole contract โ whether it came from this layer's own
research agenda, from a human, or verbatim from a caller's dispatch. It
arrives in GENERAL language and it is answered on its own terms; there is
no stub to read and nothing upward to look at.
NO parent field โ self-contained; append discovery.opened to _haipipe/project.log.jsonl
Build (optional) author the instrument under build/; set status building
Execute dispatch the TYPE SKILL โ Search -> haipipe-discovery-search,
Review -> haipipe-discovery-review, Idea -> haipipe-discovery-idea;
inspect local project evidence first unless fresh web search was asked; set status executing
Report APPEND the report: block (absent until now; outcome != lifecycle status);
set top-level status (ok / inconclusive / blocked);
THE QA FILE โ QA/<n>-<slug>.md, for exactly one of the three legal
reasons (commissioned ยท digest-only ยท executor's own):
ยท came in via gate โข -> the CLAIM already exists on disk
(state: working + started:, empty ## Answer, written at the โข
decision BEFORE Plan ran). COMPLETE it here: rewrite the state line
to `state: answered` and fill the `## Answer` body. That is the
SECOND and LAST write, by the same owner.
ยท came in via gate โก -> CREATE it here, ONCE, COMPLETE,
`state: answered`. No claim was needed โ the write is instant.
THE EXECUTOR HOLDS THE PEN: whoever asked may have CAUSED this file, but
this layer AUTHORS it โ both writes โ in general language, with no
consumer vocabulary in it (fn/qa.md ยท LAW 2). A CONSUMER never writes
a QA file, and never touches its state line;
append discovery.completed to the project log
Handoff return the terminal path (+ the QA file path, if one was written) to the
caller; the CALLER records the link on its own side and appends
discovery.consumed โ the discovery records nothing upward. No `answers:`
field, no ask mailbox, no id of any kind: whoever asked harvests the path
on their own schedule.
Step 5 Return: {status, discovery_group, discovery_folder, type, files_written, qa_file, next}.
Feedback
feedback / digest are utility verbs about THIS skill (not about discovery findings); capture-only โ fixing is a later revision pass. Full contract: fn/feedback.md + fn/digest.md; fallback inbox: feedback/README.md.
capture feedback "<text>" -> route to the unit's feedback/ inbox: cross-cutting guard first
(lifecycle/type-field/schema-wide -> THIS folder's feedback/),
else keyword -> unit, else active context, else fallback.
Units: 1_search ยท 2_review ยท 3_idea ยท agents. MERGE-OR-CREATE:
same-topic items update the existing file (dated recurrence,
verbatim history, reopen if fixed), never duplicate.
list feedback list [unit] -> aggregate open items across ALL inboxes, grouped by unit.
move feedback move <file> <unit> -> re-route a mis-filed item (pure file move).
digest digest [session] [--dry-run] -> scan a session transcript (past by name/id, else current)
for conversational feedback; distill, dedup, MANDATORY confirm
gate, then route each item through capture. Global behavioral
prefs go to /remember, not inboxes.
Behavioral Preferences (portable)
ALWAYS read and honor PREFERENCES.md in this skill's folder: git-tracked global behavioral preferences that survive a machine change, kept in sync across orchestrators by /haipipe-paper digest's global-pref fan-out.