Skip to content
Skillv1.0.0

kiln-build-prd

Run the complete kiln pipeline using an agent team. Reads the PRD to determine team structure, then orchestrates specify → plan → tasks → implement → audit → PR.

by yoshisada(0) 0 installs
Free
Sign in to install

Free account. Installing gives you the manifest plus copy-paste snippets.

See reviews

About

Imported from yoshisada/ai-repo-template (plugin-kiln/skills/kiln-build-prd/SKILL.md). Install upstream with npx skills add yoshisada/ai-repo-template --skill kiln-build-prd. Copyright stays with the author.

Kiln Run — Full Pipeline via Agent Team

User Input

$ARGUMENTS

You MUST consider the user input before proceeding (if not empty). The user input is the feature description.

Pre-Flight

  1. Verify agent teams are available (NON-NEGOTIABLE). Before anything else, check that TeamCreate is available as a tool. If it is NOT available, STOP immediately and tell the user:

    "Agent teams are not enabled. /kiln:kiln-build-prd requires Claude Code agent teams to orchestrate the pipeline.

    To enable them, add this to your Claude Code settings or launch with the flag:

    claude --enable-agent-teams
    

    Or add "enableAgentTeams": true to .claude/settings.json.

    Then restart Claude Code and run /kiln:kiln-build-prd again."

    Do NOT proceed with any other pre-flight steps if teams are unavailable. Do NOT attempt to run the pipeline in single-agent mode.

  2. If no user input was provided, ask the user for a feature description.

  3. Locate the PRD — check for a PRD in this order:

    • If user input matches a feature slug: read docs/features/*-<slug>/PRD.md
    • If docs/features/ contains exactly one feature PRD folder: read that feature PRD
    • Otherwise: read docs/PRD.md (the product-level PRD)
    • If none found, tell the user to run /kiln:kiln-create-prd first. Extract the feature scope, functional requirements, deliverables, and any named external dependencies. For feature PRDs, also read docs/PRD.md for inherited product context (tech stack, users, constraints).
  4. Read .specify/memory/constitution.md — note any constraints that affect team structure.

  5. Handle working directory and create branch:

    The user's local checkout is their working copy. The pipeline branches from the current HEAD — not from main.

    # Step A: Check for uncommitted changes
    if ! git diff --quiet || ! git diff --cached --quiet; then
      echo "You have uncommitted changes."
    fi
    # Also check untracked files
    git status --short

    If there are uncommitted changes or staged files: Commit them to the current branch first, then create the pipeline branch. Do NOT ask the user — just commit and proceed. These are typically the PRD and backlog files the pipeline needs.

    git add -A
    git commit -m "chore: commit working changes before pipeline branch"

    If the working directory is clean: Proceed directly to creating the branch.

    # Step B: Derive feature slug and create a fresh branch from current HEAD (FR-004)
    # The feature slug MUST be derived from the PRD directory name (2-4 words, lowercase, hyphenated).
    # Example: docs/features/2026-04-01-pipeline-workflow-polish/PRD.md → "pipeline-workflow-polish"
    # Strip the date prefix (YYYY-MM-DD-) from the PRD directory name to get the slug.
    PRD_DIR_NAME=$(basename "$(dirname "$PRD_PATH")")
    FEATURE_SLUG=$(echo "$PRD_DIR_NAME" | sed 's/^[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-//' | tr ' ' '-' | tr '[:upper:]' '[:lower:]')
    BRANCH_NAME="build/${FEATURE_SLUG}-$(date +%Y%m%d)"
    git checkout -b "$BRANCH_NAME"

    The branch is created from wherever the user currently is — their current branch, current commit, current state. This preserves their working context. The pipeline's work happens on this new branch; the user's original branch is untouched.

    Branch naming rule (FR-004): The branch MUST follow build/<feature-slug>-<YYYYMMDD> exactly. The feature slug is derived from the PRD directory name with date prefix stripped. Do NOT use arbitrary slugs — derive from the PRD path.

    Spec directory naming rule (FR-005): The spec directory MUST be specs/<feature-slug>/ where <feature-slug> matches the branch name's feature portion (the part between build/ and the trailing -YYYYMMDD). No numeric prefixes. The specifier agent MUST use this exact directory name.

  6. PRD freeze: The PRD is frozen the moment you read it. Do NOT ask the user for confirmation — just proceed. Log a one-line message: "PRD frozen — starting pipeline on branch $BRANCH_NAME from $(git rev-parse --abbrev-ref HEAD@{-1})." If the user needs to change requirements mid-run, they can trigger a scope-change pause (see Step 4 in Monitor and Steer).

Step 1: Analyze the PRD and Design the Team

Required Roles (in order)

The pipeline always flows through these roles. This is the minimum — you MUST have at least one teammate per role:

  1. Specifier — Runs /specify, then /plan, then /tasks in a single uninterrupted pass. All three commands MUST execute back-to-back without stopping. The specifier MUST NOT go idle between commands. Produces all spec artifacts and commits them. Always runs first.

  2. Researcher — Resolves external dependencies referenced in the PRD. Clones starters to vendor/, documents findings in research.md. Runs after specifier if the PRD names external projects; skip this role if there are no external deps. PRD naming authority: The researcher MUST NOT rename, substitute, or "improve" directory names, file names, or identifiers that the PRD explicitly specifies. If the PRD says apps/electron, the researcher documents apps/electron — not apps/desktop, not apps/electron-app, not any "technology-agnostic" alternative. The PRD is the naming authority. If the researcher believes a PRD name is wrong, they must flag it to the team lead for resolution rather than silently substituting a different name.

  3. Implementer — Runs /implement. Executes the task plan phase-by-phase, writes code matching contracts, marks tasks [X], commits per phase. Runs after specifier (and researcher if present). Concurrent-staging hazard (when ≥2 impl agents run in parallel on the same branch): the version-increment hook auto-stages VERSION + every plugin-*/package.json + plugin-*/.claude-plugin/plugin.json on every Edit/Write, so each agent's staging area silently accumulates the OTHER agent's bumps. Compounding the hazard: a file written mid-edit by a sibling agent shows as M (staged) in git status, and git add <my-files> will sweep it into the next commit. Mitigation: before EVERY git commit, an impl agent runs git diff --cached --name-only and confirms the staged set matches THEIR owner-files list from tasks.md. Unexpected files: git restore --staged <file> (NOT git reset — that affects HEAD). Document the recovery in the next commit message.

  4. QA Engineer(Web/frontend projects only) Runs the qa-engineer agent. Unlike other auditors, the QA engineer is long-lived — it starts after the specifier finishes (so it knows what to test) and runs in parallel with implementers. It operates in two modes:

    • Checkpoint mode (during implementation): Each time an implementer completes a phase and notifies the QA engineer, it spins up the dev server, tests the newly completed flows with Playwright, records video of failures, and sends actionable feedback directly to the responsible implementer via SendMessage. The implementer fixes the issue and notifies QA for re-test. This creates a tight feedback loop that catches visual bugs while the implementer still has context.
    • Final mode (after all implementation): Runs /kiln:kiln-qa-pipeline which spins up a 4-agent QA team:
      • e2e-agent: Runs Playwright E2E suite (headless, fast, deterministic)
      • chrome-agent: Uses /chrome with live data (real auth, real state). Skipped if /chrome unavailable.
      • ux-agent: 3-layer UX evaluation (axe-core + accessibility tree + visual)
      • qa-reporter (pipeline mode): Routes findings to implementers via SendMessage → waits for fixes → re-tests → files remaining issues with qa-pass + build-prd labels After /kiln:kiln-qa-pipeline, runs /kiln:kiln-qa-final as a quick green/red gate to confirm all E2E tests pass. The audit-pr agent includes the QA report summary and issue links in the PR body.

    The QA engineer tracks its checkpoint history in .kiln/qa/checkpoints.md so it doesn't re-test unchanged flows. It is a peer to implementers, not a gate after them.

    QA snapshot guidance (FR-013): QA result snapshots and incremental test-result files MUST NOT be committed to the feature branch. They belong in .kiln/qa/ which is gitignored. The QA engineer should write all artifacts (screenshots, videos, reports) to .kiln/qa/ and never git add them.

    Skip this role for CLI-only, API-only, or non-visual projects.

  5. Auditor — Runs after all implementers AND the QA engineer's final pass finish. Each auditor gets a fresh context (no implementation history polluting their judgment). Split auditors by concern so they can run in parallel:

    • audit-compliance: Runs /audit — PRD→Spec→Code→Test verification
    • audit-tests: Verifies test quality — no stubs, real assertions, coverage gate
    • audit-smoke: Builds and runs the project in a temp dir, verifies runtime behavior
    • audit-pr: Creates the PR with stats from all other auditors. If a QA engineer ran, includes QA video links and the .kiln/qa/latest/QA-REPORT.md summary in the PR body.

    For simple features, one auditor can do all of these. For complex features, split them so each auditor starts with a clean context and a focused lens.

  6. Retrospective — Messages all teammates for feedback, creates a GitHub issue with findings. Runs last, before shutdown.

