From loom
Birth a fact-anchored RESEARCH.md via relentless grill-me interview, with domain-shift detection that spawns a whiteboard panel per shift and an evaluator-contract-fit fact-check pass before commit. Composes /guild-whiteboard for panel rounds and /guild-validate for the fact-check gate; dispatches the deterministic file IO through `bin/loom research`. Supports human-paired and `--mode=auto` flows with the substrate two-budget(3 rounds × 5 shifts). Use when the user wants a research dossier whose every claim cites a source or observable.
How this skill is triggered — by the user, by Claude, or both
Slash command
/loom:loom-research <topic or short description> [--mode=auto]<topic or short description> [--mode=auto]This skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Birth a research dossier by interviewing the user (or the auto-panel)
Birth a research dossier by interviewing the user (or the auto-panel)
relentlessly, detecting domain shifts in real time, spawning a
whiteboard per shift, fact-checking the synthesized text against an
evidence-anchored rubric, and committing two artifacts via the loom
CLI: RESEARCH.md (synthesized, evidence-anchored) and
RESEARCH-NOTES.md (raw interview + per-engineer whiteboard
contributions). The skill is the research half of the RPI loop — the
output is consumed by /loom-plan (Phase 4) or by /ev-loop-interactive's
inner-RPI hop (Phase 5).
This skill is the canonical entry point for grounded research. The
grill-me posture is fact-anchored — every claim is asked to name its
source or observable before it lands in RESEARCH.md. Opinion-shaped
sentences are flagged at the fact-check gate, not at commit time.
Format references:
docs/AGENT-CONVENTIONS.md § Auto-mode and the two-budget shape
(the convergence rule + the 3 × 5 default for /loom-research).docs/AGENT-CONVENTIONS.md § Recovery from sub-agent failures
(RECOVERY-STATUS.json shape + lifecycle).docs/SUBSTRATE-COMPOSITIONS.md § Capture finding (the griot
integration pathway for [portable] markers).<topic or short description> — what the research is about. Often
ill-defined when the skill starts; the grill-me first half is about
pressing that into concrete questions.--mode=auto (optional) — run without human input. Auto-mode uses
the registered whiteboard roster as the panel and the substrate
two-budget as the convergence cap. See § Human / auto duality.--from-recovery (optional) — explicit resume signal. If
RECOVERY-STATUS.json exists at the project root and the
parent_skill matches /loom-research, the skill offers to resume
(interactive) or auto-resumes (auto-mode) regardless of this flag —
this flag forces the resume path without asking.Bash("griot use --as=llm") to load the learnings rollup
per the substrate startup-brief convention (rollup may be empty;
status line in stdout reports the load result)./loom-plan's slug-proposal step). If the user passed a full
<YYYY-MM-DD>-<slug> form, use it verbatim.projects/<slug>/RECOVERY-STATUS.json:
parent_skill === '/loom-research', surface the
failure context (failed_step, context.shift_number, partial
RESEARCH.md snippet if applicable) and offer to resume. In
auto-mode, auto-accept resume. The resumed run picks up at
context.resume_from (typically the next un-completed shift).parent_skill !== '/loom-research', stop with
an error pointing the user at the named parent skill. Two skills
don't share a single recovery file by design.Treat $ARGUMENTS as the topic. If empty or thin, ask the user what
they're researching. Otherwise summarize back what you heard in one
sentence and ask the user to confirm or refine before pressing into
the interview.
In auto-mode, frame the topic by spawning the registered whiteboard
roster against the topic-as-given (using /guild-whiteboard) and
treating the first round of engineer questions as the frame.
Walk the topic by asking concrete, evidence-seeking questions. For each question:
In auto-mode, the "user" is the whiteboard panel spawned at frame time. Each round, the panel raises 0-N new questions; the skill resolves them one at a time against the panel itself. A round with zero new questions is the silent-panel signal — convergence.
A domain shift fires when both of the following are true:
Both must fire for the same message. Single signals don't trigger a shift — vocabulary drift happens naturally as a domain widens, and "let's talk about X" can be a refinement of the same domain.
Example shifts (both signals fire):
useEffect cleanup semantics, the
user says: "OK let's switch to talking about CSS Modules and the
token pipeline." (cue + ≥ 40% vocab delta — useEffect, cleanup,
subscription → tokens, pipeline, Figma.)runner-minutes,
parallelization, cache → on-call, incident, paging.)BRIN, pg_stat_statements, vacuum → sharding,
Citus, partitioning.)Counter-examples (one signal at most — no shift):
useEffect, the user says: "Let's also
press on whether the useLayoutEffect variant has the same
cleanup behavior." (Cue-shaped phrasing but vocab overlap is high
— same domain, refinement not shift.)When a shift fires, increment the shift counter, capture the new
topic in a one-sentence summary, append an entry to
RESEARCH-NOTES.md under ## Shift N — <topic>, and emit a
research-shift event. Proceed to step 4 for the panel composition.
For each detected shift:
Glob(".claude/agents/whiteboard-*.md"). Engineers self-recuse
off-topic — there's no domain-shape filtering at this layer; the
skill spawns the whole roster and trusts each engineer to declare
inapplicability when it doesn't apply (consistent with the
evaluator non-applicability pattern documented in
agents/evaluator-base.md).projects/<slug>/whiteboards/research-shift-NN-<topic-slug>.md
where NN is the zero-padded shift number and <topic-slug> is
a kebab-case derivation of the shift's one-sentence topic./guild-whiteboard via the Skill tool with
engineers=<resolved roster>, brief=<shift topic + relevant context from the interview so far>, whiteboard=<path>. Emit a
research-panel-spawned event with the engineer list.Append raw per-engineer contributions to RESEARCH-NOTES.md under
the ## Shift N — <topic> heading (verbatim, attributed). Synthesize
the load-bearing signal into RESEARCH.md under a ## Whiteboard contributions section — one synthesized paragraph per shift, each
citing the whiteboard artifact path.
Emit a research-panel-verdict event with:
verdict: 'silent' if no engineer raised a new question this round
(convergence on this shift; move to next shift or to fact-check).verdict: 'questions-raised' with question_count if engineers
raised follow-up questions (resolve them via the interview loop
before moving on; engineers' questions feed back into step 3).[portable] scanAt each whiteboard close, scan each engineer's contribution for
[portable] markers (the convention is documented in
docs/AGENT-CONVENTIONS.md). For each marker found, write a
session-note via § Capture finding (the
bin/griot capture --evaluator-finding=... pathway — the verb's
classification names need extension in a future workstream to cover
whiteboard-portable markers; for now, document the capture intent
here and accept the verb-shape gap as a Phase 7 follow-up).
After the interview converges (silent panel or interview-exhausted shifts), but before the commit:
RESEARCH.md (synthesized from interview
answers + whiteboard contributions)./tmp/loom-research-<slug>.md./guild-validate via the Skill tool with
agents=evaluator-contract-fit and a packet whose Contract section
carries an evidence-anchored rubric: "Every factual claim
cites a source or observable. Opinion-shaped sentences are flagged.
Speculative claims are flagged unless explicitly marked as
hypotheses." Emit a research-fact-check-spawned event.research-fact-check-verdict
event with the verdict shape:
verdict: 'approved' — proceed to step 6.verdict: 'flagged' with flag_count — iterate. In the
interactive flow, grill the user on each flagged claim ("Where
does this come from?"). In auto-mode, the skill iterates by
pressing the panel against each flagged claim's sentence and
rewriting until approved or the round budget exhausts on that
claim.A claim that fails fact-check after the per-decision round budget
(3 rounds) is treated as unresolved — the skill appends it to
UNRESOLVED.md and removes it from the candidate RESEARCH.md.
This is the rare case where the fact-check pass is unable to either
ground the claim or remove it; the skill preserves the per-session
work and surfaces the unresolved item for follow-up.
Write the two candidate files to temp paths:
/tmp/loom-research-<slug>.md ← synthesized RESEARCH.md
/tmp/loom-research-notes-<slug>.md ← raw interview + whiteboards
Invoke:
Bash("loom research <slug-or-topic> \
--research-file=/tmp/loom-research-<slug>.md \
--notes-file=/tmp/loom-research-notes-<slug>.md")
The CLI auto-adopts loom substrate by default and emits
research-started + research-completed events itself (see Phase
3.1). The skill does NOT emit these — they're CLI-owned.
If the CLI errors (research-exists-committed is the common one when
re-running on a committed project), surface the error verbatim and
stop. The user resolves and re-invokes.
One short paragraph in this shape:
Created research dossier: <topic>
Location: projects/<slug>/
Files: RESEARCH.md, RESEARCH-NOTES.md, manifest.json, config.json, events.jsonl, whiteboards/research-shift-*.md
Shifts completed: <N>
Fact-check: <approved | N flagged claims resolved>
Next: run /loom-plan <slug> to compose a PLAN.md grounded in this research, OR cite the dossier from an /ev-loop-interactive inner-RPI hop.
Per docs/AGENT-CONVENTIONS.md § Auto-mode and the two-budget shape,
this skill runs in two modes:
--mode=auto): the registered whiteboard roster
substitutes for the user. Convergence is reached when a round
produces no new questions (silent panel) OR when the
two-budget caps out.The substrate default for this skill (from AGENT-CONVENTIONS.md):
If the per-session shift budget caps out before the topic converges, the skill writes three artifacts at the project root and exits non-zero per the budget-exhausted recovery flow:
RESEARCH.md (whatever was synthesized through the last
converged shift).UNRESOLVED.md — the shifts that did not complete + any
fact-check flags that didn't ground.RECOVERY-STATUS.json — the resume file (see § Recovery flow).The skill also emits a research-budget-exhausted event with
shifts_completed, rounds_completed, and reason: 'shift-budget' | 'round-budget'.
The RECOVERY-STATUS.json file shape, path, single-instance
lifecycle, concurrency assumption, and resume-semantics contract are
documented in docs/AGENT-CONVENTIONS.md § Recovery from sub-agent
failures. This skill follows that shape verbatim; no extension or
override. Skill-specific use of the existing fields:
parent_skill: /loom-research.failed_step and resume_from: one of shift-N (per shift
number), fact-check (per fact-check round), or
sub-agent-spawn (per /guild-whiteboard or /guild-validate
invocation).context: carries the current shift number, the last shift's
one-sentence topic, the path to the partial RESEARCH.md temp
file, and any unresolved fact-check claims that haven't yet
grounded or been moved to UNRESOLVED.md.On re-invocation against a slug with an existing
RECOVERY-STATUS.json whose parent_skill is /loom-research, the
skill reads the file, surfaces the context to the user (or
auto-accepts in auto-mode), and resumes from resume_from. After a
successful resume that produces a committed RESEARCH.md, the skill
deletes RECOVERY-STATUS.json per the convention's removal rule.
The hardcoded research-budget-exhausted write also captures the
failure pattern into the griot learnings system via § Capture finding
(the bin/griot capture --evaluator-finding=<classification> ...
pathway). The current classification surface (recurring plus
generator-antipattern / catalog-gap / evaluator-conflict /
sanctioned-exception as reserved-but-not-yet-implemented) does not
include a precise match for "budget-exhausted research session"; the
skill uses the closest match (catalog-gap once the verb supports it;
falls back to skipping the capture today and emits a one-line
research-budget-exhausted event with the exhaustion detail as the
only record). PLAN.md Phase 3.4 calls this hardcoded write out; the
classification gap is a Phase 7 follow-up.
/loom-plan).research-started and research-completed; the skill emits the
other six. Use bin/loom verbs where possible; for the skill-side
events, append to events.jsonl via the existing events helper
(call bin/loom events append <slug> --event=<name> --detail=<json>
if/when such a verb exists; until then, the skill's emission paths
are documented here for future hardening and the writes are made
via direct file append using the appendEvent shape).projects/<slug>/RESEARCH.md. All
RESEARCH.md / RESEARCH-NOTES.md writes go through bin/loom research. Bypassing the CLI defeats the collision check, the
auto-adopt step, and the CLI-side event emissions.RECOVERY-STATUS.json exists with a different parent_skill: stop
with an error pointing the user at the named skill. Do not try to
resume someone else's recovery./ev-loop-interactive's convention — the skill cannot fulfill its
shift-panel obligation without a registered roster.research-budget-exhausted, then exit non-zero. The next
invocation resumes from RECOVERY-STATUS.json.bin/loom research returns research-exists-committed: surface
verbatim, stop. The Deferred loom revise-research verb is the
future path for revising a committed dossier.npx claudepluginhub krambuhl/agents --plugin loomCreates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.