task-board-setup

v2026.09.24

Generator: deploys a file-based Kanban into any repo via multi-agent analysis, an optional spec + system-design layer (task-spec skill, per-task spec/design docs, domain-architect fan-out), and an optional gated CLAUDE.md-optimization pass. `upgrade` retrofits the spec layer onto an already-deployed board. Triggers: init task board, scaffold kanban, task tracker, upgrade task board, канбан-доска, спек-слой.

GitHub
安装命令
npx skhub add kochetkov-ma/task-board-setup
Markdown
SKILL.md
<!-- brewcode-meta: version=6.2.0 content_version=5.6.0 generated_by=brewtools:task-board-setup -->

[DICT: TT=task-tracker agent (generated), TB=task-board skill (generated), BRD=board.md, FEAT=.claude/features, EXCL=source-path exclusions, REL=release style (vX.Y.Z tag | commit SHA | no tag), DOM=domain id segment, FM=frontmatter, TS=task-spec skill (generated), SPEC_MODE=spec+design layer opt-in, PS=status phase, PU=upgrade phase, PR=uninstall/purge phase]

task-board-setup

Generator. Run from the MAIN conversation in (or pointed at) a TARGET repo. Deploys a self-contained, file-based Kanban into that repo:

EmitsPathMirrors etalon
Curator agent.claude/agents/task-tracker.mdbrewpage task-tracker.md
Dashboard skill.claude/skills/task-board/SKILL.mdyasna task-board SKILL
Paths-scoped rule.claude/rules/tasks.mdbrewpage tasks.md
Board + control files.claude/features/{board,PROGRESS,TRACKER,TASK_TEMPLATE,INDEX}.md + {backlog,todo,progress,closed,specs}/brewpage .claude/features/**
Spec skill (SPEC_MODE only).claude/skills/task-spec/SKILL.mdreferences/08-task-spec-skill.md
Spec template (SPEC_MODE only).claude/features/specs/SPEC_TEMPLATE.mdreferences/09-spec-templates.md
Design template (SPEC_MODE only).claude/features/specs/DESIGN_TEMPLATE.mdreferences/09-spec-templates.md

SPEC_MODE (confirmed in P1) gates the three rows above AND every spec-related addition inside the other emitted artifacts. SPEC_MODE=off -> nothing spec-related is emitted and every artifact is byte-identical to the pre-spec-layer generator.

PROGRESS.md is UNGATED -- the session-progress artifact and every site that references it belong to BOTH modes' baseline. SPEC_MODE never removes them; byte-identity above means identical to the pre-spec-layer generator plus those sites. Each reference's own header enumerates its ungated sites (02, 03, 04, 05) -- read it there, !=count from here.

This skill ORCHESTRATES. It does not hand-do the bulk analysis or the doc sweep -- it spawns subagents (Task) for those passes and integrates their output. All emitted artifacts are PARAMETRIZED from Step 1 findings; templates live in references/.

Spawn from MAIN only. This skill is inline (no context), so its Task spawns are first-level. Do not nest.

Read reference templates with the Read tool using ${CLAUDE_SKILL_DIR}/references/<file> to load them into context.

Fence rule -- GLOBAL, every emit on every path (P2, P3, P3.5, P4a-b, and PU's U3/U4 drift-ADD). When writing any generated file, unescape its inner code fences (\``` -> ```) so the emitted file has valid fences. Stated once here; the reference templates !=repeat it.

Prompt contract

Position 1 of $ARGUMENTS is a free-form prompt -- the verb, the target path and the optional directive (P0 below) may all follow it in any order, exactly as P0 already parses them. Nobody types keys: a plain sentence resolves the verb.

ModeEN keywordsRU keywordsMutates?
status(empty), status, check, show, what's deployedстатус, проверь, покажи, что стоитno
installinstall, setup, deploy, scaffold, init, create boardустанови, разверни, создай доску, настройyes
upgradeupgrade, retrofit, add spec layer, updateобнови, добавь спек-слой, апгрейдyes
enableenable, turn on, resume, unpauseвключи, возобнови, сними паузуyes
disabledisable, turn off, pause, muteвыключи, поставь на паузу, приглушиyes
uninstalluninstall, remove, unwireудали, убери, деинсталлируйyes
purgepurge, wipe, delete everything, nukeвычисти, снеси, удали всёyes, destructive

The verb-detection rule already in P0 (a standalone canonical token wins outright; a word merely containing one inside a sentence does not) IS this contract's steps 1-2 -- no reordering needed, P0 already scores correctly. Empty / no verb -> the documented default: status on a deployed board, else install into the resolved TARGET (P0's "No verb given" rule). A destructive tie (uninstall vs purge) still goes to AskUserQuestion; that already happens in P0's two-verb-conflict rule. Prose that names no canonical verb is DIR (the free-text directive), never guessed as a verb or path.

Immediately after P0 finalizes MODE and TARGET -- before dispatching into PS/PU/PE/PR/P1 -- print this block once:

PLAN — brewtools:task-board-setup
INPUT:  <arguments verbatim, or "(empty)">
MODE:   <resolved> -- <explicit | matched keyword: X | default>
SCOPE:  <TARGET>; SPEC_MODE <on|off|n/a>; touching <files this run will write, or "read-only">
DO:     <2-5 imperative bullets>
RESULT: <artifacts the user ends up holding -- board.md + control files, or the status report>

Labels are literal ASCII; values follow the conversation language.

Every skill this generator emits (task-board, and task-spec when SPEC_MODE=on) carries this same contract baked into its own template -- prompt-first hint, its own keyword table, its own PLAN block. P5's prompt-contract gate below verifies both.

Delegation

A big task handed to one agent = an agent gone for an hour: you cannot observe it, cannot correct it, and it usually drifts off-target. One subagent = ONE bounded unit -- ONE doc group, ~<=5 files, ~<=10 steps. Bigger MUST be split into N tasks, all spawned in ONE message. Applies to both spawn points: P1 analysis and P4c doc sweep.

Every spawn prompt MUST carry:

FieldContent
GOALthe overall task and why it exists -- the point beyond the file edit
ROLEwhat this agent owns; what it must NOT touch
SCOPEexact paths/commands in bounds + explicit out-of-bounds
CONTEXTwhat is already done, by whom, what runs in parallel -- trimmed to what THIS agent needs
CONSUMERwho or what uses the result next, and the shape it must fit
DONEacceptance criteria + the exact report shape you want back

A bare one-line task is never enough. Shape (P4c sweep agent):

Task(subagent_type="general-purpose", prompt="
GOAL: deploying a file-based Kanban into TARGET; the board skeleton exists and this pass
  fills it from the repo's pre-existing task docs. Sibling agents handle other doc groups.
ROLE: you own <these DOCS>. Do NOT create tasks that no document supports, do NOT edit
  source dirs, do NOT touch CLAUDE.md.
SCOPE: in -- write ONLY under TARGET/.claude/features/**; read the listed DOCS.
  Out -- EXCLUSIONS (<list from P1>), TARGET/CLAUDE.md, .claude/agents, .claude/skills.
CONTEXT: P1 already confirmed DOMAINS=<...>, REL_STYLE=<...>, LANG=<...> with the user, and
  P4a-b already wrote the board skeleton, TASK_TEMPLATE.md (id convention) and board.md
  (row format) -- read them, do not reinvent either. Sibling agents sweep the other doc
  groups into the same tree right now, so touch only the DOCS listed for you.
CONSUMER: P5 verification counts what landed under closed/ + backlog/, and the installed
  task-tracker agent reads those files from then on -- an id or status dir that deviates from
  TASK_TEMPLATE.md makes the task invisible to it.
DONE: files written under closed/ + backlog/, and a manifest: docs migrated by status,
  docs trashed, board rows authored. A no-op sweep must say so explicitly.
")

P0: Resolve verb + target repo + parse directive

$ARGUMENTS carries THREE optional, order-independent things: (a) a MODE verb, (b) a target repo PATH, (c) a free-text DIRECTIVE that tunes the optional CLAUDE.md-optimization phase (e.g. "also dedupe rules", "skip module split", "report only"). Disambiguate:

  • A standalone token (case-insensitive) from the canonical set status | install | upgrade | enable | disable | uninstall | purge sets MODE and is CONSUMED -- it never reaches DIR. A word merely containing one of them inside a sentence (e.g. "upgrade the rules wording") is NOT the verb; only a standalone token is. Two conflicting verbs -> AskUserQuestion.
  • A token that resolves to an existing directory (abs, or relative to cwd) = the PATH. Empty / unresolvable-as-dir = cwd.
  • Everything else (the remaining free text) = DIR, passed verbatim to P5.5. If no path-like token is present, the whole non-verb argument is DIR and TARGET=cwd.
  • If ambiguous (e.g. a bare word that is both a plausible relative dir and a directive verb), prefer PATH only if it resolves to an existing dir; else treat as DIR.

init, on, off, setup, remove, reset, create, update and cleanup are NOT verbs any more. Recognize init/setup/create in free text as a synonym of install, update as a synonym of upgrade, on/off as synonyms of enable/disable, and remove/reset/cleanup as a synonym of uninstall/purge (ask which), then always echo the canonical verb back. Never print a removed alias as a command.

No verb given -- resolve MODE from the board itself, after TARGET is known: a deployed board (TARGET/.claude/features/board.md exists) -> status; nothing deployed -> install into that TARGET. A bare path on a fresh repo therefore still installs, and a bare invocation on a repo that already has a board reports instead of touching anything.

EXECUTE using Bash tool. Set ARG to the path-like token (or .):

ARG="{{ARGUMENTS_PATH_OR_DOT}}"   # the path-like token, or . for cwd
TARGET="$(cd "$ARG" 2>/dev/null && pwd)"
test -n "$TARGET" && test -d "$TARGET" && echo "TARGET=$TARGET" && echo "OK" || echo "FAIL: target not a dir"

STOP if FAIL -- ask the user for a valid repo path.

Shell state does NOT survive between Bash tool calls. Every call is a fresh shell: a variable another block assigned is EMPTY here. So EVERY later block that consumes TARGET MUST open by re-establishing it literally -- TARGET="<absolute path resolved in P0>", with the actual resolved path written in, !=the variable name, !=a re-derivation. Same for anything derived from it (F, T). This applies to all blocks below without exception.

Gate blocks assert before they test. A block whose SILENCE (or whose sole OK line) is read as PASS MUST first prove it ran, by opening with this exact statement:

test -n "$TARGET" && test -d "$TARGET" || { echo "MISS TARGET unresolved -- re-resolve per P0"; exit 1; }

Without it an empty TARGET makes the test run against a nonexistent path, the error gets eaten by 2>/dev/null / || true, and the gate reports PASS having checked nothing. "No output == PASS" is true ONLY when the gate actually ran.

{{ARGUMENTS_PATH_OR_DOT}} is resolved inline in P0 (the parsed path-like token, or .), not a template-emit placeholder -- it is absent from the Placeholder map by design.

Record DIR = the remaining free text (may be empty) and MODE (status|install|upgrade|enable|disable|uninstall|purge, or unset); hold both.

Branch on board presence. An existing TARGET/.claude/features/board.md means the board is already deployed. install refuses it; upgrade, enable, disable, uninstall and purge EXPECT it.

EXECUTE using Bash tool:

TARGET="<absolute path resolved in P0>"
test -n "$TARGET" && test -d "$TARGET" || { echo "MISS TARGET unresolved -- re-resolve per P0"; exit 1; }
test -f "$TARGET/.claude/features/board.md" && echo "EXISTS" || echo "FRESH"

Resolve an unset MODE here: EXISTS -> status, FRESH -> install. Then dispatch:

MODEboard.mdDo
statuseithergo to PS. Read-only -- never writes, never asks
installFRESHcontinue to the MAJOR-4 guard, then P1 (fresh deploy)
installEXISTSSTOP. "Board already deployed. To retrofit the spec + design layer onto it, re-run as /brewtools:task-board-setup upgrade <path>. To operate the existing board, use /task-board." Do not overwrite
upgradeEXISTSgo to PU -- control transfers to references/10-upgrade.md. Skip P1-P5.5 entirely
upgradeFRESHSTOP. "Nothing to upgrade: no .claude/features/board.md in TARGET. Run /brewtools:task-board-setup install <path> to deploy a fresh board"
enableEXISTSgo to PE with WANT=enable
disableEXISTSgo to PE with WANT=disable
enable / disableFRESHrun PS instead and report that nothing is deployed. There is no machinery to toggle
uninstallEXISTSgo to PR with KEEP_DATA=true
purgeEXISTSgo to PR with KEEP_DATA=false
uninstall / purgeFRESHrun PS instead and report that nothing is deployed. Do not delete anything on a guess

Print the ## Prompt contract PLAN block once here -- MODE and TARGET are both resolved -- before continuing into the dispatched phase.

MAJOR 4 -- idempotency guard. install path ONLY (MODE=install and board.md FRESH); upgrade, uninstall and purge skip it, since pre-existing artifacts are exactly what they operate on. A FRESH board.md does not prove a clean slate: a prior run may have left other artifacts. After the board.md check, EXECUTE using Bash tool:

TARGET="<absolute path resolved in P0>"
test -n "$TARGET" && test -d "$TARGET" || { echo "MISS TARGET unresolved -- re-resolve per P0"; exit 1; }
PARTIAL=""
for p in .claude/agents/task-tracker.md .claude/skills/task-board/SKILL.md .claude/rules/tasks.md \
  .claude/skills/task-spec/SKILL.md; do
  # A parked `.disabled` twin still occupies the slot -- an install over it would orphan it.
  test -f "$TARGET/$p" -o -f "$TARGET/$p.disabled" && PARTIAL="$PARTIAL $p"
done
test -z "$PARTIAL" && echo "CLEAN" || echo "PARTIAL:$PARTIAL"

If PARTIAL: is non-empty (and board.md was FRESH), STOP and report the partial deployment. Do NOT blindly overwrite -- ask the user whether to clean those artifacts and redo, or abort. upgrade is NOT the fix here: with no board.md there is nothing to upgrade.


PS: Status (read-only inventory of the TARGET)

Runs for MODE=status -- the default on an already-deployed board -- as the fallback when enable/disable/uninstall/purge find nothing, and as the proof block after PE and PR. Writes nothing, spawns nothing, asks nothing.

EXECUTE using Bash tool:

TARGET="<absolute path resolved in P0>"
test -n "$TARGET" && test -d "$TARGET" || { echo "MISS TARGET unresolved -- re-resolve per P0"; exit 1; }
C="$TARGET/.claude"; F="$C/features"
# A `.disabled` twin is a PARKED artifact (see PE), not a missing one -- never report it as MISS.
for p in agents/task-tracker.md skills/task-board/SKILL.md rules/tasks.md skills/task-spec/SKILL.md \
  features/board.md features/PROGRESS.md features/TRACKER.md features/TASK_TEMPLATE.md features/INDEX.md \
  features/specs/SPEC_TEMPLATE.md features/specs/DESIGN_TEMPLATE.md; do
  if test -f "$C/$p"; then echo "  ok   $p"
  elif test -f "$C/$p.disabled"; then echo "  off  $p (parked as $(basename "$p").disabled)"
  else echo "  MISS $p"; fi
done
for d in backlog todo progress closed specs; do
  n=$(ls -1 "$F/$d"/*.md 2>/dev/null | wc -l | tr -d ' ')
  test -d "$F/$d" && echo "  ok   features/$d/ ($n md)" || echo "  MISS features/$d/"
done
echo "TARGET=$TARGET"

Report, in this shape:

task-board-setup — status
target:     <TARGET>
deployed:   yes|no|partial            (board.md present / absent / some artifacts only)
machinery:  enabled|DISABLED|mixed    (every artifact live / every one parked as .disabled / some of each)
spec layer: on|off|parked             (.claude/skills/task-spec/SKILL.md present / absent / .disabled)
tasks:      backlog=N todo=N progress=N closed=N specs=N
next:       install | upgrade | enable | nothing to do

partial -> name the missing artifacts and say a fresh install refuses to overwrite; the user must clean them first. deployed: yes + no spec layer -> next: upgrade. machinery: DISABLED -> next: enable, and say the tasks are all still there. machinery: mixed -> list which side each artifact is on and recommend re-running the verb that was interrupted.


PU: Upgrade mode (retrofit onto a deployed board)

Runs ONLY when MODE=upgrade and board.md EXISTS. Replaces P1-P5.5 -- do not run the fresh-init phases.

Load the upgrade procedure:

Read file: ${CLAUDE_SKILL_DIR}/references/10-upgrade.md

Hand it:

InputValue
TARGETresolved in P0
DIRremaining free text from P0 (may be empty)
recovered FINDINGSDOMAINS, EXCLUSIONS, LANG re-read from the DEPLOYED artifacts (.claude/rules/tasks.md, .claude/features/TRACKER.md, .claude/agents/task-tracker.md), NOT re-derived from scratch. Anything unrecoverable is ASKED of the user per 10-upgrade.md U2 -- !=re-analysed, !=guessed. P1 does NOT run on this path, and Agent C (row below) is the only analysis spawn in upgrade mode
Agent C outputDOMAIN_AGENTS, ARCHITECT_AGENT, AGENT_GAPS -- always run fresh (the target's agent roster is the whole point)
SPEC_MODEforced on

Rules that bind the whole phase:

  • Additive only. New files (task-spec skill, SPEC_TEMPLATE.md, DESIGN_TEMPLATE.md) are written outright. No existing task file, board row, agent, skill or rule is rewritten wholesale.
  • Every edit of an existing file is gated: show the exact diff, then AskUserQuestion per file. Declined = no edit, continue cleanly.
  • The metadata restamp (10-upgrade.md U5b) is UNGATED and always runs, including when every content row is already SKIP. It rewrites version / generated_by / last_updated in the frontmatter of the nine stamped artifacts and nothing else -- that is the ONLY thing that clears the stale verdict /brewcode:setup-status reads off board.md. An upgrade that reports success without moving the stamp sends the user round the same loop next session.
  • Never renumber, never delete. Existing task ids, scope ids and closed tasks are untouchable. board.md rows are never REORDERED and existing cell content is never CHANGED -- the one allowed row edit is APPENDING the new spec cell holding -- to each existing Progress/Todo row, per 10-upgrade.md U4 (header + separator cells patch with it; a 6-column header over 5-cell rows is corruption, not caution). spec: FM backfill is opt-in and !=run by default -- the default writes nothing to task files. When the user accepts it, the value is pending or none per the needs-spec heuristic -- never full.

PU is a thin handoff: 10-upgrade.md owns detect, verify and report. Do NOT reuse P5 here.


PE: Enable / Disable (park or restore the machinery, keep every task)

Runs for MODE=enable / MODE=disable on a deployed board. Replaces P1-P5.5. Writes no content, deletes nothing, spawns nothing.

Claude Code discovers a project agent only as .claude/agents/<name>.md, a project skill only as <dir>/SKILL.md, and auto-loads a rule only as .claude/rules/*.md. Withholding that one filename is therefore the whole switch:

Artifactdisableenable
.claude/agents/task-tracker.md-> task-tracker.md.disabledback
.claude/skills/task-board/SKILL.md-> SKILL.md.disabledback
.claude/skills/task-spec/SKILL.md (when the spec layer is deployed)-> SKILL.md.disabledback
.claude/rules/tasks.md-> tasks.md.disabledback
.claude/features/** (board, control files, every task and spec)untoucheduntouched

disable leaves the board fully readable as plain markdown and every generated file byte-identical -- only the extension Claude Code keys on is withheld. Nothing is regenerated on enable: no re-analysis, no subagents, no confirmation of FINDINGS. This is the reversible pause; uninstall is the removal.

Skill directories are parked at their SKILL.md, never by renaming the directory -- references/ beside it must keep resolving for anyone reading the files by hand.

EXECUTE using Bash tool (substitute WANT):

TARGET="<absolute path resolved in P0>"
test -n "$TARGET" && test -d "$TARGET" || { echo "MISS TARGET unresolved -- re-resolve per P0"; exit 1; }
C="$TARGET/.claude"
WANT=WANT   # enable | disable
MOVED=0; NOOP=0; MISSING=0
for p in agents/task-tracker.md skills/task-board/SKILL.md skills/task-spec/SKILL.md rules/tasks.md; do
  live="$C/$p"; parked="$C/$p.disabled"
  if [ "$WANT" = "disable" ]; then from="$live"; to="$parked"; else from="$parked"; to="$live"; fi
  if [ -f "$from" ]; then
    mv "$from" "$to" && echo "  MOVED $p -> $(basename "$to")" && MOVED=$((MOVED + 1))
  elif [ -f "$to" ]; then
    echo "  NOOP  $p already $WANT""d"; NOOP=$((NOOP + 1))
  else
    echo "  ABSENT $p (not deployed)"; MISSING=$((MISSING + 1))
  fi
done
echo "WANT=$WANT MOVED=$MOVED NOOP=$NOOP ABSENT=$MISSING"
test "$MOVED" -gt 0 -o "$NOOP" -gt 0 && echo "OK" || echo "FAIL nothing to toggle"

STOP if FAIL -- none of the four artifacts is present in either state; the deployment is broken, report it and offer install after a purge.

ABSENT skills/task-spec/SKILL.md alone is EXPECTED on a board installed with SPEC_MODE=off -- it is not an error. MOVED=0 with NOOP>0 means the board was already in the requested state: say so, change nothing else.

Then run the PS block again and print its report -- it is the proof, not the OK line. Close by naming the reversal verb and stating that .claude/features/** was not touched, so every task survived.


PR: Uninstall / Purge (remove what this skill deployed)

Runs for MODE=uninstall (KEEP_DATA=true) and MODE=purge (KEEP_DATA=false). Replaces P1-P5.5.

Removeduninstallpurge
.claude/agents/task-tracker.mdyesyes
.claude/skills/task-board/yesyes
.claude/skills/task-spec/yesyes
.claude/rules/tasks.mdyesyes
any .disabled twin of the four above (parked by disable)yesyes
.claude/features/** (board, control files, every task and spec)KEPTyes

The split is deliberate: the generated agent/skills/rule are MACHINERY, .claude/features/** is the user's DATA -- every task they ever wrote. uninstall unwires the machinery and leaves the data readable; only purge deletes the tasks.

Confirm before deleting. Print the exact file list from PS and AskUserQuestion once. For purge the question MUST state the task counts being destroyed (closed=N included) and offer uninstall (keep the data) as an alternative option. A declined confirmation ends the run cleanly -- delete nothing.

EXECUTE using Bash tool (substitute KEEP_DATA):

TARGET="<absolute path resolved in P0>"
test -n "$TARGET" && test -d "$TARGET" || { echo "MISS TARGET unresolved -- re-resolve per P0"; exit 1; }
C="$TARGET/.claude"
KEEP_DATA=KEEP_DATA   # true for uninstall, false for purge
# The `.disabled` twins go too -- removing a DISABLED board would otherwise leave the parked files behind.
rm -f  "$C/agents/task-tracker.md" "$C/agents/task-tracker.md.disabled" \
       "$C/rules/tasks.md" "$C/rules/tasks.md.disabled"
rm -rf "$C/skills/task-board" "$C/skills/task-spec"
test "$KEEP_DATA" = "false" && rm -rf "$C/features"
test ! -e "$C/agents/task-tracker.md" && test ! -e "$C/agents/task-tracker.md.disabled" \
  && test ! -e "$C/skills/task-board" && echo "OK removed" || echo "FAIL still present"

Then run the PS block again and print its report -- it is the proof, not the OK line.

CLAUDE.md is never reverted. If P5.5 optimized the target's CLAUDE.md on the way in, that edit stays: it is the user's prose by now, and this skill has no record of the original. Say so explicitly in the final report and point at git history for a revert.


P1: Multi-agent repo analysis (Step 1)

Load the analysis contract and confirmation template:

Read file: ${CLAUDE_SKILL_DIR}/references/01-analysis.md

Follow it to spawn analysis subagents IN PARALLEL (one message, multiple Task calls). Spawn the agents prescribed there (default: Plan for domains + release style, Explore for source-path exclusions + doc inventory, Agent C for the domain-agent inventory). Each returns a structured block. Integrate into a single FINDINGS object:

DOMAINS   = [ ... ]   # per-repo first-kebab id segments, derived from the repo
EXCLUSIONS= [ ... ]   # source dirs TT must NEVER write (e.g. src/, backend/, e2e-tests/, docs/)
REL_STYLE = vtag | sha | none   # detected from git tags / CI / CLAUDE.md release flow
LANG      = English | <repo doc language>
DOCS      = [ ... ]   # existing backlog/feature/task docs found, for the Step-4 sweep
DOMAIN_AGENTS  = [ ... ]  # Agent C: TARGET .claude/agents/** -> agent | domains covered | specialty
ARCHITECT_AGENT= <name>   # Agent C: best architecture-capable project agent, else `Plan`
AGENT_GAPS     = [ ... ]  # Agent C: DOMAINS with no owning agent -> they fall back to `Plan`

Present FINDINGS to the user with AskUserQuestion per the contract in 01-analysis.md (confirm/override DOMAINS and EXCLUSIONS especially). Do not generate until the user confirms.

In the SAME confirmation, also ask whether to run the optional CLAUDE.md optimization phase (P5.5) after the board is deployed. Default: offer it; if the user passed a DIR directive in $ARGUMENTS, default the answer to YES. Record OPTIN.

In the SAME confirmation, also confirm SPEC_MODE (on | off) -- per the contract in references/01-analysis.md, which owns the exact question wording. on = non-trivial tasks additionally get specs/<ID>-spec.md + specs/<ID>-design.md, and the task-spec skill is emitted. Show AGENT_GAPS in the question so the user decides with the fallback cost visible. Record SPEC_MODE.

SPEC_MODE=off is the compatibility contract: every emitted artifact is byte-identical to the pre-spec-layer generator. It is not a "reduced" mode, it is the old mode.

Empty DOMAINS edge: if analysis yields no domains, do NOT proceed with an empty {{DOMAINS}} (it would produce broken ids like T--SLUG); ask the user to name at least one domain via AskUserQuestion, or fall back to a single CORE domain.


Placeholder map

The reference templates carry these placeholders. Derive each from the confirmed FINDINGS before substituting. {{RELEASE_STYLE}} is the INPUT enum (vtag|sha|none) only -- it is NOT a literal token in any template; it picks the close-marker wording below.

Order is fixed, substitution is TWO-PASS. Pass 1: expand the gated placeholders (inventory below). Pass 2: substitute the base placeholders in the table below over the WHOLE result. A gated expansion may itself contain a base token (02's {{SPEC_TRIGGERS}} expansion contains {{FIRST_DOMAIN}}); the reverse never happens. Reversing the passes emits a literal {{FIRST_DOMAIN}}.

Two brace spellings, on purpose. This skill's own tokens are DOUBLE-brace ({{DOMAINS}}, {{TODAY}}, {{SPEC_*}} ...). The four metadata tokens are SINGLE-brace -- {PLUGIN_VERSION}, {CONTENT_VERSION}, {GENERATED_BY}, {LAST_UPDATED} -- the repo-wide spelling fixed by brewcode/skills/setup-status/references/artifact-metadata.md. Substitute both sets in pass 2; a leftover {PLUGIN_VERSION} in an emitted file is as broken as a leftover {{DOMAINS}}.

PlaceholderOwner refsDerivation
{{DOMAINS}}01,02,04,05,08,10confirmed domain id-segment list, comma-separated (e.g. HTML, KV, SITE)
{{FIRST_DOMAIN}}02,04,05,08,09,10DOMAINS[0]
{{EXCLUSIONS}}02,08,10confirmed source-dir exclusion list
{{REPO_NAME}}05,08,09,10basename of TARGET
{{LANG}}02,03,04,05,08,09,10confirmed doc language
{{TODAY}}05,08,09,10today's date, ISO (YYYY-MM-DD)
{PLUGIN_VERSION}02,03,04,05,08,10brewtools plugin version, X.Y.Z. Resolved by the bash block below -- NEVER hardcoded, never guessed
{CONTENT_VERSION}02,03,04,05,08,10this SKILL.md's own content_version, read from its line-1 brewcode-meta: marker (below the frontmatter) -- self-located, same as {PLUGIN_VERSION}, never a copy of it
{GENERATED_BY}02,03,04,05,08,10the literal brewtools:task-board-setup
{LAST_UPDATED}02,03,04,05,08,10same value as {{TODAY}}, quoted in YAML frontmatter. Metadata spelling of the date; {{TODAY}} stays the prose/card spelling
{{CLOSE_MARKER}}02,10derived from RELEASE_STYLE: vtag -> "vX.Y.Z tag + commit SHA"; sha -> "commit SHA"; none -> "date / no tag / superseded / cancelled". Exact per-ref wording maps live in 02 and 03
{{CLOSE_MARKER_SHORT}}03,04,05,10same enum, short form: vtag -> "vX.Y.Z tag"; sha -> "commit SHA"; none -> "no tag". 04 and 05 reuse 03's map
{{DOMAIN_AGENTS}}08,10a COMPLETE markdown table from Agent C's inventory of TARGET .claude/agents/** -- header row + |---| separator + one row per agent, columns exactly agent | domains covered | specialty. Consumers paste it bare, so a bodiless expansion renders as literal pipe text. Exception: no agents found -> the non-table literal line (none found -- fall back to the built-in Plan agent and say so in Evidence)
{{ARCHITECT_AGENT}}08,10ARCHITECT_AGENT from Agent C: the best architecture-capable project agent name; none -> the literal Plan
{{RELEASE_STYLE}}02 (header)INPUT enum vtag|sha|none. Gate variable ONLY -- NOT a literal token in any emitted body; it picks the close-marker wording above
{{SPEC_MODE}}03,04,09 (headers)on | off, as confirmed in P1. Gate variable ONLY -- like {{RELEASE_STYLE}} it is NOT a literal token in any template and is never substituted into an emitted body; it selects which gated blocks expand

Resolving {PLUGIN_VERSION} / {CONTENT_VERSION} / {GENERATED_BY} / {LAST_UPDATED}

Run ONCE, before P2, and hold the four values for every emitted file. EXECUTE using Bash tool:

SD="${CLAUDE_SKILL_DIR}"
if [ -n "$SD" ] && [ -f "$SD/../../.claude-plugin/plugin.json" ]; then BT_ROOT=$(cd "$SD/../.." && pwd); else BT_ROOT=$(ls -d ~/.claude/plugins/cache/claude-brewcode/brewtools/*/ 2>/dev/null | sort -V | tail -1 | sed 's:/*$::'); fi
[ -n "$BT_ROOT" ] || { echo "ERROR: cannot locate brewtools plugin root -- install/update brewtools first."; exit 1; }
PV=$(jq -r '.version // empty' "$BT_ROOT/.claude-plugin/plugin.json" 2>/dev/null || true)
PV=${PV:-$(basename "$BT_ROOT")}
# content_version -- this SKILL.md's own header marker, self-located the same way PV is.
SKILL_MD="$BT_ROOT/skills/task-board-setup/SKILL.md"
CV=$(grep -m1 'brewcode-meta:' "$SKILL_MD" | sed -n 's/.*content_version=\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/p')
[ -n "$CV" ] || { echo "ERROR: cannot read content_version from $SKILL_MD -- reinstall brewtools."; exit 1; }
echo "PLUGIN_VERSION=$PV"
echo "CONTENT_VERSION=$CV"
echo "GENERATED_BY=brewtools:task-board-setup"
echo "LAST_UPDATED=$(date +%F)"