Scaling Up

Based on what you read in the PRD, decide where to add parallelism:

  • Multiple independent components? (e.g., CLI + templates + module system) → Spawn multiple implementers, one per component, working on different files in parallel. They all depend on the specifier finishing but can run concurrently with each other.
  • Large module count? (e.g., 5 installable modules) → Spawn one implementer per module, each owning its own files.
  • Complex external deps? → Spawn a dedicated researcher alongside the specifier so research can start as soon as the plan is done.
  • Web/frontend project? → Spawn a qa-engineer that runs alongside implementers. It starts after the specifier (needs spec to know what to test) and runs checkpoint passes as implementers complete phases. Implementers message the QA engineer when a phase is done; QA tests it and sends feedback back. This is the only role that runs in parallel with implementers rather than after them.
  • Multiple audit concerns? (compliance, test quality, runtime) → Spawn multiple auditors with different focus areas running in parallel. Each auditor gets a fresh context — no implementation history — so their judgment isn't biased by what they saw being built.

Decision Checklist

Ask yourself:

  1. How many independent file sets can be implemented in parallel? → That many implementers.
  2. Are there external deps to fetch? → Add a researcher.
  3. Does this feature have a visual/frontend component? → Add a qa-engineer running alongside implementers.
  4. Is a single audit pass sufficient? → If not, split auditors by concern.
  5. What's the total teammate count? → Keep it under 8. More teammates = more coordination overhead.

Agent Friction Notes Requirement (FR-009)

ALL pipeline agents (specifier, researcher, implementers, QA engineer, auditors) MUST write a friction note to specs/<feature>/agent-notes/<agent-name>.md before completing their work and marking their task as done. This is a prerequisite for task completion — the retrospective agent reads these notes instead of polling live teammates.

Each agent's prompt already includes the friction notes section. When spawning agents, ensure the feature path is communicated so agents know where to write their notes. The specs/<feature>/agent-notes/ directory should be created by the first agent that writes a note.

Implementer Sizing Rule

After tasks.md is generated, check the task count per implementer. If any single implementer would own more than 20 tasks, split them into multiple implementers by component or phase. A single implementer doing 50+ tasks will take too long, delaying the auditor and causing the pipeline to bottleneck.

Example: If tasks.md has 73 tasks split across CLI (20), templates (27), and modules (16), spawn 3 implementers — not 1 or 2. The "keep under 6" guidance applies to non-implementer roles; add implementers as needed to keep each one under ~20 tasks.

Example Team Structures

Simple feature (single module, no external deps):

specifier → implementer → auditor → retrospective

3 teammates, fully serial.

Medium feature (CLI + templates, one external dep):

specifier → researcher ─┐
                         ├→ impl-cli ──┐→ audit-code ──┐
                         └→ impl-tmpl ─┘→ audit-tests ─┤→ retrospective

5 teammates, 2 implementers in parallel, 2 auditors in parallel.

Web frontend feature (UI + API, visual QA with feedback loop):

specifier ─┐
           ├→ impl-ui ───┐
           ├→ impl-api ──┤→ qa-engineer (final) ─┐→ audit-pr ─┐
           └→ qa-engineer ┘  (checkpoints ↔ impls)└→ audit-compliance ─┤→ retrospective

6 teammates. qa-engineer starts after specifier, runs checkpoint passes during implementation (sends feedback to impl-ui/impl-api, receives "fix ready" notifications back). After all implementers finish, QA switches to final mode for the full video report. Auditors depend on both implementers AND QA final pass.

Complex feature (CLI + 3 modules + external starter):

specifier → researcher ─┐
                         ├→ impl-core ──┐→ audit-compliance ─┐
                         ├→ impl-mod-a ─┤→ audit-tests ──────┤→ retrospective
                         └→ impl-mod-b ─┘→ audit-smoke ──────┘

7 teammates, 3 implementers in parallel, 3 auditors in parallel.

