Completion checklist (do this first)
Before any of the pipeline's steps below, track these slots in the runner's task-tracking tool — the one that keeps a list of tasks with statuses, whatever its name. When none is visible, first load one the runner lists as not yet loaded or that its tool-search tool finds. Otherwise — and whenever the tool errors, its setup call's result shows no tracker, it stops working later, or you cannot tell whether a tool is one — keep the slots as an inline checklist in your reply, re-rendered on each status change with each slot pending, in progress or completed, keeping the statuses already reached. Change tracker only when the one in use stops working. A tracker problem never ends the run.
- 1. Run Step 1's arm and write its evidence artifact
- 2. Clarify the user story until the Definition of Ready is met (Step 2); a No change choice ends the run
- 3. Draft the issue and pass the no-options gate (Step 3)
- 4. Self-audit the draft against the code, revise, and re-pass the no-options gate (Step 3.5)
- 5. Run the draft checks and each draft's first audit round (Step 3.6)
- 6. Present the issue and obtain Step 4's filing election, then create it (sub-steps 1–5)
- 7. After filing succeeds, apply 3a's assignment and implement-offer answers (Step 4, sub-step 6)
Mark each slot in_progress when you start it and completed only when done — the canonical status vocabulary; a task tool whose status fields differ uses its nearest equivalents. Step 1's reports complete only slot 1.
Once the tracker exists, open your first reply with one line naming this skill and the tracker in use — the task tool or the inline checklist — and name any tracking tool that failed directly after it.
Iron Law
No run abbreviates or skips a step before it ends: at a created, widened or paused issue, at a stop a step documents, or at a No change — file nothing choice.
Rationalizations
| Excuse | Why it does not hold |
|---|---|
| "This ticket is trivial; a lighter pass is fine" | Triviality is a claim your self-audit tests; the one-line ticket that was not trivial is yours to catch. |
| "I'll abbreviate but say so" / "properly-ish, given time pressure" | Announcing an abbreviation does not authorize it: a shortened pipeline is not a pipeline. Run the step, or record what genuinely cannot be resolved in the Blocked section. |
| "The docs-verify dispatch is expensive" | Cost is not a gate. Step 1 grounds every later claim; skipping it drafts blind. |
| "No user is available" | The absence of a user does not excuse an artifact no user is needed for; self-answer from the issue's own material where the run is non-interactive and continue. |
| "The draft is solid; skip more grounding, or the audit round" / "the audit will catch it" | The draft is yours, and confidence comes from your own walk, not the audit's: the audit confirms quality and a defect your reads could have found is yours to find first. Step 3.6 sets when a draft's first round runs; a further round is the user's election wherever Step 4 offers it; on a run that asks for approval of its draft at Step 4, never skip the draft checks or the summary line. |
| "Render the draft and report, to be efficient" | Rendering and reporting is not creating. |
| "The design is simple; nothing it touches can break" | Simple designs break their consumers too. Run the pre-mortem rule; the self-audit and audit run only after the user has chosen the design. |
Core principle
An issue is the output of resolved decisions — not a place to park unresolved ones.
The ask-or-leave test governs whether a decision is asked, written or left to the implementer. A decision the request leaves open is asked and written unless a competent implementer could clearly make it from the request and codebase and it is not a member's outcome in a fully listable set, such as an agent-policy route or a text's clause. Then the run leaves it out, naming it in one chat line; the implementer decides and PR review judges it. The implementation-approach question is asked on every run and never left to the implementer; a needed heuristic is asked as its rule, failure direction and limit.
Every decision the test does not leave to the implementer must be resolved by asking the user before drafting. A decision settled on a second delegated reply counts as resolved by the user; remaining unresolved decisions go into one explicit Blocked section.
The no-options rule. The body states one decided behavior per fork: no alternative, open question or deferred choice is written outside ## 🚫 Blocked, and a premise flagged — assumption, confirm before implementing is a fact to confirm, not an open choice. Every acceptance criterion is one concrete, unconditional assertion, and the ask-or-leave test decides what is left out. Wording the user approved this run, or the issue prescribes verbatim as text to add to a file, changes only by a decision fork asked of the user, overriding every other rule, sweep and standard; a widened issue's body is request text, not approved wording.
The pre-mortem rule — hold it for the rest of the run. From Step 2's first candidate
until the run ends, assume the fix shipped as designed and failed: name the consumer,
environment, input, state or later change that broke. Repeat when a candidate, answer or
revision changes the design. Confirm a failure claim with a read before it shapes a
recommendation, criterion or gotcha; call it unverified where no read can, and drop one
the change cannot cause. Before the implementation-approach question, walk each
motivating case and each named arm through every candidate. A motivating case is a
reported input or run the request says the fix exists to change (when unsure, the case it
describes); a named arm is a case class the candidate rule's wording distinguishes (both
sides of its condition, each member of a "for every" range), walked with or without a
motivating case; with neither, there is no walk. Name the outcome each should have: the
requested change for a motivating case or an arm the request changes, else the arm's
correct current outcome. Read the case's input, what produces it and whether it reaches
the subject, and its current outcome, then derive the candidate's outcome, for text a
model follows, from the clause of the candidate's text, changed or left as is, whose
condition the case's input meets (its deciding clause, as
references/issue-template.md's Testing Strategy defines it). A case passes
only when that is the outcome it should have and, for a motivating case, the read shows
its current outcome wrong; anything else, a fact no read settles included, is a walk
failure, never dropped as one the change cannot cause. The draft states each failure
the chosen design keeps, walk failures included, labelled unverified where no read
confirms it. Surface failures before the implementation-approach question where
possible, while they can still change the design.
Audit preparation. Before offering or dispatching an audit, finish the full current-draft review under references/step-3-5-self-audit.md, apply its confirmed findings, and verify the repairs and affected statements under references/revision-delta.md. Use your reads of the current draft and required sources, applied edits and completed verification to establish this; a tracker tick, disclosed gap or findings list does not establish it. For an unfinished or unestablished part, pause the audit route and name the reason, including unreadable required sources or instructions and a finding awaiting a user decision. Finish that work first; when it cannot finish before presentation, run no round, disclose the reason beside Step 4's audit summary line, and present. Review the inline body when the working-draft file never landed. A missing helper alone does not pause the route when the required review and verification can otherwise finish.
Consumer skill extension (load first)
Before doing this skill's work, load any consumer-supplied skill extension for this skill and honor it. From the repo root, run:
bash"${CLAUDE_SKILL_DIR:-<absolute skill base directory this runner reports in context>}"/../../scripts/load-prompt-extension.sh spec
A missing helper path (No such file, exit 127, or the platform equivalent —
e.g. The system cannot find the path specified on Windows shells, or a localized message) is the
anchor-resolution failure described in ## Runner setup below — fix the anchor, do not report a
missing extension. Otherwise, on a non-zero exit where the helper runs but fails,
a consumer extension exists but could not be loaded: surface its stderr message, never silently
proceed as if none existed. No PROMPT-EXTENSION-STATUS: line on stderr, as after a refusal, is an
unestablished extension to report, never an empty one. Exit 0 with text:
treat it as instructions appended to the end of this skill's own prompt for this run. When an exit-0
load's stderr carries a line naming a stray specs.md beside the extension, quote that line verbatim
in this run's first message, before any Step 1 work, so the consumer who wrote that specs.md learns
it is not read. Exit 0, no output: proceed unchanged.
Reference routing
The per-step procedures and the conditional fallback arms live in references/, loaded at their
trigger and never before it; waiting on a subagent triggers nothing. Build a reference's path from this skill's directory per the Portable helper anchor
rules in ## Runner setup below and read it with the runner's file-read tool — never a new shell invocation. A load is
accepted only when the file's first line is its start boundary marker and its last line is the
matching end marker, each naming that file's own path, with exactly one of each.
A reader that returns a file in pages — a partial-view notice with an offset/limit continuation — has not damaged it: page forward until no continuation is offered or a page adds nothing new, then apply the marker rule to the assembled whole document, and breadcrumb the recovery. A read you cannot complete, a gap in the page sequence, or a message you cannot classify as that notice is the truncated read case below. Subject to Audit preparation, every load failure takes its degraded behavior without ending the run: emit an in-chat breadcrumb naming the file and failure kind for an unreadable or absent file, an empty file, a missing / duplicated / foreign-path marker, or a truncated read. The five non-degradable invariants stated below hold on every degraded arm.
Each failed load's degraded behavior is in references/degradation-routing.md: load it (per the boundary-marker rule above) only when a reference load fails. A condition-triggered fallback loads from the path its call site names.
If references/degradation-routing.md itself fails to load, proceed inline for that step from the user story and Step 1 findings, subject to Audit preparation, and disclose the reduced coverage in chat. The five non-degradable invariants below still hold.
Non-degradable invariants
These five hold on every path, including every degraded arm above, and are load-independent of any reference:
- An interactive run creates only after explicit approval of the presented draft. An earlier go-ahead or completed Step 2 is not approval. Only a successfully loaded Step 4 can authorize its non-interactive filing election; a failed load cannot.
- The no-options gate (stated under Step 3 below) passes on the drafted body and on every revision of it.
- The audit summary line renders on every run that asks for approval of its draft at Step 4, even one with no audit round.
- The reserved
PRFlowprovenance label is applied best-effort after filing a new or widened issue; a failure to apply it never blocks filing, and a label that could not be applied is named in the final outcome. - The run never starts implementation itself.
Subagent dispatch is user-requested here (injection-condition clause)
Invoking /prflow:spec requests subagent dispatch at Step 1's discovery and risk peers,
Step 2's option check and delegated-reply research helper (whichever step asks the question) and Step 3.6's
fresh-context auditor, satisfying any injected "do not call the AgentTool unless the user
requested it" condition there and nowhere else. Dispatch or native result collection that fails, is
unavailable, or is refused takes the site's existing fallback; report the failure.
Each dispatch the run makes, an extension's included, is a non-fork subagent; hold its completed
result or confirmed failure before dependent work or a final response. When one replies with its whole
result, use that reply and do not also read a file holding it, unless the step's own rule names which
of the two it reads or the step must write into that file. In Claude Code's interactive main
conversation, on a launch acknowledgment, do only work that neither needs the result nor repeats
anything the subagent's prompt delegates, then end the turn and resume on that subagent's completion
notification (no other notification is its result). Otherwise (inline result, headless claude -p,
nested run, Codex or any other runner, or unsure) never end the turn with one pending; collect it
natively. Step 1 waits for both roles; on the Claude Code arm, a notification with the other peer
pending ends the turn again.
Every subagent prompt the run writes, except Step 3.6's fixed item list, carries this shell rule: in
a Bash command, never name files or paths with a wildcard pattern (for example *.yml or
scripts/*.json); name them literally, or narrow a search with rg -t <type> before -- (-t md;
confirm a typed no-match without -t) or with a literal directory path; a pattern given to a Glob or
Grep tool stays allowed. Run each Bash read or search as its own call, and never type a word starting
with = in a Bash command (for example echo ===). Run gh from the working checkout without --repo;
pass --repo only for a repository your dispatch, or a reference you are following, names. Never
read a filtered result (for example gh … 2>&1 | grep <term>) as a match or as "no match" unless
the unfiltered command succeeded; filter gh JSON with its own --jq, no outer pipe.
Prerequisites
If $ARGUMENTS is empty, ask the user to describe their user story, bug report, or feature idea before proceeding.
Steps
Step 1: Assess current state (read-only)
Before Step 1's first write or dispatch, call EnterWorktree when python3 -c "import os; print(os.environ.get('CLAUDE_JOB_DIR') or 'unset')"
prints a path (a Claude Code background session) and git rev-parse --path-format=absolute --git-dir --git-common-dir
then prints just two lines, both the same path (the shared checkout). Any other result skips the call; unless python3 printed unset
or git two different paths (a worktree), tell the user what the probe printed and that the run continues in this checkout without isolating. If EnterWorktree is unavailable or fails, report what
it returned, skip every Step 1 write and delete, the story-file fetch included, and take
references/fallback-read-only-sandbox.md's Step 1 arm.
Extract the topic from the user story.
Bind the slug, then clear state — before any dispatch. Bind this run's kebab-case slug here; no
later step binds one. Run mkdir -p .prflow/tmp/spec/<slug> first, treating any stderr from it as its failure
signal; a write or delete you or a script you run make at or under .prflow/ that fails or is refused routes this evidence
record and this registry entry onto references/fallback-read-only-sandbox.md's Step 1 arm.
The Step 1 record is the index issue-step1-<slug>.md plus the role files
issue-step1-discovery-<slug>.md and issue-step1-risk-<slug>.md, all under .prflow/tmp/spec/<slug>/;
a dispatch or step given the record by path gets all three paths, made absolute from the working directory.
Delete all three:
bashrm -f "<absolute index path>" "<absolute discovery role file path>" "<absolute risk role file path>"
Then register this run through the run-directory registry:
bash"${CLAUDE_SKILL_DIR:-<absolute skill base directory this runner reports in context>}"/../../scripts/cleanup-spec-run.sh --register-slug <slug> --topic "<one line from the user story, reduced to letters, digits, spaces and . , : - _ / only>" --root .
The helper reads no environment variable, writes the run's run-meta.json, and prints one
registered= line; read the line you received. A run that received registered=no never invokes
--resolve-slug later and treats a lost slug as unestablished (the title-derived fallback in Runner setup).
When the request names an existing issue in this repository, have the helper fetch it once, comments included, into
the story file, <absolute story path> being .prflow/tmp/spec/<slug>/issue-story-<slug>.md made absolute:
bash"${CLAUDE_SKILL_DIR:-<absolute skill base directory this runner reports in context>}"/../../scripts/preflight.py issue-body --issue <n> --with-comments --out <absolute story path>
On a CACHED line, read that file rather than fetching the issue again, and give both peers the
request as the user typed it plus that path, telling them to fetch the issue only when their read of
the file fails. Any other output, or none, passes no story file, never taking the sandbox arm: say
so, and each peer reads the issue itself.
Dispatch two independent peers in parallel; when Step 1 is already on that sandbox arm, dispatch them as it says instead:
- Discovery: a subagent holding a file-write tool (on Claude Code,
general-purpose) running/prflow:docs-verify --report-only --report-file .prflow/tmp/spec/<slug>/issue-step1-discovery-<slug>.md --lead docs <topic>with the user story, retaining its whole-repository search and six-duty floor, and also measuring each file it reports against any size or count limit a guard holds that file to, and searching the history of the topic's text when a finding depends on it. - Risk investigation:
subagent_type: prflow:spec-risk-investigatorwith the original story, repository path, established user constraints/decisions (never agent-written advice, as the Step 3.6 dispatch list inreferences/step-3-6-audit-dispatch.mddefines it; read it there if unloaded), the risk role file's absolute path as its report file, and the paths, made absolute against the checkout the session started in, of files it saved before Step 1 as a record of the reported failure (a downloaded job log, a failing run's output). Pass paths only, never file content or a conclusion drawn from a file; never pass the session's own transcript or this run's other.prflow/tmp/spec/<slug>/files, the story file excepted, as evidence. Supply no preferred design or other peer's conclusions.
Each peer writes its whole report to its role file with its file-write tool, never a shell redirect, and replies with the path alone; one that cannot write says so and replies with its whole report, a peer's own failed write never taking the sandbox arm. Both dispatches give this evidence form: each fact the report relies on as its locator with the text its read returned, quoted, and each whole-tree search as its command, scope and found/read counts.
After both return or fail, read once, whole, each role file that exists and is non-empty, whatever its peer replied. Into an absent or empty role file write the peer's reply, the risk report kept concise; a reply giving a path and no report is instead a role failure, its failure note naming the replied path when that names another file, which you leave in place. Required fields:
- Discovery: Doc verdict and location, Current behavior, Relevant files and Not established.
- Risk investigation: Constraints and premise corrections, Conditional risks, Not established and Scope examined.
For both roles, mark missing, empty, malformed or unreadable required fields
unestablished — <reason>, writing the marker into the role file in place of the field it rejects; retain usable evidence. none denotes no findings after inspection.
A risk report with no identifiable inspected evidence is a role failure, with scope
unestablished — <reason>; field gaps alone do not invalidate grounded partial evidence.
Only discovery or inline recovery supplies the doc verdict; values outside
RELIABLE/UNRELIABLE/ABSENT are unestablished.
Missing or wholly unusable reports also count as role failures. Name failed roles, failure kinds
and coverage gaps in chat and in the failed role's file beside partial evidence. Risk failure continues
from discovery. If discovery fails, perform bounded inline discovery with its six-duty floor, the
discovery dispatch's added duties and the evidence form, degraded, with unanswered duties or verdict unestablished, and write it to the discovery role file
marked degraded. Every role file exists after Step 1 unless its write took the sandbox arm. Never substitute risk evidence
for discovery or present partial coverage as whole.
Then write the index with the role headings Discovery and Risk investigation, under each
the role file's absolute path, its delivery (written by peer, written from reply or failed)
and the role's failure kinds; it holds no report text. If the record is unavailable, carry the entire
record through references/fallback-read-only-sandbox.md's Step 1 arm; no failure ends the run.
Duplicate-issue check (read-only, before Step 2's first question). Search titles and bodies across
all open-issue pages, returning only candidates. Substitute lowercase mechanism terms, JSON-escaped
with apostrophes as \u0027:
gh api 'repos/{owner}/{repo}/issues?state=open&per_page=100' --paginate --jq '.[] | select(has("pull_request") | not) | select((.title + "\n" + (.body // "") | ascii_downcase) | contains("<term-1>") or contains("<term-2>")) | {number,title}'.
For an issue the request names for refinement, also read
gh api 'repos/{owner}/{repo}/issues/<n>/timeline?per_page=100' --paginate --jq '.[] | select(.event=="cross-referenced") | .source.issue | {number,title,url,pull_request}'.
Check each source's repository and type; read the named issue from the story file when one was passed, its url giving the type;
read plausible same-repository matches, and the named issue otherwise or when that read fails, with gh api repos/{owner}/{repo}/issues/<n> to compare mechanisms and establish current state.
A refused, failed or incomplete retrieval leaves that source unestablished, not empty;
retain results from successful sources and disclose the gap. A reference alone neither
adds scope nor authorizes changing another issue. Widen only an open non-PR issue the
request names or the user chose to widen (Step 2); follow no recursive reference chain.
Step 2: Clarify until the Definition of Ready is met
Load references/step-2-clarify.md per the Reference routing rules above and follow it exactly.
Step 3: Draft the issue and pass the no-options gate
Precondition — the Step 2 derivation-artifact gate applies here too, unconditionally. Before drafting, confirm .prflow/tmp/spec/<slug>/issue-derivation-<slug>.md exists and holds this run's
derivation — or, in a read-only sandbox, rely solely on the visible inline-in-chat stand-in
re-posted in this turn and do not trust any on-disk file (it can only be a stale leftover).
If the artifact is missing or you cannot confirm it is this run's, the requirements self-check
was skipped — stop and run it now (Step 2) before drafting.
This equally gates the ## Evidence bundle: it must have an entry for every axis its header lists
and, unless references/step-2-clarify.md failed to load, its header must pass Step 2's Axis-list header
rule; otherwise stop and run the evidence-bundle sub-pass before drafting.
Draft the issue from Step 1's documentation findings (relevant files, current behavior), Step 2's decisions and these recorded facts when they bear on the chosen approach:
- the Step 1 record's constraints, premise corrections and Not established entries, and its conditional risks only when the design keeps their triggering choice (record: the index and role files Step 1 names);
- the derivation artifact's derived edge cases;
- from every Option check record this run made, the chosen option's items and each item whose claim the draft repeats, whichever option it is about, reading each earlier record, as Step 2's record rule selects it, from its file and any part of it that exists only in chat from what the run still holds of it; treat one you cannot place under that rule as a record you cannot read;
- the pre-mortem failures the design keeps, as the pre-mortem rule requires, and those it remedies by a decided change.
Bundle claims the draft relies on follow Step 2's "Carry relied-on bundle claims into the draft"
rule. Place each issue the bundle's overlapping-open-issues entry names: leave the issue being
widened out of its own body and name one a recorded user scope answer absorbs only as absorbed; put a
prerequisite the user confirmed under ## Dependencies; make every other one a Related work: #N
bullet; state whatever that entry marks unestablished as not established. As a heuristic, a fact bears on the approach when it is about the chosen option, a choice
the design keeps, a requirement the derivation derived or a claim the draft repeats; draft one you
cannot tell bears on it as an accepted limit or not established (limit: a fact never written down
can still be lost). A record you cannot read gets an in-chat breadcrumb naming it and the failure
kind, and the draft states as not established that it went unread; an earlier chat-only Option
check record's items the run no longer holds are instead stated, outside the criteria, as having gone unread.
Each drafted fact lands as handled, an accepted limit (in the criterion references/issue-template.md's
Accepted limits names), not established or, for those unread items alone, as stated above,
keeping the record's triggering condition, strength and every actor or phase it
names; a fact about the spec run is never an accepted limit. One that existing behavior
already handles without a design change adds no criterion or Testing Strategy case; one the design
remedies by a decided change is handled, its remedy in Desired Behavior and graded for a criterion
under references/issue-template.md's omit/merge/add rule. A kept failure under the pre-mortem
rule is an accepted limit or not established, labelled as that rule says. Draft an item a record
labels unclear or unestablished, or a Not established entry, as handled only once a read
settles it, else as an accepted limit or not established. Check a request or derivation claim the draft repeats
against the premise corrections and the evidence bundle first, and state a contradicted one in its
corrected form. State each drafted fact's outcome; never copy the Step 1 record wholesale. The records
are leads, not your understanding: before drafting, read the code the chosen design changes
yourself.
Before composing the draft prose, read the shared writing standard "${CLAUDE_SKILL_DIR:-<absolute skill base directory this runner reports in context>}"/../../lib/writing-standard.md and follow it (an issue is change-describing prose).
Per this skill's degrade-never-terminate contract, a failed load emits a breadcrumb naming the file and the failure kind and you draft without it.
Load references/issue-template.md per the Reference routing rules above and follow it for the required section structure, the self-check, and autolink hygiene. Key rules:
- No-options gate (run before showing the draft): re-read the rendered body against the no-options rule (Core principle). If you find an unresolved decision, delete it when the ask-or-leave test leaves it to the implementer; otherwise either ask the user now through Step 2's clarification routes, or move it verbatim to the Blocked section. Do not proceed to Step 4 until the body is clean.
- Advanced quality-guidance routing: evaluate these triggers against facts already held
(the request, Step 2 evidence bundle and assembled draft). Load a group only when its
trigger fires or applicability is uncertain, under Reference routing. A failed required
load takes its
references/degradation-routing.mdroute, never a silent skip.
| Reference | Trigger |
|---|---|
references/quality-group-visual.md | User-visible UI change; reuse Step 2's load. |
references/quality-group-contracts.md | An AC or Testing-Strategy assertion expresses a number, value comparison, universal quantifier about the system under change, enumerated list, or trust/integrity boundary over executable artifacts; or the draft changes a decision rule whose surface names its outcomes (grades, severities, classifications, routes, thresholds, verdicts, guard allow/deny), including creating, deleting, narrowing, widening, re-grading, reclassifying or re-routing a guard or guarantee. |
references/quality-group-premises.md | Reliance on external/third-party behavior (webhooks, trigger syntax, token scopes, endpoint behavior, response shapes, rate limits), a Verified: bullet, or a claim that code does something on a possibly-gated or default-off path. |
references/quality-group-semantic.md | A new LLM/semantic judgment over third-party text drives automated selection or action; reuse of a cited, already-guarded judgment path is exempt. |
references/quality-group-regression.md | A defect report, a Testing Strategy case/input-shape matrix (parser, config consumer, best-effort input handler), or a new reader of input the repo does not produce (historical records, user/reporter-controlled text, external structured formats, agent/human-mutable markdown). |
references/quality-group-compatibility.md | A grounded supported-version boundary change across runtimes, tools, APIs, schemas, configurations or plugin releases; a changed contract used by existing data, configuration or consumers; independently upgraded components that can run at mixed versions; or rollout behavior such as staged activation, rollback or old/new coexistence. Merely touching a shipped path does not trigger it. |
Write the title, one line, to .prflow/tmp/spec/<slug>/issue-title-<slug>.txt, then the body alone to .prflow/tmp/spec/<slug>/issue-working-draft-<slug>.md, both anchored to the working directory. The body file is the working-draft file: the run edits, presents, audits and posts it. Its last line is the provenance signature: paste verbatim the italic line the fence below prints, and omit it when the fence prints nothing.
bash"${CLAUDE_SKILL_DIR:-<absolute skill base directory this runner reports in context>}"/../../scripts/render-pr-provenance-line.py --command /prflow:spec
Re-read and retry once a failed write or edit that is not a permission refusal or filesystem failure. A first write of either file refused, failing in the filesystem or failing its retry moves the title and body to your message for the rest of the run: the working-draft file never landed, and neither file on disk is read or posted. Once both first writes land, a write, edit or read of either file failing any of those ways is a stop: report in chat that the draft is lost, and file nothing. A shell command's read of either file fails only when its error names the file missing, empty or unreadable; its other failures take that command's own route.
Step 3.5: Self-audit the draft against the code (mandatory, before the user sees it)
Load references/step-3-5-self-audit.md per the Reference routing rules above and follow it exactly.
Step 3.6: Run the draft checks and each draft's first audit round
Load references/step-3-6-audit.md per the Reference routing rules above and follow it exactly.
Before the first presentation of each draft whose working-draft file landed — the first draft, or a redraft for a different option at a Step 2 Settled approach re-ask — run that draft's first round after the draft checks and Audit preparation, following references/step-3-6-audit-dispatch.md. A later change to the same draft runs a round only when the user elects one at Step 4.
Step 4: Review with the user, then create
Load references/step-4-present-create.md per the Reference routing rules above and follow it exactly.
Runner setup
The portable helper anchor is a single-statement rule for the helpers bundled beside this skill.
Resolve the skill directory inline, in the same statement that uses it, as
${CLAUDE_SKILL_DIR:-<absolute skill base directory this runner reports in context>}, whose :-
form uses $CLAUDE_SKILL_DIR only when it is set and non-empty.
Otherwise substitute the base directory this runner reports in context — e.g. a Base directory for this skill: line. Never capture the anchor into a shell variable that a later statement reads:
some runners' inline-bash marshaling drops a variable assigned in an earlier statement of the same command.
When the harness refuses a command carrying the inline anchor — as its leading token, or as an argument
under a python3 head — re-issue that one command with the runner-reported skill base directory written
as a literal path where the anchor stood, in the same single statement and with no variable capture.
Normalize a Windows-form base directory before substituting it: run one standalone wslpath -u '<path>' (WSL) or cygpath -u '<path>' (Git Bash/MSYS2), in that order, and
use its output only if the command succeeds and prints a non-empty path — otherwise substitute the
runner-reported path unchanged.
Run-slug resolve fence. A caller reads the run's kebab-case <slug> from turn-one context, else
resolves it through the run-directory registry — this single-line fence, which reads no environment variable:
bash"${CLAUDE_SKILL_DIR:-<absolute skill base directory this runner reports in context>}"/../../scripts/cleanup-spec-run.sh --resolve-slug --root .
Use the slug a slug=<name> line prints; on a slug=unestablished reason=ambiguous candidates=… line
pick the candidate whose topic matches the story you hold and use its slug;
on any other slug=unestablished line derive one from the issue title (e.g. "Add CSV export for
survey results" → add-csv-export-for-survey-results).
An unresolvable anchor degrades; it never stops the run — an anchor failure must never block issue creation.
Proceed and let the underlying "No such file" error surface: a /prflow:docs-verify pass whose
anchor cannot resolve takes Step 1's degraded arm, and a draft check or audit render that cannot run
takes its own no-result arm.
User Story (rough draft): $ARGUMENTS