Why the bare form. CLAUDE_SKILL_DIR is a TEXT SUBSTITUTION on the skill prompt, not an env var: CC 2.1.226 rewrites only the EXACT dollar-brace literal {CLAUDE_SKILL_DIR} (replace(/\$\{CLAUDE_SKILL_DIR\}/g, dirname(skillPath)) and a string-pattern replaceAll). A brace-modifier form such as :-fallback inside the braces is therefore NOT matched, reaches the shell verbatim, and its fallback ALWAYS wins. CLAUDE_PLUGIN_ROOT is a real env var but is exported only to hook processes and MCP servers -- never to a skill's Bash tool -- so it is ALWAYS empty here. The skill dir is correct in a cache install AND in a --plugin-dir dev run; the cache glob below it is a last-resort fallback only, and it would name the INSTALLED plugin. If PLUGIN_VERSION comes back empty or non-X.Y.Z, STOP and report -- do not emit a file with a guessed or literal-placeholder version.

These three feed the four-key metadata frontmatter (doc_type: llm, version, generated_by, last_updated) on every emitted artifact: the task-tracker agent (02), the task-board (03) and task-spec (08) skills, the tasks.md rule (04), and the five .claude/features/** control files (05). doc_type is the literal llm -- no placeholder. Per-task CARD frontmatter (id/title/status/priority/owner/created/updated/tags/links/spec) is domain data and never carries these keys.

Gated placeholders -- the convention

The spec layer adds gated blocks inside otherwise-unchanged templates, following the {{CMD_DECOMPOSED_NOTE}} convention already used in references/02-task-tracker-agent.md. Every gated placeholder has exactly ONE of TWO kinds -- line or inline -- declared in the header of its owning reference file, alongside its expansion. That header is the source of truth for the EXPANSION TEXT and the whitespace handling; the inventory below is the complete name / kind / gate index.

RuleDetail
Every gate is per-tokenA gated placeholder carries its OWN gate CONDITION -- SPEC_MODE=on, SPEC_MODE=off, or CMD_DECOMPOSED=true. "Emitted" always means THAT condition is true. There are TWO gate variables, and one of them has an off arm: !=assume the condition is SPEC_MODE=on, !=key any removal off SPEC_MODE alone
Kind linethe token is the only reason its line exists. Condition TRUE -> replace the whole LINE with the expansion. Condition FALSE -> REMOVE the whole LINE. No blank line left behind, no orphan heading, no trailing separator
_ON / _OFF armsan _ON/_OFF pair is ONE gate written as two adjacent line placeholders. _ON emits when the gate is on; _OFF emits when the gate is off; the other arm's line is REMOVED. EXACTLY one arm of the pair survives every run, in BOTH modes -- !=both, !=neither, !=a third kind. The _OFF arm is how a line placeholder rewrites a baseline line back to its byte-identical original
Kind inlinethe token sits inside a line that exists in BOTH modes. Condition TRUE -> replace the TOKEN with the expansion. Condition FALSE -> delete the TOKEN only; the line stays
inline whitespacedeclared per site by its own reference file. BOTH forms are legal, do NOT unify them: some sites carry a single space BEFORE the token, deleted together with it (02); others carry no leading space and the expansion supplies its own (03, 05). Follow the reference header, never a global rule
SPEC_MODE=off resultthe emitted artifact is byte-identical to the pre-spec-layer output. This holds only if every token was resolved against its OWN condition -- an _OFF arm dropped as if it were an on token breaks byte-identity
Verificationafter substitution, grep -nE '\{\{|\{(PLUGIN_VERSION|CONTENT_VERSION|GENERATED_BY|LAST_UPDATED)\}' the written file -- any surviving {{...}} OR single-brace metadata token is an unresolved placeholder and a defect. P5 executes this over every emitted path

Gated placeholder inventory (complete)

PlaceholderKindEmitted whenOwner ref
{{CMD_DECOMPOSED_NOTE}}lineCMD_DECOMPOSED=true02
{{CMD_DECOMPOSED_INVARIANT}}lineCMD_DECOMPOSED=true02
{{SPEC_TRIGGERS}}inlineSPEC_MODE=on02
{{SPEC_BRD_COL}}inlineSPEC_MODE=on02
{{SPEC_TRIAGE_BLOCK}}lineSPEC_MODE=on02
{{SPEC_CHECKLIST}}lineSPEC_MODE=on02
{{SPEC_BRD_FEATURES_ON}}lineSPEC_MODE=on02
{{SPEC_BRD_FEATURES_OFF}}lineSPEC_MODE=off02
{{SPEC_DESC_TRIGGERS}}inlineSPEC_MODE=on03
{{SPEC_ADD_ROW_COL}}inlineSPEC_MODE=on03
{{SPEC_INVARIANTS}}lineSPEC_MODE=on03
{{SPEC_ADD_STEP}}lineSPEC_MODE=on03
{{SPEC_MOVE_STEPS}}lineSPEC_MODE=on03
{{SPEC_VIEW_FLOW}}lineSPEC_MODE=on03
{{SPEC_FM_FIELD}}inlineSPEC_MODE=on04
{{SPEC_RULES}}lineSPEC_MODE=on04
{{SPEC_COL_H}}inlineSPEC_MODE=on05
{{SPEC_COL_S}}inlineSPEC_MODE=on05
{{SPEC_LC_CLOSE}}inlineSPEC_MODE=on05
{{SPEC_FEATURE_TABLE_HEAD_ON}}lineSPEC_MODE=on05
{{SPEC_FEATURE_TABLE_HEAD_OFF}}lineSPEC_MODE=off05
{{SPEC_FM_LINE}}lineSPEC_MODE=on05
{{SPEC_SCOPE_BLOCK}}lineSPEC_MODE=on05
{{SPEC_BOARD_COL_NOTE}}lineSPEC_MODE=on05
{{SPEC_TRACKER_SECTION}}lineSPEC_MODE=on05
{{SPEC_INDEX_ROWS}}lineSPEC_MODE=on05

Two _ON/_OFF pairs exist: {{SPEC_BRD_FEATURES_*}} (02, board section-6 line) and {{SPEC_FEATURE_TABLE_HEAD_*}} (05, board.md ## Feature specs header + separator).

{{SPEC_INVARIANTS}} lives in 03 ONLY -- the 02 copy was cut. Names are FILE-SCOPED: resolve every gated token against its owner's header, never across files. Refs 01, 06, 07, 08, 09, 10 declare NO gated placeholders. 08 and 09 are gated at WHOLE-FILE granularity (emitted only when SPEC_MODE=on); the file is the gate, not a token. A {{TOKEN}} in 10 is prose, not a placeholder.

Gated surfaces by reference: 02 spec triage + checklist + description triggers + board cols/section-6; 03 SPECS view + add/move steps + invariant + description triggers + add-row col; 04 spec rules 13-22 + spec: FM field; 05 TRACKER section 10 + spec: FM line + ## Scope block + board spec column + Feature-specs header + INDEX rows + lifecycle close gate.


P2: Generate task-tracker agent (Step 2)

Load the agent template:

Read file: ${CLAUDE_SKILL_DIR}/references/02-task-tracker-agent.md

Substitute every placeholder per the Placeholder map above; each reference file's header also lists the placeholders it uses. Write the result to TARGET/.claude/agents/task-tracker.md. The template mirrors the brewpage etalon: prime directive (BRD canonical), layout, lifecycle state machine, invariants, id convention, BRD format, grooming loop, procedures, finishing checklist.

RELEASE_STYLE shapes the closing-marker wording: vtag -> vX.Y.Z tag + commit SHA; sha -> bare commit SHA; none -> date / no tag / superseded / cancelled.


P3: Generate task-board skill (Step 3)

Load the skill template:

Read file: ${CLAUDE_SKILL_DIR}/references/03-task-board-skill.md

Substitute placeholders, then Write to TARGET/.claude/skills/task-board/SKILL.md. The template mirrors the yasna etalon: on-demand dashboard with flows view / add / move / backlog / groom, delegating non-trivial / bulk passes to the task-tracker agent.


P3.5: Generate task-spec skill (SPEC_MODE only)

Run ONLY if SPEC_MODE=on. If off, skip silently -- write nothing, mention nothing.

Load the skill template:

Read file: ${CLAUDE_SKILL_DIR}/references/08-task-spec-skill.md

Substitute placeholders ({{DOMAIN_AGENTS}}, {{ARCHITECT_AGENT}}, {{DOMAINS}}, {{LANG}}, {{REPO_NAME}}, plus whatever the reference header declares), then Write to TARGET/.claude/skills/task-spec/SKILL.md.

The emitted skill is the spec + design authoring flow: resolve id -> read task + existing specs -> parallel domain research -> parallel domain-architect design fan-out -> synthesize design -> synthesize spec -> AskUserQuestion on open questions -> parallel domain-expert review -> coverage gate -> write docs + update task FM and the board row.

disable-model-invocation MUST NOT be set on the emitted skill: plain-prose invocation is a first-class path, alongside /task-spec <ID> [full|design|refresh] and the task-tracker NEXT: run /task-spec <ID> (...) redirect.

Domains with no owning agent (AGENT_GAPS) fall back to the built-in Plan. That fallback must be recorded per domain in the emitted design's ## Evidence -- silence is a defect.


P4: Generate rule + scaffold + doc sweep (Step 4)

4a. Rule

Load the rule template:

Read file: ${CLAUDE_SKILL_DIR}/references/04-tasks-rule.md

Substitute placeholders, then Write to TARGET/.claude/rules/tasks.md. Frontmatter paths: [".claude/features/**"]. It mirrors the brewpage rule PLUS one extra rule: at the START of ANY task, run the task-tracker agent in ISOLATION (a spawned subagent, NOT inlined). This rule lives ONLY in .claude/rules/tasks.md -- explicitly NOT in CLAUDE.md. Steps P0-P5 do NOT touch the target's CLAUDE.md; the ONLY sanctioned, gated way to modify it is the optional P5.5 phase below (opt-in, every change behind AskUserQuestion).

4b. Scaffold .claude/features/**

Load the file templates:

Read file: ${CLAUDE_SKILL_DIR}/references/05-features-templates.md

Create the folder tree + control files. git mv is not needed (fresh files):

EXECUTE using Bash tool:

TARGET="<absolute path resolved in P0>"
test -n "$TARGET" && test -d "$TARGET" || { echo "MISS TARGET unresolved -- re-resolve per P0"; exit 1; }
F="$TARGET/.claude/features"
mkdir -p "$F"/{backlog,todo,progress,closed,specs} && echo "OK scaffold" || echo "FAIL scaffold"

Then Write each control file from 05-features-templates.md (placeholders substituted): board.md, PROGRESS.md, TRACKER.md, TASK_TEMPLATE.md, INDEX.md, backlog/README.md. PROGRESS.md is UNGATED -- written in both SPEC_MODE states, at init, so the session has a progress surface before the first task exists.

If SPEC_MODE=on, additionally load:

Read file: ${CLAUDE_SKILL_DIR}/references/09-spec-templates.md

Substitute placeholders and Write both documents into the specs/ dir already created by the mkdir above:

From 09-spec-templates.mdWrite to
SPEC_TEMPLATETARGET/.claude/features/specs/SPEC_TEMPLATE.md
DESIGN_TEMPLATETARGET/.claude/features/specs/DESIGN_TEMPLATE.md

If SPEC_MODE=off, write neither. specs/ stays an empty dir, exactly as before.

4c. Multi-agent doc sweep

Load the sweep procedure:

Read file: ${CLAUDE_SKILL_DIR}/references/06-doc-sweep.md

Follow it to spawn sweep subagents IN PARALLEL over the DOCS inventory from Step 1: dedup, delete cruft, migrate ready/done tasks into closed/, format backlog/, and author the initial board.md counts/tables from what was found. The board authored in 4b is the empty skeleton; this pass fills it.

Empty DOCS edge: if the DOCS inventory from Step 1 is empty, SKIP the sweep (4c) entirely; board.md stays the empty skeleton from 4b. Do not spawn a sweep agent with nothing to do, and never invent tasks.

The sweep subagents write ONLY under TARGET/.claude/features/**. They must respect the EXCLUSIONS -- never edit source dirs.


P5: Verify + report

EXECUTE using Bash tool:

TARGET="<absolute path resolved in P0>"
test -n "$TARGET" && test -d "$TARGET" || { echo "MISS TARGET unresolved -- re-resolve per P0"; exit 1; }
for p in .claude/agents/task-tracker.md .claude/skills/task-board/SKILL.md .claude/rules/tasks.md \
  .claude/features/board.md .claude/features/PROGRESS.md .claude/features/TRACKER.md \
  .claude/features/TASK_TEMPLATE.md .claude/features/INDEX.md .claude/features/backlog/README.md; do
  test -f "$TARGET/$p" && echo "OK  $p" || echo "MISS $p"
done
for d in backlog todo progress closed specs; do
  test -d "$TARGET/.claude/features/$d" && echo "OK  folder $d" || echo "MISS folder $d"
done

If SPEC_MODE=on, also EXECUTE using Bash tool:

TARGET="<absolute path resolved in P0>"
test -n "$TARGET" && test -d "$TARGET" || { echo "MISS TARGET unresolved -- re-resolve per P0"; exit 1; }
for p in .claude/skills/task-spec/SKILL.md \
  .claude/features/specs/SPEC_TEMPLATE.md .claude/features/specs/DESIGN_TEMPLATE.md; do
  test -f "$TARGET/$p" && echo "OK  $p" || echo "MISS $p"
done

If SPEC_MODE=off, skip that loop -- and assert the inverse: none of those three paths may exist.

Leftover-placeholder gate. BOTH brace families, or it misses half the tokens: this skill's own tokens are DOUBLE-brace ({{DOMAINS}} ...) and the four metadata tokens are SINGLE-brace ({PLUGIN_VERSION}, {CONTENT_VERSION}, {GENERATED_BY}, {LAST_UPDATED}). No emitted body legitimately contains either, so every hit is an unresolved placeholder. Runs in BOTH modes over every emitted path (the SPEC_MODE=on paths simply do not exist when off). || true keeps a clean run's rc=1 from aborting the block -- which is exactly why the block MUST assert TARGET first: with TARGET empty the grep hits a nonexistent path, rc=2 is swallowed by 2>/dev/null + || true, and the gate prints OK having read nothing. EXECUTE using Bash tool:

TARGET="<absolute path resolved in P0>"
test -n "$TARGET" && test -d "$TARGET" || { echo "MISS TARGET unresolved -- re-resolve per P0"; exit 1; }
test -d "$TARGET/.claude/features" || { echo "MISS nothing emitted -- gate did not run"; exit 1; }
LEFT="$(grep -rnE '\{\{|\{(PLUGIN_VERSION|CONTENT_VERSION|GENERATED_BY|LAST_UPDATED)\}' \
  "$TARGET/.claude/features" "$TARGET/.claude/rules/tasks.md" \
  "$TARGET/.claude/agents/task-tracker.md" "$TARGET/.claude/skills/task-board" \
  "$TARGET/.claude/skills/task-spec" 2>/dev/null || true)"
test -z "$LEFT" && echo "OK  no leftover placeholders" || { echo "MISS leftover placeholders:"; echo "$LEFT"; }

A clean run PRINTS OK no leftover placeholders. No output at all = the block did not run, !=PASS -- fix the block and re-run.

Prompt-contract gate. Every emitted skill must carry the workspace prompt contract: the argument-hint starts with [prompt] and the body contains a PLAN — block. EXECUTE using Bash tool:

TARGET="<absolute path resolved in P0>"
test -n "$TARGET" && test -d "$TARGET" || { echo "MISS TARGET unresolved -- re-resolve per P0"; exit 1; }
FAIL=0
for f in "$TARGET/.claude/skills/task-board/SKILL.md" "$TARGET/.claude/skills/task-spec/SKILL.md"; do
  test -f "$f" || continue
  grep -qE '^argument-hint: "\[prompt\]' "$f" && echo "OK  hint $f" || { echo "MISS hint $f"; FAIL=1; }
  grep -q '^PLAN — ' "$f" && echo "OK  PLAN $f" || { echo "MISS PLAN block $f"; FAIL=1; }
done
test "$FAIL" -eq 0 && echo "OK prompt contract" || echo "FAIL prompt contract"

Any MISS (from any gate above -- existence, leftover-placeholder, prompt-contract) -> re-emit the missing artifact, re-substitute the leftover placeholder, or fix the offending hint/PLAN block, before finishing.

Report to the user:

  • the 9 paths created (+ 5 folders); SPEC_MODE=on adds 3 more
  • DOMAINS, EXCLUSIONS, REL_STYLE, LANG used
  • SPEC_MODE (on/off) and, when on, the {{DOMAIN_AGENTS}} table actually baked into the emitted task-spec skill (agent | domains | specialty) plus ARCHITECT_AGENT
  • AGENT_GAPS -- every domain with NO owning agent, which therefore falls back to the built-in Plan. Always print this, even when empty (AGENT_GAPS: none). A hidden gap is a silently weaker design phase. Non-empty -> suggest /brewcode:agents to author the missing domain agents, then re-run /brewtools:task-board-setup upgrade <path>
  • the sweep manifest counts: docs migrated (by status) / docs trashed / board rows authored -- so a silent no-op sweep is visible
  • next step: /task-board to view, or just start a task (the new rule runs task-tracker at task start). SPEC_MODE=on -> also /task-spec <ID> for any non-trivial task
  • if P5.5 ran: CLAUDE.md lines before->after (vs ~200 optimal / 300 over), local-only items moved to CLAUDE.local.md, modules split into nested CLAUDE.md, rules deduped, whether text-optimize was invoked

Do NOT commit. Committing is a user / manager action.


P5.5: CLAUDE.md optimization (optional, gated)

Run ONLY if OPTIN (from P1) is true. PROPOSE-ONLY: every restructuring is behind AskUserQuestion -- never force a change. This is the sanctioned replacement for the old "do not touch CLAUDE.md" stance.

Load the procedure:

Read file: ${CLAUDE_SKILL_DIR}/references/07-claude-md-optimize.md

Pass it TARGET, DIR (the directive parsed in P0), and EXCLUSIONS/MODULES context from P1. Follow it to: detect + report current-vs-target line count; propose (and on approval apply) local-only extraction to CLAUDE.local.md; over-budget decomposition into nested module CLAUDE.md (loaded on-demand) + path-scoped rules; rules dedup; then delegate token-compression to brewtools:text-optimize on the touched files. Set CMD_DECOMPOSED for the report and for the task-tracker note.

Verified mechanic (code.claude.com/docs/en/memory): root CLAUDE.md loads in full at launch; NESTED subdirectory CLAUDE.md loads ON-DEMAND when Claude works in that subtree; @path imports are EAGER (no context savings). Module detail therefore moves into nested module CLAUDE.md, never @import.

If OPTIN is false, skip silently. Never edit CLAUDE.md outside this phase.


Guards

ConditionResponse
TARGET not a dirSTOP, ask for valid path
upgrade on a DISABLED board (.claude/rules/tasks.md.disabled present, tasks.md absent)STOP. The recovered FINDINGS are read from the deployed artifacts and a parked file is not deployed. Report it and tell the user to run enable first, then upgrade
enable/disable and every one of the four artifacts is absent in BOTH statesSTOP -- the deployment is broken. Report it; do not create files, the toggle never generates
install over a board whose artifacts are parked as .disabledrefused by the MAJOR-4 partial guard -- a .disabled twin still occupies the slot. Tell the user to enable (to resume) or purge (to start over)
board.md FRESH but other primary artifacts present (partial prior run)STOP -- report partial deployment; ask the user whether to clean and redo. Do NOT blindly overwrite. upgrade is not the fix (fresh-init path only; the upgrade path skips this guard)
Reference template missing under ${CLAUDE_SKILL_DIR}/references (incl. 08-task-spec-skill.md, 09-spec-templates.md, 10-upgrade.md when SPEC_MODE=on or upgrade)ERROR: reference not found -- reinstall brewtools. STOP.
SPEC_MODE=on but AGENT_GAPS covers EVERY domain (no project agents at all)ALLOWED -- proceed, {{DOMAIN_AGENTS}} becomes the literal (none found ...) line and every domain falls back to Plan. But SURFACE it loudly in the P5 report and suggest /brewcode:agents to author domain agents, then upgrade
SPEC_MODE=offEmit NOTHING spec-related: no task-spec skill, no spec templates. Every gated placeholder resolved against its OWN condition -- a false line -> line removed, a false inline -> token removed, and the _OFF arm of each pair EXPANDS (its condition is true when the mode is off). Every artifact byte-identical to the pre-spec-layer generator
Design authored without a domain-architect fan-outDefect -- the emitted task-spec skill must spawn >=1 agent per touched domain in ONE message; a lone generalist design is rejected
Upgrade proposes rewriting an existing fileShow the diff and AskUserQuestion first; declined = no edit. Additive-only: never renumber ids, never delete tasks or board rows
User does not confirm FINDINGSDo NOT generate; re-ask or abort
A subagent proposes editing source dirs (EXCLUSIONS)Reject that edit; sweep writes ONLY .claude/features/**
Nested spawn requested (Task from a subagent)Forbidden -- orchestrate from main only
OPTIN true but no root CLAUDE.md in targetreport "no CLAUDE.md to optimize"; skip P5.5; do NOT create a root CLAUDE.md
P5.5 proposal declined by usermake NO edit; continue/finish cleanly (never force)
Secret detected in committed CLAUDE.mdmask value in output; on move, warn gitignore != history purge; never echo full secret
An argument names no canonical verb and no resolvable path, yet is read as one anywaydefect -- P0's own rule: only a standalone canonical token is a verb, only a resolvable dir is a path; everything else is DIR (prose), never guessed
PLAN block missing, or printed after MODE/TARGET dispatch has already started writingdefect -- print it once right after P0 resolves MODE + TARGET, before PS/PU/PE/PR/P1
发现
标签

此技能尚未发布标签。

版本
最新版本元数据

版本

v2026.09.24

发布时间

2026年9月24日

分类

未分类

许可证

NOASSERTION

源路径

brewtools/skills/task-board-setup

默认分支

main

最新提交

7f5b5d8

Tree SHA

5bfd4fc