Each teammate should run the kiln commands (/specify, /plan, /tasks, /implement, /audit) — not reimplement their logic. Implementers running in parallel should each get a filtered view of tasks.md (only their component's tasks).

Step 1.5: Baseline Checkpoint (when PRD has quantitative SC or NFR thresholds)

If the PRD includes any SC OR NFR item with a literal number — ≥3 fewer X, X% faster, ≤Nms, ≥80% coverage, count drops by Y — the team-lead MUST insert a baseline-capture step BEFORE the specifier finalizes spec.md/tasks.md. Carve-out: byte-identity NFRs (assertions of the form 'output MUST be byte-identical to pre-PR behavior on the no-X path') do NOT require a baseline measurement — the existing pre-PR output IS the baseline by construction. When skipping for this reason, the specifier documents the rationale in their friction note ('baseline-checkpoint skipped: byte-identity NFRs do not require numeric baseline'). Skipping this step (without the byte-identity carve-out) means the spec ships with thresholds that can't be re-derived from observed reality, which produces "+N% deviation in blockers.md" every time (see PR #166 SC-G-1 recalibration, PR #168 NFR-H-5 +5ms deviation).

Procedure:

  1. Spawn researcher-baseline BEFORE the specifier finalizes spec.md.
  2. Wait for researcher-baseline to write research.md §baseline with current-main numbers.
  3. The specifier reads research.md §baseline and re-derives every quantitative SC/NFR threshold from the live measurement, NOT from the PRD literal.
  4. If the live measurement makes a PRD threshold unreachable (e.g., baseline already at the target — PR #166 hit this when FR-E batching had collapsed the baseline to 1 before SC-G-1 was authored), the specifier rewrites the threshold into a compound gate that captures the spirit of the metric AND flags the calibration in spec.md ## Open Questions.
  5. If the live measurement makes a NFR perf budget unreachable on the implementation hardware (e.g., NFR-H-5 50ms target unreachable on macOS due to irreducible python3 fork), the specifier rewrites the threshold with a documented tolerance band BEFORE implementation starts. Do NOT "set the threshold and discover the tolerance after the fact" — that pattern produces blockers.md noise every pipeline.

Hard pre-req: implementers may not begin until the specifier has reconciled SC/NFR numbers against live baseline. The specifier task is NOT complete just because spec.md exists — it must explicitly note "thresholds reconciled against research.md §baseline" in its friction note.

Why this is needed: PRD literal "SC-G-1 ≥3 fewer Bash/Read tool calls" was unreachable in PR #166 because FR-E batching had already collapsed the baseline to 1. PRD literal "NFR-H-5 ≤50ms" was unreachable in PR #168 because of an irreducible python3 fork. Both cases produced mid-pipeline recalibration friction (specifier + researcher-baseline + audit-compliance friction notes; blockers.md R-1 in #166 + B-2 in #168). Issue #167 PI-3 + Issue #169 PI-3 captured this as the single most-recurring pipeline friction.

Step 2: Create the Team and Tasks

  1. Use TeamCreate with a descriptive name (e.g., kiln-{feature})
  2. Use TaskCreate to create ALL tasks. You MUST create every task listed in the Mandatory Tasks section below, plus any additional tasks from your PRD analysis.
  3. Set task dependencies using TaskCreate or TaskUpdate (see dependency rules below)
  4. Assign tasks to teammates by setting owner via TaskUpdate

Mandatory Tasks (NON-NEGOTIABLE — always create these)

Every pipeline run MUST include these tasks regardless of feature complexity. Do NOT skip any of them:

# Task Owner Depends On Why Mandatory
1 Specify + plan + research + tasks specifier Produces all spec artifacts
N Implementation (1+ tasks) implementer(s) specifier Builds the feature
Q Visual QA (checkpoints + final) qa-engineer specifier (Web/frontend only) Feedback loop during impl + final video report. Create this task if the PRD has any visual/frontend component. The QA engineer does NOT wait for implementers to finish — it runs alongside them.
A Audit + smoke test + create PR auditor all implementers + qa-engineer (if present) Quality gate + deliverable
R Retrospective retrospective ALL other tasks Self-improvement — feeds back into the skill and template. ALWAYS the last task before shutdown. MUST NOT start until every other task is completed or explicitly cancelled.

The retrospective task exists to make every pipeline run improve the next one. Skipping it means repeating the same friction forever.

Additional Tasks (PRD-dependent)

Based on your PRD analysis, you may add:

  • Multiple implementation tasks (one per independent component) for parallelism
  • A separate researcher task if external deps need resolving
  • A qa-engineer task for web/frontend projects (runs alongside implementers, not after)
  • Multiple audit tasks split by concern (compliance, tests, smoke) for parallelism

Task Granularity Rule

Each implementer MUST have exactly one task that represents ALL of their work. The implementer MUST NOT mark this task as completed until every phase and every sub-task in tasks.md that they own is finished and committed. The auditor depends on these task completions, so premature completion signals cause the auditor to run against incomplete code.

Include this in every implementer's prompt:

Do NOT mark your task as `completed` via TaskUpdate until ALL of the following are true:
- Every task assigned to you in tasks.md is marked [X]
- Every phase you own has been committed
- You have no remaining uncommitted work

Your task completion is the signal that triggers the auditor. If you mark it done early, the auditor will audit incomplete code and produce invalid findings.

Task Dependencies

Wire dependencies following these rules:

  • All implementation tasks depend on the specifier task
  • Researcher task (if present) depends on the specifier task
  • Implementer tasks depend on the researcher task (if present)
  • QA engineer task (if present) depends on the specifier task — it starts alongside implementers, NOT after them. It needs the spec to know what to test but does NOT need implementation to be complete.
  • Audit tasks depend on ALL implementation tasks AND the qa-engineer task (if present)
  • Retrospective depends on EVERY other task — list all task IDs (specifier, researcher, every implementer, qa-engineer, auditor) as addBlockedBy dependencies when creating the retrospective task via TaskCreate. Do NOT depend on only the auditor — that leaves a race condition where implementers may still be running.

Task Dependency Example (CLI project, no QA)

Task 1: Specify (no deps)                         → owner: specifier
Task 2: Research (depends: 1)                     → owner: researcher
Task 3: Impl CLI (depends: 2)                     → owner: impl-cli
Task 4: Impl templates (depends: 2)               → owner: impl-templates
Task 5: Audit + smoke + PR (depends: 3, 4)        → owner: auditor
Task 6: Retrospective (depends: 1, 2, 3, 4, 5)   → owner: retrospective  ← depends on ALL tasks

Task Dependency Example (Web frontend project, with QA)

Task 1: Specify (no deps)                         → owner: specifier
Task 2: Impl UI (depends: 1)                      → owner: impl-ui
Task 3: Impl API (depends: 1)                     → owner: impl-api
Task 4: Visual QA (depends: 1)                    → owner: qa-engineer  ← starts with implementers, NOT after
Task 5: Audit + PR (depends: 2, 3, 4)             → owner: auditor      ← waits for impls AND QA final pass
Task 6: Retrospective (depends: 1, 2, 3, 4, 5)   → owner: retrospective

Note: Task 4 (QA) depends only on the specifier, so it unblocks at the same time as the implementers. The QA engineer runs checkpoint passes during implementation by communicating with implementers via SendMessage. It only marks its task as completed after its final pass (all flows tested, video exported). The auditor waits for this completion before starting.

The system automatically unblocks dependent tasks when their dependencies complete. The retrospective will not unblock until every single dependency is marked completed.

Pre-Spawn Checklist

Before spawning any teammates, verify:

  • Specifier task exists
  • At least one implementation task exists
  • QA engineer task exists (if web/frontend project)
  • Audit task exists
  • Retrospective task exists ← if this is missing, add it now
  • All dependencies are wired correctly
  • Every task has an owner assigned

Step 2.5: Research-First Variant Routing (FR-009 — FR-012 of research-first-completion)

Read the PRD frontmatter and decide whether this run uses the research- first variant pipeline (a per-axis empirical gate inserted between /tasks and /implement) or the standard pipeline (byte-identical to pre-research-first behavior).

§2.5.1 — Skip-path probe (NFR-002 byte-identity)

# parse-prd-frontmatter.sh already ran during Pre-Flight; PRD_FRONTMATTER_JSON
# is populated. Single jq lookup on already-parsed JSON — NO new subprocess
# fork on the skip path.
NEEDS_RESEARCH=$(jq -r '.needs_research // false' <<<"$PRD_FRONTMATTER_JSON")
if [ "$NEEDS_RESEARCH" != "true" ]; then
  # Skip-path: structural no-op — single jq lookup on already-parsed JSON;
  # NEVER emit stdout on skip path (Decision 7 — NFR-002 byte-identity).
  : # explicitly do nothing; fall through to Step 3
else
  # Variant path — see §2.5.2.
  echo "research-first variant invoked: $PRD_PATH"
fi

NEVER emit stdout on the skip path. Decision 7 / NFR-002 mandates byte- identity routing for non-research PRDs. A "research-first-skipped" log line would create a stdout diff against pre-PR behavior, violating the byte- identity invariant. OQ-6 (deferred) explicitly notes this — re-open if maintainers want skip-path observability.

§2.5.2 — Variant pipeline steps (FR-010)

When NEEDS_RESEARCH == "true", the variant pipeline executes these steps between /tasks (already complete by Step 2) and /implement (spawned via implementer in Step 3). The team-lead orchestrates the variant inline; NO new wheel workflow JSON is shipped (Decision 2):

  1. establish-baseline — invoke plugin-wheel/scripts/harness/research-runner.sh against the declared corpus (fixture_corpus: declared|promoted → use fixture_corpus_path) OR the synthesizer's accepted output (fixture_corpus: synthesized → coordinate with the fixture-synthesizer agent shipped per plan-time- agents). Capture metrics to .kiln/research/<prd-slug>/baseline-metrics.json.

  2. implement-in-worktreegit worktree add <tempdir> <branch> per Decision 4. Spawn the implementer in the worktree (the implementer's prompt MUST include Working directory: <worktree-tempdir>). Record the tempdir for cleanup via trap so it survives interruptions.

    Loud-fail invariant (NFR-007 / Decision 4): if git worktree add fails (e.g., locked working tree, filesystem incompatible), bail with:

    Bail out! research-first-worktree-failed: <error>
    

    NO silent fallback to cp -R — Decision 4.

  3. measure-candidate — invoke research-runner.sh against the candidate plugin-dir (from the worktree) against the SAME corpus. Capture metrics to .kiln/research/<prd-slug>/candidate-metrics.json.

  4. gate — invoke plugin-wheel/scripts/harness/evaluate-direction.sh for mechanical axes (per axis-enrichment §4); invoke plugin-wheel/scripts/harness/evaluate-output-quality.sh for the output_quality axis (per plan-time-agents §4). Capture per-axis verdicts to .kiln/research/<prd-slug>/per-axis-verdicts.json. (This PR does NOT modify the per-axis verdicts JSON shape — foundation precedent / NFR-009 invariant.)

  5. gate-pass branch (FR-012) — every axis returns pass. Continue to the existing /audit + PR-creation steps. The auditor MUST be told to inject a ## Research Results heading + per-axis pass-status table into the PR body, and to attach the research-report path (.kiln/logs/research-<uuid>.md — foundation precedent). Pass these inputs in the auditor's prompt.

    Per-axis table shape (markdown):

    | metric | direction | priority | verdict |
    |--------|-----------|----------|---------|
    | tokens | lower | primary | pass (-22% mean across 12 fixtures) |
    | output_quality | equal_or_better | primary | pass (5/5 candidate_better) |
    
  6. gate-fail branch (FR-011) — ANY axis returns regression. HALT the pipeline before invoking /audit or PR-creation. Surface the verbatim per-axis report (read from per-axis-verdicts.json) on stdout. Emit:

    Bail out! research-first-gate-failed: <prd-slug>
    

    to stderr; exit 2. The auditor + PR-creator agents are NEVER spawned on the gate-fail path — FR-011 reviewer-visible invariant.

  7. worktree cleanup — regardless of branch (pass OR fail), run:

    trap 'git worktree remove --force "$WORKTREE_TEMPDIR" 2>/dev/null || true' EXIT

    so the worktree is cleaned up even if the variant pipeline is interrupted.

§2.5.3 — Edge cases

  • needs_research: true but no fixture_corpus: — bail at the corpus-load step (between baseline and gate) with:

    Bail out! research-first-routed-but-no-corpus: <prd-path>
    

    The validator emits a write-time warning per validate-research-block.sh rule 10, but build-prd is the gate that cannot proceed without a corpus.

  • needs_research: true but empirical_quality: [] — bail at the pre-baseline step with:

    Bail out! research-first-routed-but-no-axes: <prd-path>
    

§2.5.4 — Operational note for maintainers

The variant pipeline is opt-in per PRD frontmatter only. There is no --research flag and no environment-variable bypass — that is a non-goal of this PRD. To bypass research-first routing, the maintainer hand-edits the PRD frontmatter to remove needs_research: true.

Step 3: Spawn Teammates

Spawn all teammates EXCEPT the retrospective agent. The retrospective is spawned later in Step 5 after all auditors complete. This keeps its context clean — an agent spawned at pipeline start accumulates idle notifications and peer DM summaries for the entire run, burning tokens on irrelevant context.

Spawn teammates using the Agent tool with:

  • team_name set to the team name from Step 2
  • name set to a descriptive name (e.g., specifier, impl-core, auditor)
  • run_in_background: true
  • mode: "bypassPermissions"

Each teammate's prompt should include:

  • Canonical paths (FR-006): "Working directory: , Branch: , Spec directory: specs//". These MUST be included in every agent's prompt at spawn time so agents never need to guess or glob for paths.
  • Which tasks they own (by task ID or description)
  • Instructions to run the appropriate kiln commands for their tasks
  • The feature description from user input
  • Instructions to use TaskUpdate to mark tasks in-progress when starting and completed when done
  • Instructions to use SendMessage to notify dependent teammates when unblocked
  • Instructions to check TaskList after completing each task to find the next available work
  • Instructions to read ~/.claude/teams/{team-name}/config.json to discover other teammates by name

Specifier Prompt — Chaining Requirement (NON-NEGOTIABLE)

The specifier's prompt MUST include these exact instructions to prevent stalling between commands:

SPEC DIRECTORY NAMING (FR-005): The spec directory MUST be specs/<feature-slug>/ where <feature-slug>
matches the branch name's feature portion (the part between "build/" and the trailing "-YYYYMMDD").
No numeric prefixes. For example, if the branch is build/pipeline-workflow-polish-20260401,
the spec directory MUST be specs/pipeline-workflow-polish/. Do NOT use any other naming scheme.

You MUST run all three kiln commands in a single uninterrupted pass:
1. Run `/specify` with the feature description
2. IMMEDIATELY after specify completes, run `/plan` — do NOT stop, do NOT wait, do NOT go idle
3. IMMEDIATELY after plan completes, run `/tasks` — do NOT stop, do NOT wait, do NOT go idle
4. ONLY after all three are done: commit all artifacts, mark your task completed, and notify downstream teammates

Each slash command will report "completion" and suggest next steps — IGNORE those suggestions and proceed to the next command in this list. Your task is NOT complete until spec.md, plan.md, contracts/interfaces.md, and tasks.md all exist and are committed.

Why this is needed: Each /* skill ends by reporting completion and suggesting the next command. Without explicit chaining instructions, the specifier agent treats each skill completion as a stopping point and goes idle, requiring a manual nudge from the team lead to continue. This caused a ~10 minute stall in the 015 pipeline run.

Researcher Prompt — PRD Naming Authority (NON-NEGOTIABLE)

The researcher's prompt MUST include these exact instructions:

When documenting findings in research.md:
- If the PRD explicitly names a directory, file, package, or identifier, you MUST use that exact name. Do NOT substitute a "better", "cleaner", or "technology-agnostic" name.
- Example: If the PRD says `apps/electron`, document `apps/electron` — not `apps/desktop`.
- If you believe a PRD name is incorrect or problematic, flag it to the team lead with your reasoning. Do NOT silently rename it in your research output.
- Verify every directory name, package name, and file path in your research.md against the PRD before committing. Any mismatch is a bug.

Why this is needed: In the 015 pipeline, the researcher substituted apps/desktop for the PRD's apps/electron, documenting it as "technology-agnostic naming." This cascaded into spec artifacts and module definitions, requiring two fixup commits (b142ba9, a8b35cc) and manual mid-pipeline renaming across all affected files.

QA Engineer Prompt — Feedback Loop Protocol (NON-NEGOTIABLE for web/frontend projects)

The QA engineer's prompt MUST include these exact instructions:

You are the QA engineer for this pipeline. You run the `qa-engineer` agent definition.

## SKILLS
- `/kiln:kiln-qa-setup` — Run FIRST. Installs Playwright, scaffolds .kiln/qa/, generates test matrix and test stubs.
- `/kiln:kiln-qa-checkpoint` — During implementation. Tests new flows, sends feedback to implementers.
- `/kiln:kiln-qa-pipeline` — After ALL implementers finish. 4-agent team (e2e + chrome + ux + reporter in pipeline mode). Reporter routes findings to implementers for fixing.
- `/kiln:kiln-qa-final` — Quick gate after /kiln:kiln-qa-pipeline. Just runs playwright tests and confirms green.

## WORKFLOW
1. On startup: Run `/kiln:kiln-qa-setup`
2. If `/kiln:kiln-qa-setup` reports credential-dependent flows, message the team lead:
   "QA CREDENTIALS NEEDED — [list flows]. Please ask the user to fill in .kiln/qa/.env.test."
   Do NOT block — continue testing non-auth flows while waiting.
3. Watch for messages from implementers saying a phase is complete
4. When notified: Run `/kiln:kiln-qa-checkpoint`
5. When an implementer messages "fix ready": Run `/kiln:kiln-qa-checkpoint [flow-name]` to re-test
6. If team lead provides credentials: re-check .kiln/qa/.env.test and unblock auth flows
7. After ALL implementers are done: Run `/kiln:kiln-qa-pipeline` (4-agent team with fix routing)
8. After `/kiln:kiln-qa-pipeline` completes: Run `/kiln:kiln-qa-final` (quick green/red gate)
9. Mark your task as completed via TaskUpdate ONLY after `/kiln:kiln-qa-final` is green
10. Notify the auditor that QA is complete and report is ready

## CREDENTIALS
- NEVER hardcode or guess credentials — always load from .kiln/qa/.env.test
- NEVER log, screenshot, or expose credentials in video recordings
- If credentials aren't provided, mark affected flows as SKIPPED in the QA report — do NOT block the pipeline

## FEEDBACK RULES
- For each FAILURE: send actionable feedback directly to the responsible implementer via SendMessage:
  - What you tested (user flow + steps)
  - What went wrong (with screenshot path)
  - Suggested fix direction
  - Severity (Critical/Major/Minor)
- For each PASS: send brief confirmation to the implementer
- Re-test promptly when an implementer says "fix ready" — you're in their critical path

Do NOT mark your task as completed until the final pass is done and all artifacts are committed.
Your task completion is the signal that triggers the auditor — it needs your QA report and video links for the PR.

Why this is needed: A QA engineer that only runs after implementation misses the chance to catch visual bugs while the implementer still has context. By running checkpoint passes during implementation and sending feedback directly to implementers, bugs get fixed in the same phase they're introduced — not discovered hours later in a final audit.

Implementer Prompt — QA Feedback Protocol (when QA engineer is present)

When a QA engineer is on the team, add this to every implementer's prompt:

A QA engineer (qa-engineer) is testing your work as you build it. After completing each phase:
1. Commit your work
2. Send a message to qa-engineer: "Phase N complete — [list of user flows now testable]. Dev server runs on port [port]."
3. Continue to your next phase — do NOT wait for QA results
4. If qa-engineer sends you feedback about a failure:
   a. Read the feedback carefully (it includes what they tested, what failed, and a suggested fix)
   b. Fix the issue in your current phase if possible, or note it for a dedicated fix pass
   c. After fixing, message qa-engineer: "Fix ready for [flow name] — please re-test"
5. QA feedback fixes are part of your work — do NOT mark your task as completed until QA issues in your scope are resolved

Implementer Prompt — Test Substrate Hierarchy (NON-NEGOTIABLE for any test fixture work)

EVERY implementer prompt MUST include this block when the implementer authors test fixtures (which is most pipelines):

**Test substrate hierarchy** — when authoring fixtures, cite evidence in this order:

1. **Live workflow substrate** — if a `/kiln:kiln-test <plugin> <fixture>` substrate exists for the workflow under test (e.g. `plugin-kiln/tests/perf-kiln-report-issue/`), that is PRIMARY evidence. Run it and cite the verdict report at `.kiln/logs/kiln-test-<uuid>.md`.
2. **Pure-shell unit fixtures** (`run.sh`-only pattern, dominant in `plugin-wheel/tests/`) — invoke directly via `bash <fixture>/run.sh` and cite exit code + last-line PASS summary + assertion count. The kiln-test harness CANNOT discover these (only test.yaml-bearing dirs are discoverable per `plugin-wheel/scripts/harness/wheel-test-runner.sh`) — this is a known substrate gap (B-1 in PRs #166 + #168 blockers.md), NOT a discipline failure.
3. **Structural fixtures** (greps over migrated text, file existence checks) — TERTIARY, only acceptable when (1) and (2) are infeasible.

When the spec says "invoke `/kiln:kiln-test plugin-X <fixture>`" for a `run.sh`-only fixture, treat as "invoke OR direct bash-run with PASS-cite — substrate-appropriate" until the harness ships a `harness-type: shell-test` substrate (roadmap item `2026-04-25-shell-test-substrate`). Cite the substrate you used in your friction note so the auditor doesn't have to re-derive it.

Do NOT silently substitute structural fixtures for live substrates that exist. If you skip a live substrate, document why in your friction note — the auditor will check.

Why this is needed: Two consecutive PRDs (PR #166, PR #168) shipped with the same B-1 substrate carveout in blockers.md because the discipline ("invoke + cite kiln-test verdict") was absorbed but the substrate physically can't run the dominant fixture format. Naming the hierarchy explicitly prevents the next implementer from re-discovering the carveout for a third PRD. Direct lesson from issue #167 PI-1+PI-2 + issue #169 PI-1.

Auditor Prompt — Implementation Completeness Check (NON-NEGOTIABLE)

The auditor's prompt MUST include these exact instructions:

Before starting your audit, verify that ALL implementation AND QA are truly complete:
1. Run `TaskList` and check that every implementer task has status `completed` — not `in_progress`, not `pending`
2. If a qa-engineer task exists, verify it is also `completed` (QA final pass done, videos exported)
3. Read `tasks.md` and verify that every task assigned to implementers is marked `[X]`
4. If ANY implementer or qa-engineer task is still in progress or unchecked, do NOT begin auditing. Instead:
   - Message the team lead: "Audit blocked — task {id} is not yet complete."
   - Wait for the team lead to confirm all work is done before proceeding.

Do NOT audit a partially-complete implementation. Your audit findings are only valid against the final state of the code.

If a QA engineer ran, read `.kiln/qa/latest/QA-REPORT.md` and include its findings in your audit:
- Reference the QA pass/fail verdict
- Link video artifacts in the PR body (.kiln/qa/latest/videos/*.webm)
- Flag any remaining QA failures as blockers

Why this is needed: In the 015 pipeline, the auditor started at 20:05 and documented blockers (missing v2 template, missing Zero/Drizzle/Auth), but the implementer committed those exact fixes at 20:06 and 20:12. The auditor was working against incomplete implementation because it began as soon as its task dependency resolved — but the implementer had marked its coarse-grained task as "completed" before finishing all phases of work.

Auditor Prompt — Live-Substrate-First Rule (NON-NEGOTIABLE for live-runtime gates)

The auditor's prompt MUST include this block when ANY NFR/SC item is a live-runtime gate (e.g., live-smoke, perf, or end-to-end behavioral verification):

**Live-substrate-first rule** — when verifying a live-runtime gate (live-smoke, perf, end-to-end), cite evidence in this order BEFORE reaching for structural fixtures or sub-agent re-runs:

1. **Live workflow substrate** — check whether a `/kiln:kiln-test <plugin> <fixture>` substrate exists that exercises the workflow under test against post-PRD code:
     ls plugin-*/tests/ | grep -E '(perf|smoke|live)-<workflow-name>'
   If such a substrate exists, that IS your canonical evidence. Run it and cite the verdict report path + the underlying TSV/JSON output. Structural fixtures and sub-agent re-runs are SECONDARY evidence and may NOT substitute for an available live substrate.
2. **Wheel-hook-bound workflows** — if the workflow under test activates wheel hooks (Stop, PostToolUse), it is NOT driveable from sub-agent context — Stop hooks bind to the primary session. If no kiln-test substrate exists for a wheel-hook-bound workflow, escalate to team-lead. Do NOT silently substitute a structural fixture and call the NFR satisfied. **2a. CLAUDE.md Rule 5 carve-out (newly-shipped agents)** — when the workflow under test spawns an agent shipped in the same PR, live-spawn is forbidden in-session. Tier-2 direct-invocation PASS-cite of the contract under test (jq expression / shell branch logic / mocked LLM spawn) is canonical evidence — NOT a substrate downgrade. Document the carve-out in the audit report so the live-integration path is queued for the next session. **2b. Skill-body cache lag carve-out (newly-shipped skill changes)** — when the PR modifies `plugin-kiln/skills/<skill>/SKILL.md` (or any plugin's skill body), a `Skill({skill: ...})` invocation in-session expands the PUBLISHED plugin cache (pre-PR body), not the working tree. Auditor MUST detect this case (`git diff --name-only main..HEAD | grep -E 'plugin-[^/]+/skills/[^/]+/SKILL.md'`) and either (a) invoke the skill via `/kiln:kiln-test`'s `--plugin-dir <repo-root>/plugin-<name>` override path so the working-tree body executes, or (b) document a `B-PUBLISH-CACHE-LAG` blocker entry citing this carve-out and queue the live verification for the post-merge session. Choosing (b) without (a) is acceptable only when (a) is not yet wired.
3. **Structural surrogate fallback** — only when (1) and (2) are exhausted. When you fall back, document explicitly in your friction note: which live substrate you tried, why it failed, what structural surrogate you used, and what evidence the surrogate provides for the gate.

If the spec says "live-smoke" but you used a structural surrogate, the auditor's job is to flag the gap to team-lead, NOT to silently downgrade the gate. The team-lead decides whether to escalate to user, accept the surrogate, or build the missing substrate.

Why this is needed: NFR-G-4 became a checkbox in PR #166 — both auditor and team-lead reached for structural surrogates first. The user intervened with "are you using the kiln-test skill?" Without that nudge, the PRD would have shipped on a structural-only verdict. PR #168 absorbed the discipline (audit-compliance reached for the proven substrate without prompting) but the gap is still latent — this rule makes the live substrate the FIRST reach, not the last. Direct lesson from issue #167 PI-1 (Theme A) + issue #169 Theme A.

Auditor Prompt — Blocker Reconciliation Before PR (NON-NEGOTIABLE)

The auditor's prompt MUST also include:

Before creating the PR, reconcile blockers.md against the current code state:
1. Re-read every blocker in blockers.md
2. For each blocker, check if the code has been updated since it was documented:
   - Run `git log --oneline` and check for commits that may have addressed the blocker
   - Read the affected files to verify current state
3. If a blocker has been resolved by a later commit, update its status to "RESOLVED" with the commit hash
4. Update the compliance summary table to reflect the actual final state
5. Commit the updated blockers.md before creating the PR

The PR must reflect the FINAL state of the code, not a point-in-time snapshot from mid-implementation.

When creating the PR, always add the `build-prd` label:

gh pr create --label "build-prd" --title "[feature-name]: [short description]" --body "$(cat <<'PREOF'
## Summary
- [bullet points from audit findings]

## Compliance
- PRD coverage: X%
- Test coverage: X%
- Blockers: N (see specs/{feature}/blockers.md)

## QA Results
- Smoke test: PASS/FAIL
- Visual QA: PASS/FAIL/SKIPPED — [video count] recordings
- QA Report: .kiln/qa/latest/QA-REPORT.md

## Test plan
- [ ] Tests pass (`npm test`)
- [ ] Build succeeds (`npm run build`)
- [ ] Smoke test passes
- [ ] Visual QA passes (if applicable)

🤖 Generated with [Claude Code](https://claude.com/claude-code)
PREOF
)"

Why this is needed: In the 015 pipeline, blockers.md cited B-001 (missing v2 template), B-002 (missing Zero/Drizzle/Auth), and B-003 (only 2 UI components) as critical gaps with 65% compliance. But the implementer fixed all three in later commits. The blockers.md was never updated, so the PR would have shipped with a stale 65% compliance figure when the actual number was higher.

Key Rules for All Teammates

Include these in every teammate prompt:

  • Read .specify/memory/constitution.md before any code changes
  • Run the kiln slash commands — don't reimplement their logic
  • Mark tasks via TaskUpdate (in_progress → completed)
  • After completing a task, check TaskList for the next unblocked, unassigned task
  • Message the next teammate by name when their work is unblocked
  • No two teammates should edit the same file — each owns specific file sets
  • Every exported function MUST match specs/<feature>/contracts/interfaces.md exactly
  • Mark tasks [X] in tasks.md IMMEDIATELY after completing each one
  • Commit after each phase, not in one big batch
  • Coverage gate: >=80%
  • Scope-change protocol: If you receive a message containing "SCOPE CHANGE" from the team lead, finish your current task, commit your work, and STOP. Do not start any new tasks until you receive a "RESUME" message. After resuming, re-read tasks.md and contracts/interfaces.md before starting your next task — they may have changed.

Teammate Idle Behavior

Teammates go idle after every turn — this is normal. An idle teammate can still receive messages. If a teammate sends a message and then goes idle, that's the expected flow (they sent their message and are waiting for a response). Do NOT treat idle as an error or shutdown.

Step 4: Monitor and Steer

After spawning, you are the team lead. Your job is coordination, not implementation.

  1. Messages arrive automatically — no need to poll. When teammates send messages, they appear as new conversation turns.
  2. Do NOT implement tasks yourself — wait for teammates to complete their work.
  3. If a teammate reports a blocked task that should be unblocked, nudge the blocking teammate or update the task status.
  4. If a teammate is stuck on an error, investigate and provide guidance via SendMessage.
  5. If a teammate stops early (tasks remain incomplete), spawn a replacement to continue.
  6. Track progress via TaskList — check periodically to see what's done and what's blocked.

Handling Teammate Communication

  • Use SendMessage with the teammate's name (not agentId) to communicate.
  • Peer DM visibility: when teammates message each other, a brief summary appears in their idle notification. This is informational — you don't need to respond.
  • Use broadcast sparingly — token costs scale with team size.

Stall Detection (FR-005)

Monitor agent activity and detect stalled agents. A stalled agent wastes pipeline time and blocks downstream work.

Default timeout: 10 minutes (configurable per-project by adjusting this value).

How to detect stalls:

  • Track the last activity time for each agent (last commit, task update, or message sent)
  • Each time you process a task update or receive a message, check all in_progress tasks
  • If any agent's task has been in_progress for longer than the stall timeout with no commits, task updates, or messages from that agent, it is considered stalled

When a stall is detected:

  1. Send a check-in message to the stalled agent: "Your task has been in_progress for [N] minutes with no activity. Are you stuck? Please report your status."
  2. If the agent responds and activity resumes, reset the stall timer
  3. If the agent does not respond after a second check-in (another timeout period), escalate:
    • Spawn a replacement agent to continue from where the stalled agent left off
    • Or investigate the agent's last output for errors and provide guidance

Phase Dependency Enforcement (FR-006)

When dispatching implementer agents that work on multi-phase task lists, enforce phase ordering:

Rule: Do NOT dispatch or unblock Phase N+1 agents until ALL tasks in Phase N are marked [X] in tasks.md.

How to enforce:

  1. Before dispatching each implementer or sending a "proceed to next phase" message, read tasks.md
  2. Check that every task in the current phase is marked [X]
  3. If any task in the current phase is still [ ], do NOT dispatch the next phase's agents
  4. When all tasks in Phase N are complete, message the Phase N+1 agents: "Phase N is complete. You are unblocked to begin Phase N+1."

Why: Without enforcement, agents can race ahead and build on incomplete foundations, causing cascading failures. A Phase 2 agent that starts before Phase 1 is done may reference code that doesn't exist yet.

Mid-Pipeline Auditor Checkpoint

When approximately 50% of implementer tasks in tasks.md are marked [X], spawn a short-lived audit-midpoint agent to catch structural issues early — before the full audit at the end. This prevents problems like the missing Dockerfile in the obsidian-mcp-mvp pipeline (issue #14) from being caught only at final audit.

How to trigger: While monitoring via TaskList, track the ratio of completed implementer tasks. When it crosses ~50%, spawn the midpoint auditor.

audit-midpoint agent prompt (spawn with run_in_background: true):

You are a lightweight mid-pipeline auditor. Your job is to catch structural gaps EARLY, not to do a full compliance audit. Check these specific things:

1. **Deployment artifacts**: Read plan.md's "Deployment Readiness" section. For every artifact marked "Yes", verify the file exists or has a task assigned in tasks.md. Flag any missing artifacts.
2. **Contract compliance**: Spot-check 3-5 implemented functions against contracts/interfaces.md. Flag signature mismatches.
3. **Structural completeness**: Verify the project structure in plan.md matches what's been created so far. Flag missing directories or misnamed paths.

Report findings to the team lead via SendMessage. Do NOT fix anything — just report. Keep it brief: a bulleted list of gaps found (or "No structural gaps found").

After reporting, mark your task as completed. This is a one-shot check, not an ongoing role.

Create a task for this agent in Step 2 (e.g., "Mid-pipeline structural check") with dependencies on the specifier task only (it runs during implementation, not after). The final auditors do NOT depend on this task — it's advisory.

Docker Rebuild Between Implementation and QA (FR-008)

When all implementers have completed their tasks and before dispatching QA agents for the final pass, check if the project uses Docker:

# Check for Docker configuration in the project root
if [ -f "Dockerfile" ] || [ -f "docker-compose.yml" ] || [ -f "docker-compose.yaml" ] || [ -f "compose.yml" ] || [ -f "compose.yaml" ]; then
  echo "Docker project detected — rebuilding containers before QA"
  if [ -f "docker-compose.yml" ] || [ -f "docker-compose.yaml" ] || [ -f "compose.yml" ] || [ -f "compose.yaml" ]; then
    docker compose build 2>&1 || echo "WARNING: Docker rebuild failed — QA may test stale containers"
  else
    docker build -t "$(basename $(pwd))" . 2>&1 || echo "WARNING: Docker rebuild failed — QA may test stale containers"
  fi
fi

Rules:

  • Only run this step if Dockerfile or docker-compose.yml (or compose.yml variants) exists in the project root
  • If no Docker configuration exists, skip this step entirely
  • If the rebuild fails, log a warning and proceed to QA — do NOT block the pipeline. QA agents will detect stale containers via their own pre-flight checks.
  • Run this AFTER all implementers mark their tasks as completed but BEFORE dispatching QA final pass or audit agents

Handling Scope Changes Mid-Pipeline

If the user changes scope, updates the PRD, or asks to modify requirements while implementers are already running:

  1. Immediately broadcast a PAUSE to all implementers and the QA engineer: Send each a message: "SCOPE CHANGE — stop current work after finishing your current task. Do NOT start any new tasks. Commit what you have and wait for further instructions."
  2. Wait for all to acknowledge the pause. Check TaskList — no implementer or QA engineer should have tasks in in_progress state after acknowledging. If someone doesn't respond, send the pause message again.
  3. Update spec artifacts: Have the specifier (or yourself) update spec.md, plan.md, contracts/interfaces.md, and tasks.md to reflect the new scope. Commit the updated artifacts.
  4. Notify everyone of what changed: Send each implementer a targeted message listing which tasks are added, removed, or modified. Send the QA engineer a message listing which user flows changed so it can update its test matrix.
  5. Resume: Send each a message: "RESUME — scope change applied. Re-read tasks.md and contracts/interfaces.md before starting your next task." The QA engineer should re-run /kiln:kiln-qa-setup to regenerate the test matrix.

Why this matters: Without an explicit pause, implementers work against stale spec artifacts and the QA engineer tests against outdated flows. The pause-update-resume cycle ensures all agents work from the same source of truth.

Step 4b: Issue Lifecycle Completion (FR-007, FR-008)

After the audit-pr agent creates the PR, and before spawning the retrospective, the team lead completes the issue lifecycle for this build. Step 4b runs inline in the team lead's main-chat context (NOT a dedicated agent).

  1. Identify the PRD path and PR number (set during pipeline orchestration):

    PRD_PATH="<the PRD path used for this build, e.g. docs/features/2026-04-23-pipeline-input-completeness/PRD.md>"
    PR_NUMBER="<the PR number from audit-pr, e.g. 145>"
    TODAY="$(date -u +%Y-%m-%d)"
    LOG_FILE=".kiln/logs/build-prd-step4b-${TODAY}.md"
    mkdir -p .kiln/logs
  2. Path normalization helper (defined inline):

    # normalize_path <raw>: strip leading ./, trailing /, and surrounding whitespace.
    # Echoes empty string if the path is absolute (starts with /) or empty after stripping.
    normalize_path() {
      local raw="$1"
      # strip surrounding whitespace incl. CR
      raw="$(printf '%s' "$raw" | tr -d '\r' | sed -E 's/^[[:space:]]+//; s/[[:space:]]+$//')"
      # reject absolute
      case "$raw" in
        /*) printf '' ; return 0 ;;
      esac
      # strip leading ./
      raw="${raw#./}"
      # strip trailing /
      raw="${raw%/}"
      printf '%s' "$raw"
    }
    
    PRD_PATH_NORM="$(normalize_path "$PRD_PATH")"

2b. Read derived_from: frontmatter (FR-004, FR-005 — spec prd-derived-from-frontmatter):

# read_derived_from <prd-path>
# Extracts the `derived_from:` list from the first YAML frontmatter block
# of the PRD. Emits one repo-relative path per line on stdout.
# Emits NOTHING (and returns 0) if:
#   - the PRD has no frontmatter block, OR
#   - the block has no `derived_from:` key, OR
#   - the list is empty (`derived_from: []` OR `derived_from:` with no child rows).
# Never exits non-zero — read failures degrade to "no entries" (Step 4b then falls to scan-fallback).
read_derived_from() {
  local prd="$1"
  [ -f "$prd" ] || { return 0; }
  awk '
    BEGIN { state = "before"; emit = 0 }
    # Close on the second --- (end of frontmatter block)
    state == "inside" && /^---[[:space:]]*$/ { exit 0 }
    # Open on the first --- (must be the first non-empty line)
    state == "before" && /^---[[:space:]]*$/ { state = "inside"; next }
    # Bail if the first non-empty line is not ---
    state == "before" && NF > 0 { exit 0 }
    # Inside the block
    state == "inside" {
      # Start of derived_from key (inline empty list or block-sequence header)
      if ($0 ~ /^derived_from:[[:space:]]*(\[\])?[[:space:]]*$/) {
        emit = 1
        next
      }
      # Any other top-level key closes the emit window
      if (emit == 1 && $0 ~ /^[A-Za-z_][A-Za-z0-9_]*:/) {
        emit = 0
        next
      }
      # Block-sequence entry under derived_from
      if (emit == 1 && $0 ~ /^[[:space:]]+-[[:space:]]+/) {
        # Strip the leading "  - " and any trailing CR/whitespace
        sub(/^[[:space:]]+-[[:space:]]+/, "", $0)
        sub(/[[:space:]]+$/, "", $0)
        gsub(/\r/, "", $0)
        if (length($0) > 0) print $0
      }
    }
  ' "$prd"
}

# Read derived_from once; empty means fall through to scan-fallback.
DERIVED_FROM_LIST=()
while IFS= read -r entry; do
  [ -n "$entry" ] && DERIVED_FROM_LIST+=("$entry")
done < <(read_derived_from "$PRD_PATH")

if [ "${#DERIVED_FROM_LIST[@]}" -gt 0 ]; then
  DERIVED_FROM_SOURCE="frontmatter"
else
  DERIVED_FROM_SOURCE="scan-fallback"
fi

# missing_entries is ONLY populated on the frontmatter path. Always initialized so
# the extended diagnostic line emits `missing_entries=[]` on the scan-fallback path.
MISSING_ENTRIES=()
  1. Scan for matching items — frontmatter-path primary, scan-fallback secondary (FR-004, FR-005, FR-006):

    The frontmatter path iterates DERIVED_FROM_LIST directly and tracks missing on-disk entries. The scan-fallback path runs the PR-#146 scan-and-match loop verbatim.

    SCANNED_ISSUES=0
    SCANNED_FEEDBACK=0
    MATCHED=0
    ARCHIVED=0
    SKIPPED=0
    MATCH_LIST=()  # absolute or repo-relative paths to archive
    
    if [ "$DERIVED_FROM_SOURCE" = "frontmatter" ]; then
      # Frontmatter-path scan (FR-004, FR-006): iterate derived_from list.
      # SCANNED_* reflect the derived_from list (not a directory scan) — preserves the
      # diagnostic's original field semantics ("what the step looked at").
      for entry in "${DERIVED_FROM_LIST[@]}"; do
        case "$entry" in
          .kiln/issues/*)   SCANNED_ISSUES=$((SCANNED_ISSUES + 1)) ;;
          .kiln/feedback/*) SCANNED_FEEDBACK=$((SCANNED_FEEDBACK + 1)) ;;
        esac
    
        if [ ! -f "$entry" ]; then
          # Missing entry — record in diagnostic, continue (FR-006: no pipeline abort).
          MISSING_ENTRIES+=("$entry")
          continue

Truncated - read the full file at https://github.com/yoshisada/ai-repo-template/blob/84093dce77a3ecf72a39f4309315e1df05afe5d1/plugin-kiln/skills/kiln-build-prd/SKILL.md.

Use it

Copy one of these into your project. Installing also returns the manifest and these snippets.

yaml
targets:
  - https://api.opensmartroute.ai/api/v1/registry/yoshisada-ai-repo-template-kiln-build-prd/manifest   # or paste the manifest below

Manifest

An Open Capability Manifest: the router reads it to know what this does, what it costs and when to pick it.

yoshisada-ai-repo-template-kiln-build-prd.ocm.jsonjson
{
  "ocm": "1",
  "id": "yoshisada-ai-repo-template-kiln-build-prd",
  "kind": "skill",
  "name": "kiln-build-prd",
  "description": "Run the complete kiln pipeline using an agent team. Reads the PRD to determine team structure, then orchestrates specify → plan → tasks → implement → audit → PR.",
  "publisher": "yoshisada",
  "version": "1.0.0",
  "capabilities": {
    "domains": [
      "general"
    ],
    "tags": [
      "skill-md",
      "github"
    ],
    "languages": [
      "en"
    ]
  },
  "quality_prior": 0.6,
  "examples": [
    "Run the complete kiln pipeline using an agent team. Reads the PRD to determine team structure, then orchestrates specify → plan → tasks → implement → audit → PR."
  ],
  "primary": false,
  "metadata": {
    "source": {
      "provider": "github",
      "repository": "https://github.com/yoshisada/ai-repo-template",
      "path": "plugin-kiln/skills/kiln-build-prd/SKILL.md",
      "ref": "84093dce77a3ecf72a39f4309315e1df05afe5d1",
      "url": "https://github.com/yoshisada/ai-repo-template/blob/84093dce77a3ecf72a39f4309315e1df05afe5d1/plugin-kiln/skills/kiln-build-prd/SKILL.md",
      "key": "yoshisada/ai-repo-template/plugin-kiln/skills/kiln-build-prd/SKILL.md"
    },
    "compatibility": "Requires spec-kit project structure with .specify/ directory"
  },
  "instructions": "# Kiln Run — Full Pipeline via Agent Team\n\n## User Input\n\n```text\n$ARGUMENTS\n```\n\nYou **MUST** consider the user input before proceeding (if not empty). The user input is the feature description.\n\n## Pre-Flight\n\n1. **Verify agent teams are available (NON-NEGOTIABLE).**\n   Before anything else, check that `TeamCreate` is available as a tool. If it is NOT available, **STOP immediately** and tell the user:\n   > \"Agent teams are not enabled. `/kiln:kiln-build-prd` requires Claude Code agent teams to orchestrate the pipeline.\n   >\n   > To enable them, add this to your Claude Code settings or launch",
  "cost": {
    "context_tokens": 23511
  }
}

Fetch it by URL: GET /api/v1/registry/yoshisada-ai-repo-template-kiln-build-prd/manifest?version=1.0.0

Reviews

Star ratings from people who tried it. One review per account; edit yours any time.

No reviews yet. Install it, try it, and be the first to rate it.

kiln-build-prd - Skill - OpenSmartRoute