search-knowledge
Inside a drive, after a round of its plays leaves questions open, close every one the drive's own sources or memory already answer — before anything is built or anyone is asked. Merges the questions a
SKILL.mdcore/components/plays/search-knowledge/SKILL.md
GitHubsearch-knowledge
Close what the loop's sources and memory already answer, so /research-knowledge works only on
what is truly not known.
Pipeline position: none. A member play the Shared Loop Run runs inside a loop's rounds
(R5c), first of /search-knowledge → /research-knowledge → /check-knowledge; it opens and
lands nothing.
Compiled From
This play was compiled from the search-knowledge ICE (reference/ice.md) by create-play
(#686). Intent defines constraints (C1–C4) and failure conditions (F1–F4); the expectation
defines success scenarios (S1–S2), a Done means (D1–D2, baked to stop-condition.yaml), and
one recovery entry per failure condition. To modify this play, update reference/ice.md and
recompile with edit-play.
Do NOT edit this file manually — it is a compiled artifact.
Role
You are the orchestrator. You run the grouping and the check as scripts, and hand the judgment
— confirming the groups, answering from the sources and from memory — to the knowledge-builder
agent through a JSON contract over files on disk. You never raise, decide, apply or promote a
memory update, and you never write the product model.
Agent boundaries:
| Agent | Domain | Skills it invokes | Phases |
|---|---|---|---|
knowledge-builder |
The knowledge a loop's round found missing | find-answers-in-sources |
Search |
knowledge-builder is the single domain agent; it reaches memory only through the memory
tool (search, find, read, cite). Everything else is a script.
Pre-flight
| Check | Constraint | Action on Failure |
|---|---|---|
A loop contract is given and the shared checker accepts it (check_loop_contract.py) |
C4 | Hard halt — this play runs only inside a loop |
Config, stm_base (preflight.py) |
— | Hard halt |
python3 scripts/preflight.py --play search-knowledge --config .garura/core/config.yaml \
--branch "$(git branch --show-current)" > <working>/preflight.json
python3 scripts/check_loop_contract.py --play search-knowledge \
--branch "$(git branch --show-current)" --contract <contract.json> --out <working>/run.json
python3 scripts/session_stamp.py --phase start \
--marker "{stm_base}<issue>/status/session-stamp-search-knowledge.json" \
--cwd "$(pwd)" --branch "$(git branch --show-current)"
<working> is {stm_base}<issue>/context/search-knowledge/round-<n>/ — the contract's issue
and round.
Task DAG
[T1] Group the round's open questions blockedBy: []
[T2] Search the sources and memory blockedBy: [T1]
[T3] Check the search blockedBy: [T2]
[T4] Scenario Validation blockedBy: [T3]
[T5] Close blockedBy: [T4]
Workflow
Phase: Group
Step 1 — Group the round's open questions · Owner: play (script) · Depends on: pre-flight
python3 scripts/group_questions.py --review-dir "<review_dir>" --issue <issue> \
--memory-tool .garura/core/tools/memory/memory.py --out <working>/question-groups.json
SE-1 (F1/C1): question-groups.json lists every open question of the round once — every
open-<play>.json question and every memory update the memory tool lists as waiting for the
issue — and the questions it names as one topic share a group.
Phase: Search
Step 2 — Search the sources and memory · Owner: knowledge-builder · Depends on: Step 1
{ "task": "search: close every open group the loop's sources or memory answer",
"inputs": { "groups": "<working>/question-groups.json",
"sources": ["<the loop's Source evidence folders — for a prototype: views, journeys, the page>"],
"issue": "<issue>",
"check_script": "<play-dir>/scripts/check_search.py" },
"outputs": { "search": "<working>/search.json",
"check_report": "<working>/search-check.json" },
"task_id": "search-knowledge" }
The agent confirms the groups by judgment, gives each one plain question, runs
find-answers-in-sources on every group, then looks up what is still open through the memory tool
and cites what it uses.
SE-2 (F2/C2): every group answered or partly names source (with a quote and its file)
or memory (with its trace); the agent's transcript shows memory reached only through the
memory tool.
SE-3 (F3/C3): every group partly or open names what is missing, and every open group
reads should-show or no-screen.
Phase: Check
Step 3 — Check the search · Owner: play (script) · Depends on: Step 2
python3 scripts/check_search.py --search <working>/search.json \
--groups <working>/question-groups.json --out <working>/search-check.json
Exit 0 — clean. Otherwise send the report back to Step 2 (at most twice), then close HALTED.
SE-4 (F4/C4): run.json reads in_loop: true; every file this run wrote is under
{stm_base}<issue>/; git status shows no change under the product model; the memory tool
lists the same waiting updates as at the start.
Phase: Scenario Validation
Step 4 — Scenario evals · Owner: play · Depends on: Step 3
- SCE-1 (S1 — Discovery loop, many repeated questions):
search-check.jsonreadsok: trueand every question id is in exactly one group. - SCE-2 (S2 — Discovery loop, an answer the prototype holds): a group the prototype answers
reads
found: answered,closed_by: source, with a quote and its file.
Phase: Evidence & Close
Step 5 — Close · Owner: play · Depends on: Step 4
Inside a loop the play closes as a sub-play: its evidence as evidence.record says, no
delivery report of its own, a compact result for the loop (loop contract, step 7).
# --- Standard Play Close (shared; see ../_shared/play-close.md) ---
# Run the close in ../_shared/play-close.md. Its Step L loads the templates through
# template-manager and sets ts and evidence_dest; then run this play's own lines below;
# then Steps C0-C2 (inside a loop: no C2, a compact result for the loop). The Next line
# comes from the Next-line map.
# evidence_base="${stm_base}${issue}/evidence/search-knowledge/" ; slug="#${issue}"
session_stamp=$(python3 scripts/session_stamp.py --phase close \
--marker "${stm_base}${issue}/status/session-stamp-search-knowledge.json")
python3 scripts/check_stop_condition.py --manifest "<play-dir>/stop-condition.yaml" \
--base "<working>/" --out "${stm_base}${issue}/status/stop-condition-search-knowledge.yaml"
sc_exit=$? # 0 held · 1 unmet · 2 error
# --- end Standard Play Close ---
Scenario Validation
| Scenario | Persona | Eval |
|---|---|---|
| S1 — many repeated questions | Discovery loop | SCE-1 |
| S2 — an answer the prototype holds | Discovery loop | SCE-2 |
Recovery
| For | Trigger | Direction | Handoff |
|---|---|---|---|
| F1 | a question in no group or two | regroup from group_questions.py's output and confirm by judgment; re-run the check |
autonomous |
| F2 | a group left open that the source or memory answers, an answer without its quote or trace, or memory read by path | re-run find-answers-in-sources and the memory tool's lookup for it; quote or cite the answer |
autonomous |
| F3 | an open group without what is missing or why | name what is missing and whether the source should show it | autonomous |
| F4 | no loop contract, a write outside the issue, a model write, or a memory update touched | halt; move the record under the loop's issue; undo the write | human |
Pause and Resume
The run's working folder is per round (context/search-knowledge/round-<n>/). On entry, skip a
step whose output exists and checks clean; a round already searched is not searched again.
Compilation Metadata
| Field | Value |
|---|---|
| fingerprint | sha256:51bef1b53df6fa0e500858286781376f46e27205ed2b8c0a4c3ef9e5c395fe4d (of reference/ice.md) |
| compiled_by | create-play (#686) |
| pipeline_position | none (a loop's member play) |
| stop_condition | stop-condition.yaml (D1–D2) |
| domain_agents | 1 (knowledge-builder) |
| skills_used | find-answers-in-sources |
| scripts | 6 (group_questions.py, check_search.py, preflight.py, session_stamp.py, check_stop_condition.py, check_loop_contract.py) + test_search_knowledge_scripts.py |
| step_evals | 4 (SE-1…SE-4) |
| scenario_evals | 2 (SCE-1…SCE-2) |
| recovery_entries | 4 (one per failure condition; 3 autonomous / 1 human) |