Interview Skill

SkillDev tools

Use when onboarding a new product/project. Progressive interview to understand purpose, vision, north star, and competitive landscape.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Interview Skill skill

What this skill tells your AI

The instructions your AI receives, as published by haabe/mycelium in plugins/mycelium/skills/interview/SKILL.md and read by ahel’s review.

Progressive onboarding through structured discovery conversation.

Preflight: Read target canvas file(s) before any Write/Edit

Hard rule. Before issuing Write or Edit against any .claude/canvas/*.yml, use the Read tool on that file in this session. Claude Code's Read-before-Write check requires the Read tool specifically — cat/head/grep via Bash do NOT satisfy it.

Edit vs Write — different cost profiles (verified 2026-05-14):

  • Edit (exact-string replacement): Read with limit: 1 satisfies the check at ~50 tokens. State-tracking is per-file, not per-byte — subsequent Edit calls work anywhere in the file. Use this for partial updates against large canvas files (e.g., purpose.yml at 800+ lines).
  • Write (full replacement): do a full Read first. Write obliterates the file; you should see what you're about to replace. The limit:1 shortcut is not appropriate here.

ID-bearing entries — scan the ID space before assigning (added 2026-05-15, v0.23.19): When adding a new component, opportunity, solution, or any other ID-bearing entry to a canvas file, run a Bash grep first to confirm the next ID in your prefix sequence is actually free:

grep -o "<prefix>-[0-9][0-9]*" .claude/canvas/<file>.yml | sort -u -t- -k2 -n | tail -3

Replace <prefix> with the canvas's ID prefix (comp for landscape, opp for opportunities, sol for solutions, ht for human-tasks, etc.). Then pick the next free integer, matching the zero-padding already used in that file. The sort is NUMERIC (-t- -k2 -n) rather than lexical, and that is not pedantry: a plain sort -u orders ht-1 after ht-080, so on a canvas with inconsistent padding it reports the wrong maximum and the next ID collides. Verified on the dogfood repo 2026-08-13, where lexical sort returned ht-1 as the highest human-task ID against an actual ht-080. grep -o is also deliberate: it matches IDs wherever they appear, including cross-references and prose, so an ID that was promised somewhere but not yet defined is not handed out twice. validate_canvas.py has a duplicate-ID check (lines 230-239) that catches the failure on CI, but a duplicate can persist in the working tree for days if CI isn't run between edit and discovery — see roadmap-repo corrections.md 2026-05-15 "Duplicate canvas ID created in landscape.yml" for the worked example.

Original failure mode: anti-pattern #7 instance #5, 2026-05-09 — agent conflated Bash head with the Read tool, lost ~14k tokens to a Write-fail → remedial-full-Read → re-Write loop. The limit:1 discipline (graduated 2026-05-14, v0.23.18) prevents the second-order cost where the agent correctly follows the rule but full-Reads every time. The ID-scan discipline (graduated 2026-05-15, v0.23.19) prevents the related class where the agent reads enough of the file to satisfy the Edit check but not enough to see existing ID assignments — kin to anti-pattern #8 (Stale State Read).

If this skill writes to multiple canvas files, register each one first (limit:1 for Edit-only paths; full Read for Write paths) AND ID-scan any prefix you intend to assign.

See CLAUDE.md Canvas writes — Read before Write for the canonical rule.

When to Use

  • Starting a new product or project.
  • Joining an existing product that lacks documented context.
  • Context has changed significantly and needs refreshing.

Workflow

Phase 0: Canvas state detection (ALWAYS FIRST)

Read .claude/canvas/purpose.yml and .claude/diamonds/active.yml at session start. Determine state:

  • Canvas empty (template-only fields, no diamonds in active_diamonds): proceed to Universal Brief Flow below.
  • Canvas populated (purpose statement set OR diamonds present): proceed to Continuing-Project Routing below.

This replaces the prior intent check ((a) try for 10 min / (b) onboard real project) and the prior time-budget routing (<8h / 8-48h / 48+h). Both were predict-the-future questions asked before any value was delivered. The brief is now universal for empty-canvas entry; depth and time-cost are chosen post-brief, when the user has the data to choose.

Universal Brief Flow (canvas empty)

Goal: the user walks away in ~10 minutes with a one-page brief on their idea that they can paste into a notes app and feel was worth the time. Then they choose what comes next, with each option declaring its time cost.

State the deal in one line, then ask the four questions (one at a time, follow the energy):

"I'll ask 4 short questions about your idea, then give you a one-page brief. ~10 minutes. Nothing leaves your machine. I won't ask how much time you have for the whole project right now — depth and time-cost are chosen after the brief, when you have data to choose."

  1. (one sentence, hard limit) "What are you trying to change, and for whom?"
  2. "Tell me about the last time someone in that group hit the problem you're trying to solve. What did they actually do?" (Torres past-behavior — not "would they want X")
  3. "If you had to bet on one thing being wrong about this idea, what would it be?"
  4. "What's the smallest move you could make this week to find out?"

Format constraint discipline (per ht-012 cohort-log f4, shipped v0.23.21): the format spec (e.g., "one sentence") MUST appear before the question text and as a bolded mechanical constraint, not as a prose prefix that can be read as a rhetorical politeness. The "In one sentence, X?" framing was misread as "succinctly, X?" — the user answered in 2-3 sentences before discovering the constraint was hard. Render format specs as parenthetical or bolded prefixes; do not rely on prose to carry the constraint.

Why-first discipline (Sinek inside-out, v0.55.1 — makes the theory real). Q1 leads with the change the product makes — Sinek's Why, the difference you want true in the world — then for whom. Two clauses, one sentence, open stem. This is deliberate: the Golden Circle communicates inside-out (Why → How → What), so purpose must be elicited, not back-labeled from a build-list. Keep the stem open — a solution-first / curiosity-first user who answers with what they're building ("I'm building X") is fine; do NOT block or force a problem-frame they may not have. Then, with ONE light follow-up, do two things: (a) reach the belief"what becomes true for them if it works?" (the change-in-the-world — Sinek's actual Why — NOT merely the problem/job, which is Torres/Christensen territory); (b) capture the build if not yet given — "and what are you building to do that?" (the brief needs the idea name). Sinek is not hard-gated AT ENTRY (purpose stays optional in the schema until work is derived from it), so a user who still can't name the change proceeds — and the flagging is now real: validate_canvas.py's purpose_why_findings WARNs on an absent, empty or whitespace-only why every run. Until v0.145.0 this sentence promised a flag that NOTHING PERFORMED: no script read purpose["why"] to test presence, so "optional at entry" was indistinguishable from "permanently empty, and nobody will ever say so". It stops being optional the moment purpose_properties existspurpose.schema.json then requires a non-empty why and validation FAILS, because binding properties derived from an absent purpose are derived from nothing. minLength is doing real work there: a present-but-empty why: "" satisfies a bare required while carrying no purpose, and that is the legacy (pre-plugin, v0.1.x) template's shape, so legacy-migrated projects can be carrying one. Populate purpose.yml (Step 2) from the change/why answer — what becomes true in the world — NOT the build and NOT a bare problem statement; that is what makes the decision-log's "Theory: Sinek (purpose)" true rather than back-labeling a Torres job as a Sinek belief.

Phase-index narration discipline (per ht-012 cohort-log f9, shipped v0.23.21): the Phase 1–6 structure below is internal skill organization. Do NOT narrate phase numbers ("Phase 4 Landscape", "Phase 6 product-type") to the user. When routing or referencing a later step in user-facing output, use the outcome label ("we'll explore the landscape next", "the project-type question comes later"). Same discipline applies in /mycelium:diamond-assess and any skill that surfaces routing decisions.

After Q4, in this exact order:

Step 1 — Render the brief FIRST (before any tool calls)

Output the brief markdown to the chat. This is the visible payoff and it MUST appear before canvas writes — Claude Code clutters the TUI with tool-call blocks if writes come first.

# Brief: <one-line idea name>

## Who it's for
<one paragraph synthesizing Q1+Q2: lead with the CHANGE / why (what becomes true in the world if it works — Sinek's purpose), then who they are, the job they're getting done, what they do today>

## Biggest assumption
<one paragraph from Q3, ending with: "This is risky because…">

## Biggest risk
<one of: value | usability | feasibility | viability — Cagan's lens, named in plain language without using "Cagan" or "four risks">

## Your next concrete move
<one paragraph sharpened from Q4: what to do, what you'll learn, when you'd know>
Step 2 — Side-effect canvas + decision-log writes (after brief is rendered)

Hard requirement: all FOUR files below must be written before Step 3. This is not optional or "best-effort" — downstream skills (/mycelium:diamond-assess, /mycelium:jtbd-map, /mycelium:ost-builder) AND the auto-dogfood verification all assume the brief flow produces this complete artifact set. The brief flow's "10-min first value" promise IS this four-file write.

Read+Edit in parallel where possible (one tool batch for Reads, one for Edits) to minimize TUI noise. Order does not matter, but ALL FOUR must land:

  • (1 of 4) .claude/harness/decision-log.md — APPEND a minimal entry naming the brief's substance. Do NOT defer to the "After the Interview" section below; that section EXTENDS this minimal entry, it does NOT replace it. If you skip this write, the audit trail has a hole for any user who stops after the brief (which is most of them). Format (literal — do not paraphrase the section headers):

    ### YYYY-MM-DD - Interview brief: <Q1 idea name>
    - **Decision**: Conducted 4-question brief on <Q1 idea name>. Purpose, JTBD-functional, and biggest risk captured. Tagged as internal_stakeholder evidence pending external validation.
    - **Theory**: Sinek (purpose), Christensen (JTBD-functional from Q1+Q2), Torres (riskiest assumption from Q3), Cagan (four-risks classification on Q3).
    - **Evidence**: User-supplied Q1-Q4 answers (paraphrase Q1+Q3 in 1-2 sentences each, mentioning the project name and the user's own words about what they're building).
    - **Confidence**: 0.15 (canvas-density-emergent — see formula).
    - **Why_not_alternatives**: N/A (first interview).
    

    Added 2026-05-22 (v0.23.40), hoisted to first-in-list 2026-05-23 (v0.23.41) per Phase 5 finding that the decision-log write was being skipped when buried mid-list — the agent followed canvas-write bullets but treated this one as optional.

  • (2 of 4) .claude/canvas/purpose.yml: purpose statement from Q1's change/why answer (what becomes true in the world — Sinek's Why — NOT the build, NOT a bare problem/job), JTBD functional from Q1+Q2, workarounds from Q2. Tag all entries source_class: internal_stakeholder, validated: false.

  • (3 of 4) .claude/canvas/jobs-to-be-done.yml: stub JTBD entry from Q1+Q2 with functional dimension populated and emotional/social/hiring/firing/opportunity_score fields present as placeholders for downstream /mycelium:jtbd-map enrichment. Even a one-line stub (e.g., hiring: "TBD via /mycelium:jtbd-map") is enough — the file existing with the JTBD structural shape is what lets the auto-dogfood evaluator's jtbd_mapped check pass AND lets /mycelium:jtbd-map build incrementally rather than from a blank file. Tag source_class: internal_stakeholder, validated: false. Added 2026-05-22 (v0.23.39) per Phase 3c onboarding-cold-start finding.

  • (4 of 4) .claude/diamonds/active.yml: L0 Purpose diamond, scale: L0, phase: discover (lowercase per active.yml schema convention), confidence: 0.15 (canvas-density-derived: purpose 0.05 + JTBD functional 0.05 + workarounds 0.025 ≈ 0.125 → 0.15; see formula table at end of file), evidence_type: speculation (corrected 2026-08-05 — this read evidence_type: internal_stakeholder, which is a source_class VALUE written into an evidence-STRENGTH field. active.schema.json $refs the Gilad ladder for this property, so the old instruction produced a schema-INVALID diamond. A founder brief is one internal stakeholder, unvalidated — speculation is where that sits on the ladder. Record the source separately as source_class: internal_stakeholder), theory_gates_status all pending, note: created_via: brief. Also write a definition_of_done stub on this diamond (it is a field, not a fifth file — the four-file contract is unchanged): outcome = the behaviour-change the purpose implies for the Q1+Q2 user (problem-first, not a build-list), signal = the one observable thing from Q4's "what you'll learn / when you'd know," kind: lagging (L0 default — "people keep choosing it / fits, not ships"), provenance: {source_class: internal_stakeholder, validated: false}. A one-line outcome + signal stub is enough at birth; it gets sharpened by /mycelium:define-done. Per ${CLAUDE_PLUGIN_ROOT}/skills/define-done/SKILL.md.

Do NOT write opportunities.yml, north-star.yml, landscape.yml, or any other canvas file from the brief alone — those are populated when the user picks a depth option in Step 3.

After writing all four files, output four lines (one per file written):

  1. Saved your brief to canvas (purpose.yml + jobs-to-be-done.yml + diamonds/active.yml) + decision-log entry.

  2. L0 confidence set to 0.15 — this reflects what a 4-question brief can establish (purpose 0.05 + JTBD functional 0.05 + workarounds 0.025). Confidence increases as more canvas dimensions get evidence; see the formula at the end of this skill for the full ladder.

  3. Tagged your brief as source_class: internal_stakeholder (your own description, not independent user evidence yet) + validated: false. If you have real interview data, user research, or behavioral evidence behind these answers, run /mycelium:assumption-test or /mycelium:log-evidence to attach it — the source class then shifts and confidence rises. The five source classes are: external_human, external_data, internal_stakeholder, internal_desk, internal_simulated (see schema for full definitions).

  4. Pinned a starter Definition of Done — what "done" looks like for this purpose as a behaviour-change, not a feature shipped. Run /mycelium:define-done to sharpen it (problem → signal → kill-criterion), or it'll be flagged for sharpening later.

Lines 2 + 3 together are opp-004 candidate #3 and opp-005 candidate #1: surface the framework's classification choices at point of display so users have visibility into how their input is being weighted, not just buried-in-docs discipline. Line 4 surfaces the outcome-bar at birth (the implicit-harshest-bar problem is invisible until named).

Step 3 — Render the depth menu (informed by brief content)

If Q3's risk type is unambiguous, prefix the menu with one line of informed recommendation. Cite the specific Q3/Q4 phrase that drove it (Lanham contrastive XAI — "based on X, recommend Y, because Z"). Skip the recommendation if Q3 is ambiguous; default to "Several options worth considering — pick what matches your bandwidth."

Then render the menu:

Where to next? Pick one:

1. Test the biggest assumption  (~10 min)  — /mycelium:assumption-test on what you flagged as risky. Smallest-viable-test design.
2. Go deeper into discovery     (~10–45 min) — north star, landscape, constraints, classification. You choose how deep.
3. [Contextual options — see table below, max 2]
4. Stop for now                  (~0 min)   — your brief is saved. Run /mycelium:diamond-assess when you come back.
5. Friction log                  (~5 min)   — what felt off about the last 10 minutes? See CONTRIBUTORS.md.

Other? Tell me what.

Contextual options (insert at position 3, max 2 surfaced):

Trigger keyword/shape in briefOption to surfaceTime
GDPR, HIPAA, FDA, regulated, public sector, patient, health, financialRun regulatory review (/mycelium:regulatory-review)~15 min
"complex," "uncertain," "novel," "no precedent," "first time anyone has"Classify the domain (/mycelium:cynefin-classify)~5 min
Mobile app + non-tech users + accessibility implicationsAccessibility audit (/mycelium:a11y-check)~15 min

Do NOT surface a contextual option if the trigger is weak or inferred — false positives waste user time. Default to tighter detection.

If 3+ contextual triggers fire, surface the strongest 2 and add a one-liner: "Other depth options based on your brief — ask if you want to see them."

Step 4 — Route based on user choice
  • Test the biggest assumption → Invoke /mycelium:assumption-test with Q3's biggest assumption pre-loaded as the target. Confidence will refine when the test designs.
  • Go deeper into discovery → Proceed to Go Deeper Sub-Routing below.
  • Contextual option → Invoke the named skill.
  • Stop for now → "Your brief is saved. Run /mycelium:diamond-assess whenever you want to come back. Bye."
  • Friction log → "What felt off? Where did the framework get in your way? By default this stays in our conversation — say so if you want me to write it to a file (e.g. .claude/evals/dogfood-reports/YYYY-MM-DD-friction.md) so it survives the session. If you'd like the friction to become a public receipts-case under your name (CV-citable contribution to Mycelium, see CONTRIBUTORS.md for how that works), I'll ask before publishing anything outside this repo."
  • Other → Surface a brief skill index ("Here's what Mycelium can do — pick one or describe what you want") then route based on response.

Go Deeper Sub-Routing

When user picks "Go deeper," ask:

"How deep?

  • Light (~10 min) — landscape sketch only
  • Medium (~25 min) — landscape + north star + classification
  • Full (~45 min) — also constraints, current state, ethical bounds

Or pick specific phases: north star, landscape, constraints, classification, current state, ethical bounds.

Based on your brief, I'd suggest [recommendation per heuristic table below]."

Heuristic table for informed depth recommendations (re-read brief content, match, propose):

Brief signalRecommend phase(s)Why
Q3 names a viability risk (will users pay, unit economics)Phase 4 LandscapeViability needs market evidence
Q3 names a feasibility risk (can we build, performance, scale)Phase 3 North Star + leading indicatorsFeasibility needs measurable proof points
Q3 names a usability risk (will people figure it out)Phase 2 deeper JTBD (emotional/social) + Phase 5b constraintsUsability is downstream of full job context
Q3 names a value risk (does anyone want this)Phase 2 deeper JTBD + Phase 5c "anything I missed"Value is the JTBD core question
Q1+Q2 user/cohort is vaguePhase 2 deeper JTBD (specific persona)Can't proceed without a sharper user
Brief mentions regulated / public-sector / healthPhase 5b constraints + suggest /mycelium:regulatory-reviewConstraint surfacing is load-bearing
Brief mentions team, decisions, hiring, org dynamicsPhase 5 current stateOrg context shapes solution space
Brief mentions "first," "novel," "no one has done this"Phase 4 Landscape (Wardley genesis lens) + suggest /mycelium:cynefin-classifyGreenfield needs strategic frame
No strong signal (default)Phase 1 ethical bounds + Phase 4 LandscapeSafe minimum that always adds value

Run only the recommended phases unless user asks for more. Use Phase 1-6 content (preserved below) as the source for actual question text and canvas writes. Sprint-mode shape (compressed Phase 1+2, deferred 3-5c) is preserved as a possible Light/Medium configuration if user asks for the abbreviated form.

Source for path-selection mechanism: Hoskins friction log (2026-04-25) — original Phase 0 path selector now relocated as informed sub-routing within Go deeper. Hoskins receipts case attribution preserved. Horthy (instruction budget overflow). Corrections.md: "Interview ceremony too long for sprints."

Continuing-Project Routing (canvas populated)

When /mycelium:interview is invoked on a canvas with content, do not run the brief flow. Instead:

"This project's canvas has content from [date of last write]. Last diamond touched: [scale, phase, confidence]. What's happening?"

Options:

  • Continue work → Invoke /mycelium:diamond-assess (current state + recommended next).
  • New idea on this product → Run Universal Brief Flow, append result as a new diamond rather than overwriting the existing L0.
  • Wrong directory / fresh project intended → "Recommend npx degit haabe/mycelium new-dir to a fresh directory; this canvas tracks the existing project."
  • Joining the team / new to this project → Invoke /mycelium:diamond-assess with onboarding framing (canvas as orientation doc).

Edge case: if last brief-write was within 24h on this canvas with the same Q1 idea name (the user is iterating on their own brief), offer: "Update the brief with new answers, or start fresh?"

NARRATION DISCIPLINE — required for all phases below

Phase numbers (Phase 1 / Phase 2 / Phase 5b / Phase 6 / etc.) are internal section structure for skill authors. Do NOT narrate phase numbers to the user. Reference the outcome the phase produces, not the index. Per opp-006 (internal-vocabulary leak).

Examples of correct narration:

  • ✗ "The interview skill would normally populate these from Phase 6 questions."
  • ✓ "These get populated by the project-classification questions in the full interview flow."
  • ✗ "We'll go through Phase 5b constraints now."
  • ✓ "Now the questions about constraints — what can't change, who has to approve what, what rules apply."
  • ✗ "Phase 0 detected an existing canvas."
  • ✓ "Detected an existing canvas — here's where you left off."

Same discipline applies when one skill references another: name the outcome ("the project-type question in /interview"), not the phase index ("interview's Phase 6"). Internal vocabulary stays internal.

Phase 1: Purpose & Vision

  1. Ask: "What problem does this product/organization solve? Who suffers without it?"
  2. Ask: "What does success look like in 3 years? What would change in the world?"
  3. Ask: "What will you never do, even if it would be profitable?" (ethical boundaries)
  4. Synthesize into a purpose statement. Validate with the user.

Phase 2: Users & Jobs

  1. Ask: "Who are your primary users? Describe a specific person."
  2. Ask: "What are they trying to accomplish? What job are they hiring your product to do?"
  3. Map JTBD (functional, emotional, social) per user type.
  4. Ask: "What workarounds do they currently use?"

Phase 3: North Star & Metrics

  1. Ask: "What is the single metric that best indicates you're fulfilling your purpose?"
  2. Ask: "What leading indicators predict movement in that metric?"
  3. Construct a north star framework: metric + input metrics.

Phase 4: Landscape & Strategy

  1. Ask: "Who else solves this problem? How are you different?"
  2. Ask: "What are you betting on strategically right now?"
  3. Ask: "What is your biggest uncertainty or risk?"
  4. Sketch initial Wardley map positioning if sufficient context exists.

Shortened here. Read the whole file on GitHub.

Signals

GitHub stars
45
Forks
3
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
interview-haabe
Source
github.com/haabe/mycelium