light-spec
Skill6 starsChanged 2 months agoMITView on GitHub
Structured spec generation with auto-cycled agent review + tier auto-derive (v2.7.0-rc1+). Use when a Linear issue moves to spec stage. Use when writing/refining a feature spec before /work. Use when the Spec Review Agent flags gaps.
In this repository32 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- brainstorm-reviewSkill
- brainstormSkill
- conceptSkill
- defineSkill
- financial-reviewSkill
- light-spec-reviseSkill
- linear-hygieneSkill
- linearSkill
- phase-planSkill
- pipekit-helpSkill
- pipekit-updateSkill
- pk-bugSkill
- pk-exitSkill
- pk-expressSkill
- pr-fixSkill
- prod-readySkill
- pr-security-reviewSkill
- release-changelogSkill
- repo-security-reviewSkill
- review-planSkill
- roadmap-createSkill
- roadmap-reviewSkill
- security-gateSkill
- spec-preflightSkill
- startupSkill
- strategy-createSkill
- strategy-syncSkill
- sync-linearSkill
- tpmSkill
- verifySkill
- workSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
22 rules. About 0 are common, 13 are distinctive, and 9 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈13
Distinctive · estimate
This author's own choices. Worth a look.
9
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 17
Create a light spec — enough structure for /work to generate a plan, but fast enough to draft in one pass.
- Distinctive: line 41
If raw idea: Ask the user for a 1-2 sentence description of what they want and why.
- Distinctive: line 53
Do NOT inline the exploration into the main session even if you think "I can just grep for this quickly." The decision is about context …
- Very specific: line 55
Use the Explore agent (subagent_type: Explore, thoroughness: medium) to answer:
- Distinctive: line 64
Write the spec using the Light Spec Template below.
- Distinctive: line 90
Cross-spec handoff awareness: If this spec references another issue with phrases like *"X will replace…"*, *"X consumes…"*, *"X …
- Distinctive: line 94
Don't leave handoff promises buried in prose.
- Distinctive: line 98
Before presenting to the user, audit every section:
- Very specific: line 121
Read the line matching Complexity: from the spec body.
- Very specific: line 124
If the Complexity line is missing or ambiguous, surface a one-line confirmation prompt before publishing: Complexity not parseable — apply …
- Distinctive: line 136
If this spec changes the database schema, it is not planning-ready until it carries a Migration Plan.
- Very specific: line 139
If no schema change: delete the ### Migration Plan section from the spec.
- Distinctive: line 147
Only runs when Phase 3.7 detected a schema change.
- Distinctive: line 151
If yes, spec two issues with an explicit dependency, not one issue with two halves.
- Very specific: line 175
If yes (default), for each open question, call the AskUserQuestion tool — one question per call so each gets its own dialog.
- Distinctive: line 190
Add a fourth option only when there's a genuinely distinct alternative to the recommendation (e.g., "Persist now" vs "Persist later") — …
- Very specific: line 194
Keep as TBD: leave it in Risks & Open Questions.
- Distinctive: line 195
Drop / out of scope: remove the related Requirements/AC entries.
- Distinctive: line 198
Ask: _"Want to refine anything else before I push this to Linear?"_
- Very specific: line 292
Read the canonical template from templates/light_spec_template.md in the method repo (or pipekit/templates/light_spec_template.md in …
- Very specific: line 334
If you disagree with the auto-derivation, change the Complexity field in the spec body and re-run /light-spec PROJ-XXX — the tier label …
- Distinctive: line 358
When you encounter these situations, take the safer path:
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Light Spec Skill
Draft a structured, plan-ready specification for a Linear issue. Bridges the gap between raw brainstorms and full PLAN.md files.
Triggers
/light-spec— start from scratch or provide an issue ID/light-spec PROJ-123— spec an existing issue
Purpose
Create a light spec — enough structure for /work to generate a plan, but fast enough to draft in one pass. Optionally delegate to Linear's agent for refinement before pulling into planning.
Core Principle
A light spec is an AI→AI contract: Generator → Reviewer → Planner. You are not guiding a human — you are constraining an AI. Every rule in this spec must be:
- Explicit — no implied behavior
- Unambiguous — one interpretation only
- Enforceable — a downstream agent can validate compliance
Controlled incompleteness is allowed. Light specs are intentionally lightweight. Brevity, [TBD] markers, and limited context are fine. Hidden assumptions and implicit behavior are not. The line is: can the planner work without guessing?
Inputs
| Input | Source | Required |
Issue ID (e.g., PROJ-123) | Argument or prompt | No — creates new issue if omitted |
| Idea description | User prompt | Yes, if no issue ID |
Execution Steps
Phase 1 — Capture
- If issue ID provided: Read the issue with its description and thread via the project's Linear route —
pk issue show PROJ-123 --fields id,title,state,labels,priority,project --comments— once (verb table:sop/Linear_SOP.md § Linear transport; themcproute's equivalent is listed there). Extract title, description, existing labels, project, and any sub-issues, and carry those fields through the review cycle — don't re-fetch. On themcproute a full-content read drags the whole comment thread, a sticky payload re-billed every turn (.claude/rules/pipekit-tooling.md§ MCP Result Payloads Are Sticky), and that route's create/update calls in Phase 5 echo the whole spec body back; on either route, do the batch in one subagent, serially, and keep the spec-time loop in the main thread lean. - If raw idea: Ask the user for a 1-2 sentence description of what they want and why.
Phase 2 — Technical Context
Explore the codebase to understand what exists and what's needed.
When to use the Explore subagent (required — recent Claude models default to direct tool calls unless told when to delegate):
This phase MUST spawn an Explore subagent rather than calling Grep/Read directly. Two reasons:
- The exploration produces lots of intermediate output (file listings, pattern matches) that you only need the conclusion from. Keeping it in the subagent's context protects the main session from rot.
- Codebase-wide exploration benefits from parallel search across multiple conventions/locations, which the subagent handles.
Do NOT inline the exploration into the main session even if you think "I can just grep for this quickly." The decision is about context hygiene, not capability.
- Use the
Exploreagent (subagent_type: Explore, thoroughness: medium) to answer:- What existing code/infrastructure is relevant?
- What patterns does the codebase already use for similar features?
- What database tables, APIs, or UI components are involved?
- Are there any obvious constraints or blockers?
- Identify the issue's initiative context from Linear: which
i{N}.initiative andI{N}.P{N}.project its Linear project belongs to. Derive it live (the issue's Linear project, orpk next) — there is nolinear-map.jsonorPHASES.mdto read. This anchors the spec to the right initiative without guessing.
Phase 3 — Draft Light Spec
Write the spec using the Light Spec Template below. Fill in every section.
Decision discipline: All behavior-affecting decisions should be either defined or marked [TBD]. A decision left implicit (not mentioned at all) means the planner will guess, and guesses compound. [TBD] is only valid if it does not block task decomposition. If a [TBD] would force the planner to guess at task boundaries, resolve the decision before the spec is ready.
Scope discipline: Specs define WHAT, not HOW. Litmus test: if a statement can be rewritten as "change X line" or "use Y syntax," it is implementation detail — remove it. If a statement can be rewritten as "the system should [observable behavior]," it belongs in the spec. Do not include file paths to create, function signatures, or implementation patterns — /work's planning step owns the HOW.
Code reference discipline (v4.23.0+): Where the spec legitimately points at existing code (Technical Context, Decisions, AC anchors), reference it — don't paste it. Cite path + symbol or heading (e.g. `src/lib/format.ts` → `formatCurrency()`), preferring symbols over raw line numbers — line numbers rot fastest, a symbol survives edits above it, and /spec-preflight resolves symbols empirically. Use a line number only as a secondary qualifier when the symbol alone is ambiguous. Three reasons pastes lose: the paste asserts a stale reality the moment the file changes; on the mcp route Linear bills the body twice (the create/update calls echo it back — .claude/rules/pipekit-tooling.md § MCP Result Payloads Are Sticky) and every later full-content read re-drags it; and preflight can verify a reference but can only trust a paste.
Pasting IS right when the pasted content is itself the contract, not a description of code: an exact expected diff, a small type signature the implementation must match, an error string to assert on, or content that doesn't exist yet (nothing to reference). Keep pastes contract-sized, not context-sized.
The litmus: a reference the planner must chase is fine; a reference that's ambiguous at plan time is not. "The helper in utils" makes the planner guess — Blocking, same as any spec gap. `formatCurrency()` in `src/lib/format.ts` is a contract.
Acceptance Criteria discipline (behavioral, not presence-only): Every AC must verify observable behavior, not element presence. A spec that ships ACs like "component X exists" / "function Y is called" lets implementations pass tests without actually working — surfaced 2026-05-02 by RS-63/64 in rs-vault, where tests + 7-check gate + antagonistic review all passed but the running app was 60% broken (search bar non-functional, panel didn't animate, Notes save unwired, History tab placeholder, integration step skipped).
Bad → Better examples:
| ❌ Presence-only AC | ✅ Behavioral AC |
"Component <Search> exists" | "Given /page renders, when user types 'SW3' in the search input, then results filter to addresses containing 'SW3' within 300ms" |
"Save button calls onSave" | "Given user clicks Save, when fetch resolves, then DB row contains the value AND UI shows 'saved' state AND reloading the page shows the persisted value" |
| "Tabs render" | "Given drawer is open, when user clicks each of the 4 tabs, then each tab renders its real content (not 'coming soon' placeholder)" |
"Token --color-x exists in globals.css" | "Given page renders at 1440px viewport, when computed style of .foo is read, then background-color resolves to var(--color-x)" |
"Animation duration matches --duration-base" | "Given user clicks toggle, when panel transitions, then getAnimations() reports duration ≈ 180ms AND visual state changes from collapsed to expanded" |
For UI surfaces, at least one AC must be a visual or computed-style assertion — not just unit-test presence. If the spec is design-driven, reference the figma source explicitly and require pixel-diff or computed-style verification.
Cross-spec handoff awareness: If this spec references another issue with phrases like "X will replace…", "X consumes…", "X provides…", that's a load-bearing handoff promise. Either:
- Include the handoff itself as an AC in the predecessor's spec ("The integration in file Y is updated to use the new component, replacing the placeholder"), OR
- Mark it explicitly in the successor's spec as a required integration step ("This issue must update file Y to consume…").
Don't leave handoff promises buried in prose. Today's miss (RS-64) shipped because RS-63 said "RS-64 will replace the placeholder" but RS-64's AC didn't include the integration step. Both passed; the app was broken.
Phase 3.5 — Planning Readiness Check
Before presenting to the user, audit every section:
- Identify every point where the planner would need to guess — scan for implicit assumptions, undefined behaviors, and missing decision points
- For each guessing point, do one of:
- Convert it into a Decision (defined or
[TBD]) - Clarify the Scope to eliminate the ambiguity
- Move it to Risks & Open Questions if it can't be resolved now
- Convert it into a Decision (defined or
- Validate: the spec is only ready when no guessing is required for task decomposition.
[TBD]is acceptable; implicit assumptions are not.
Phase 3.6 — Derive tier label from Complexity (v2.7.0-rc1+)
The spec's **Complexity:** field is the source of truth for the issue's tier. Parse it and compute the matching tier:* Linear label so the downstream /work and /verify skills get a consistent gate signal — no manual labeling step required.
Mapping:
| Complexity in spec body | Tier label | Why this tier |
Trivial, Low (~2-4h) | tier:quick | /work uses inline planning, single-issue mode, light gates. |
Medium (~6-10h) | tier:standard | Default tier. Full /work pipeline, evidence layer, opt-in antagonistic review (auto-fires on sensitive-path diffs). |
High (~12-20h+), Very High, Critical | tier:heavy | Mandatory antagonistic review, /strategy-sync reminder at hand-off, full evidence pipeline. |
Extraction logic:
- Read the line matching
**Complexity:**from the spec body. - Match the first named complexity token present (case-insensitive):
Trivial | Low | Medium | High | Very High | Critical. Ignore everything else (hour ranges, parentheticals). - Map per the table above. If no token matches but an hour range is present (e.g.,
~8h), infer:≤4h → quick,5-11h → standard,≥12h → heavy. - If the Complexity line is missing or ambiguous, surface a one-line confirmation prompt before publishing:
Complexity not parseable — apply 'tier:standard' (Recommended) or 'tier:heavy' / 'tier:quick'?Defaultstandard.
Why this is a Phase 3.6 step, not a Phase 5 inline action: the user gets one final read-through (Phase 4) before publish. Surfacing the derived tier alongside the spec gives them a redirect window if the auto-derivation looks wrong. The tier choice ships in Phase 5's label payload as a normal part of the save.
Print the derived tier in the Phase 4 spec re-presentation as a one-liner near the Complexity field:
Derived tier: tier:heavy (from "Complexity: High (~16-22h)")Phase 3.7 — Migration Plan gate (schema-touching specs)
If this spec changes the database schema, it is not planning-ready until it carries a Migration Plan. Phase 2's Explore already surfaced the involved tables — use that to decide.
- Detect schema change. The spec touches schema if it adds/alters tables, columns, types, constraints, indexes, RLS policies, functions, or triggers. Signals: the
Database:line names a new/changed table; Requirements or AC imply persisted state that doesn't exist yet; Phase 2 found "new tables needed." - If no schema change: delete the
### Migration Plansection from the spec. Done — skip to Phase 4. - If schema changes: the
### Migration Plansection is mandatory. Fill all six fields (schema objects, migration tool + dir frommethod.config.md § Migration dir, forward intent, rollback intent, data backfill, authorization). The change MUST land as a migration file — never an ad-hocALTERor a hand-edited schema dump. The AI still writes all the DDL; only the artifact is constrained. Seesop/Database_SOP.md. - Validate concreteness. A Migration Plan with "TBD" on rollback or authorization that would force the planner to guess is a blocker — resolve it now or mark it in Risks & Open Questions for the Phase 4 walk-through. "Irreversible — data loss on revert" is a valid rollback answer; an empty one is not.
This is the spec-time half of gap #1's artifact rule. The Spec Review Agent (templates/spec_review_skill.md § Migration Rule) independently blocks a schema-touching spec that reaches review without a concrete plan, and /verify runs a migration-review subagent on the diff — but catching it here, before publish, saves a review round-trip.
Phase 3.75 — Split gate: data layer vs. the client that consumes it (v4.26.0+)
Only runs when Phase 3.7 detected a schema change. One question:
Does this spec also rewrite the application code that consumes what the migration changes?
If yes, spec two issues with an explicit dependency, not one issue with two halves.
Why — the two halves review differently, and this is a property of the work, not the team:
- Data-layer review converges. Policies, grants, and predicates are a finite, statically reviewable surface, falsifiable by mutation — re-add a policy leg, watch the specific test fail, restore. A clean pass carries real information and stays true.
- Client-behavior review does not converge. Stale in-memory snapshots, transaction boundaries between separate writes, zero-row writes the API reports as success, ordering, scope-resolved-at-load-versus-at-use. These surface one at a time, and each fix moves code the previous round already cleared. A clean pass carries much less.
Bundled, every review round must hold both — so the converged half is dragged back through review every time the other half moves.
The split is not 50/50 — getting the line wrong is the failure mode of adopting this carelessly. Client changes the migration forces travel with the migration: an RPC call a narrowed policy makes mandatory, a call site for a function the migration drops. Reverting those ships a broken UI. Only the hardening and UX work layered on top moves to the second issue.
Draft the split as: issue A (migration + the client changes it forces) → blocks → issue B (the client rewrite). Present both in Phase 4 and let the user collapse them back if they disagree.
Anchor — a consumer project, 2026-07. Two CRITICAL security fixes, a 1,816-line migration across 23 schema objects, and a rewrite of an admin tab inside an 8,000-line page, all on one branch: eight /verify rounds over two days. The migration reviewed clean from round 6 onward under three independent reviewers; essentially every defect across all eight rounds lived in the client half. The branch was cut at round 7 and shipped at round 8. Split at spec time, plausibly a three-round issue.
Phase 4 — Present and Iterate
- Show the draft spec to the user.
If the spec has any items in
## Risks & Open Questions— walk through them interactively before publishing:This spec has N open question(s). Walk through with recommendations? (default Y)If yes (default), for each open question, call the
AskUserQuestiontool — one question per call so each gets its own dialog. Structure:header: short chip (≤12 chars) summarizing the question topic — e.g., "Save view"question: the full question, ending with?options: 2–4 mutually-exclusive choices. First option is your recommendation with(Recommended)suffix on the label. Each option'sdescriptioncarries the reasoning + trade-off (1–2 sentences).- The "Other" option is auto-provided by the tool — do not include manually.
Standard option set per question (adapt as needed):
Label Description <recommended action> (Recommended)Why this is the best fit + the trade-off the user accepts by picking it. Keep as TBDLeave in Risks & Open Questions; defer to planning or implementation. Drop / out of scopeRemove from this spec entirely. Use when the question reveals the item shouldn't ship in this issue. Add a fourth option only when there's a genuinely distinct alternative to the recommendation (e.g., "Persist now" vs "Persist later") — don't pad to four.
After the user answers, edit the spec inline:
- Recommended / different answer: move the question from Risks & Open Questions to Decisions, with the chosen path as the resolution
- Keep as TBD: leave it in Risks & Open Questions; mark
[TBD] - Drop / out of scope: remove the related Requirements/AC entries; note in Notes that the item was dropped
- Re-present the updated spec (one final read-through) with the new Decisions section visible.
- Ask: "Want to refine anything else before I push this to Linear?"
- Iterate until the user approves.
Why interactive walk-through: open questions left in the spec body get visually skimmed and silently shipped as "implicit." Forcing each through AskUserQuestion turns every TBD into a deliberate decision (committed / deferred / dropped) — same lesson family as the behavioral-AC discipline above. No question gets lost in prose.
Phase 5 — Publish to Linear
- Update or create the Linear issue via the project's Linear route, in one call — existing:
pk issue update PROJ-123 --title "…" --description-file <spec.md> --state <Spec ready state> --project <lane> --priority N --add-label spec --add-label <tier-from-Phase-3.6> --remove-label <old tier>; new:pk issue create --title "…" --description-file <spec.md> --state <Spec ready state> --project <lane> --priority N --label spec --label <tier-from-Phase-3.6> --label "Area: <area>" --label "Repo: <repo>":- team:
pkreads it frommethod.config.md --title: concise spec title (prefix with domain if useful, e.g., "Budget: Multi-currency support")--description-file: the full light spec (markdown) — write it to a file, or pipe it with---state: the configuredSpec ready state— read it withpk config "Spec ready state" "Specced"(defaultSpecced). This is the statepk spec-cyclerequires on entry (Phase 6), so publishing to it keeps the interlock intact on any board. Projects whose Linear workflow has noSpeccedcolumn setSpec ready stateto a state they do have (e.g.Needs Spec); hardcodingSpeccedhere would try to set a nonexistent state and break the cycle.--priority: ask user (default 0/None if unsure)--project: suggest based on Phase 2 findings, confirm with user- labels: the merged list
[...existing_labels_minus_old_tier, 'spec', '<tier-from-Phase-3.6>']- Pull
existing_labelsfrom Phase 1'spk issue showread (new issues → empty list). - Strip any pre-existing
tier:quick | tier:standard | tier:heavylabel — the Phase 3.6 derivation replaces it (--remove-label <old tier>on the update). Other labels (Feature,Finance, domain tags, etc.) are preserved —--add-label/--remove-labelare deltas, so labels you don't name are untouched. - If
existing_labelscarries noArea:label, choose one now frommethod.config.md § Area Labels(for the issue's own work) and--add-labelit; likewise aRepo:label where§ Repo Labelsis populated. A spec published without an Area is uncut work noArea: * — backlogview can show (a consumer project, 2026-10). On a board with no§ Area Labelsconfig, skip this. - If
pk config "Linear transport" apiismcp: that route's update call takes labels as a wholesale set, not a delta — it replaces the issue's whole label list — so pass the full merged set there (the verb table names that route's delta tools too; a single wholesale set is just cleaner since Phase 5 reconciles the entire label list at once).
- Pull
- team:
- Store the issue ID for reference.
- Anything found while speccing that is not this spec's scope (a bug in adjacent code, a gap in a neighbouring surface) is its own issue, filed to
sop/Linear_SOP.md § Filing a follow-up issuein onepk issue createcall:Source: <this issue> (found while speccing)as the body's first line, anArea:chosen for the finding's own work, a Type label, priority from the floor table, state by that priority (never Triage), and arelatesrelation. Never a bareBugwith no placement — that is the drift/linear-hygienethen has to home (a consumer project, 2026-10).
Why the merge: Phase 5 reconciles the issue's whole label list at once — the Phase 1 read says what is on the issue, Phase 3.6 says which tier belongs, and the publish applies exactly that difference. Pulling the existing label list in Phase 1 and merging here means custom human-applied labels (e.g., Finance, Customer-impact) survive the publish. Stale tier:* labels are explicitly stripped so the Phase 3.6 derivation is authoritative — if the user re-runs /light-spec PROJ-XXX after raising the Complexity, the tier label updates accordingly.
Phase 6 — Spec Review Cycle (automated)
Enter the cycle automatically once Phase 5 publishes. Do not prompt the user before pass 1 — the cycle is the whole point of /light-spec. The cycle calls pk spec-cycle, which owns the agent trigger, the polling, and the state transition on Pass — so this skill never posts the @linear comment directly.
The user can opt out only by interrupting (Ctrl-C). Confirmation prompts appear on passes 2 and 3 inside the loop below — that is the designed bail-out point.
Cycle (max 3 passes):
pass = 1
loop:
bash: pk spec-cycle PROJ-XXX
read pk's last "VERDICT: <X>" line and exit code
case VERDICT:
Pass → done. pk has set the issue state to the configured
"Spec approved state" (default: Approved). Tell the user:
"✓ Spec approved on pass {pass}. ➜ next: pk branch PROJ-XXX"
EXIT.
Revise → invoke /light-spec-revise PROJ-XXX.
Pass-aware confirmation:
- pass == 1: auto-invoke. No prompt.
- pass >= 2: show the agent's blocker count and readiness
score, then prompt: "Continue to /02? [Y/n/o]"
Y → invoke /02
n → exit, leave issue in the spec-ready state
o → invoke /02 with override directive (the user wants
to override the agent verdict, not patch the spec)
After /02 returns, increment pass and loop.
Stalemate → pk's 3-comment guard fired before triggering. Tell the user:
"Agent already reviewed 3x — likely stalemate. Run
/light-spec-revise PROJ-XXX with the override path."
EXIT.
Timeout → no agent response in 5 min. Tell the user:
"Agent didn't respond. Inspect Linear UI; rerun
/light-spec PROJ-XXX when ready."
EXIT.
Malformed → tell the user the agent comment couldn't be parsed and
point them at Linear UI. EXIT.
if pass == 3 and verdict was Revise:
Tell the user: "3 passes complete. /02 has the override path if the
agent is stuck — rerun /light-spec-revise PROJ-XXX."
EXIT.
pass += 1Why pk spec-cycle and not an inline pk issue comment: centralizes the Linear-agent trigger format in one place (so a Linear product change is one fix, not many), keeps the polling out of Claude's context window, and matches the rest of the pk CLI surface.
State preconditions: pk spec-cycle refuses to run if the issue is not in the configured "Spec ready state" (default: Specced). Phase 5 of this skill sets that state, so the precondition holds on entry.
Phase 7 — Planning Pointer
Tell the user how to proceed:
Next steps:
- To turn this spec into a plan and execute it:
pk branch PROJ-XXX, then/work PROJ-XXXfrom inside the worktree- To refine further:
/light-spec PROJ-XXXto iterate
Light Spec Template
Read the canonical template from templates/light_spec_template.md in the method repo (or pipekit/templates/light_spec_template.md in consuming projects). Use that template structure for all specs.
How This Connects to Planning
The light spec is designed so /work's planning step can consume it directly. /work materializes a task DAG to .pk-work/PROJ-XXX-PLAN.md (one atomic task per entry, each with files / change / verify / done). The spec maps onto that plan like so:
| Light Spec Section | Native Plan Use |
| Problem + Goal | Plan goal / approach |
| Proposed Solution | Plan approach description |
| Scope | Task boundaries (which files each task may touch) |
| Decisions | Task change lines (defined) or a research task (TBD) |
| Requirements | Task set + each task's done condition |
| Acceptance Criteria | Per-task verify + done; the tests /work authors |
| Technical Context + Authority | Task files sets + which layer is authoritative |
| Risks & Open Questions | Research task up front, before dependent tasks |
| Complexity | Tier label (Phase 3.6) → which /work gates run |
/work reads the Linear issue, extracts the spec, and uses it as the foundation for task decomposition.
Complexity Guidelines
Same as /brainstorm, but with planning implications. Phase 3.6 maps these to tier:* Linear labels automatically.
| Complexity | Planning implication | Auto-derived tier (v2.7.0-rc1+) |
| Trivial | Single-step change, no decomposition. Often a typo/copy/rename. | tier:quick |
| Low (~2-4h) | /work plans inline from the spec — a complete AC section is the plan. | tier:quick |
| Medium (~6-10h) | Benefits from a single planning pass. The light spec provides enough for /work to generate a task DAG. | tier:standard |
| High (~12-20h+) | Likely a larger task DAG across an initiative. The light spec seeds /work's --deep parallel-grounding decomposition. | tier:heavy |
| Very High / Critical | Cross-phase, cross-team, or migrates load-bearing infrastructure. Always heavy. | tier:heavy |
The auto-derived tier feeds into:
/workSteps 3/4/6/7 (plan strictness, security review, hand-off behavior — per v2.6.0 tier reinstatement)/verifyStep 0.5 dispatch (evidence layer + reality-check for tier ≥ standard; verify-complete sentinel on PASS for every tier, quick a minimal virtual one)/verifyStep 5 (mandatory antagonistic review on heavy; auto-fires on sensitive-path diffs for standard)pk shipverify-complete.md gate (hard-fail on any tier without a verify-complete.md whose sha matches HEAD)
If you disagree with the auto-derivation, change the Complexity field in the spec body and re-run /light-spec PROJ-XXX — the tier label will refresh on the next publish.
Red Flags
Thoughts that mean "slow down and widen scope." Paired with .claude/rules/pipekit-discipline.md.
| Flag | What it actually means |
| "The AC is short because the feature is simple" | Short AC = high risk of planning-time ambiguity. Simple features are where "obvious" behavior diverges between spec author and planner. Be explicit. |
| "The user said they want X, so I'll just write that" | The spec has to be decomposable without guessing. If you'd have to guess a decision, mark it [TBD] and ask — don't paper over. |
| "The POC shows the answer already" | POC is reference, not spec. Translate observable behaviors into testable requirements; don't assume the planner reads POC code. |
| "Authority is obvious from context" | It isn't. Specs without an explicit authoritative layer (DB, utils, API) are the #1 cause of spec revision. Name it. |
| "I'll skip the review agent, the spec is clear" | Clear-seeming specs fail planning review most often — the clarity is in your head, not on the page. Run the review. |
"AC says <Component> exists and that's enough" | Presence ≠ behavior. The thing under test is what the user sees and does. Replace with behavioral AC: input → expected output, observable in the running app. |
"AC says onSave callback fires" | Mock-tests are not user-tests. Add an end-to-end AC: data persists, UI reflects, page reload shows it. |
"Integration into <other-file> is implied" | Implicit integration steps were the RS-64 miss. If the spec touches one component but requires updating another to use it, name the second update as an explicit AC. |
| "Visual matches figma" (without measurable check) | Unmeasurable. Replace with: pixel-diff threshold (e.g. < 5% at 1440px), or computed-style assertions on key tokens, or both. |
| "I'll paste the code so the planner has context" | Pasted code rots the day the file changes, and Linear bills it twice (echoed body + sticky payload). Reference path + symbol; paste only contracts — exact expected diff, small type signature, content that doesn't exist yet. |
| "The migration and the UI rewrite are one feature — splitting them is artificial" | Shipping them together is one thing; reviewing them together is another. The data layer converges under review and the client doesn't, so bundled, the converged half is re-reviewed every round the other half moves. Split per Phase 3.75, keeping the client changes the migration forces on the migration's side. |
Common Drifts to Avoid
When you encounter these situations, take the safer path:
- Skipping codebase exploration → When uncertain whether exploration is needed, explore. Assumptions about what exists are wrong more often than right.
- Leaving authority implicit → Define it explicitly. Ambiguous authority is the #1 cause of spec revision.
- Vague acceptance criteria → Apply the litmus test: can the planner verify each criterion without guessing what "works correctly" or "handles properly" means? Every criterion needs a concrete, observable outcome.
- Implicit decisions → Put it in the Decisions section (defined or
[TBD]). Context is not a contract — downstream agents can't read your mind. - Assuming API behavior → Check the installed version. Training data may not reflect the project's actual dependencies.
- Pasting code blocks as context → Reference
path+ symbol instead. A paste is a snapshot that silently diverges from the file; a reference stays verifiable by/spec-preflight.
Next-step output
After the spec is drafted and posted to Linear, emit an inline ➜ Next: line in your terminal output pointing to pk branch {issue-id} if the spec is approved (the user will then /work {issue-id} from inside the worktree), or the next spec to draft if this one is still pending human review. Do not write a NEXT.md file — v2 retired the mirror; pk next reads "what's next?" live from Linear.
Related Skills
/brainstorm— lighter: feasibility-only, no structured spec/sync-linear— reconciles strategy-doc drift against the Linear initiative hierarchy
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

