Best for
- Use when the user wants an existing GitHub issue turned into a finished, reviewed pull request — "implement issue 123", "pick up ticket 45", "build the feature described in issue 7", "go fix the bug in issue 99", "start…
The01Geek/prflow/skills/implement/SKILL.md
Use when the user wants an existing GitHub issue turned into a finished, reviewed pull request — "implement issue 123", "pick up ticket 45", "build the feature described in issue 7", "go fix the bug in issue 99", "start working on that issue". Triggers on any request to do the work an issue already describes, whether or not a slash command is used.
Decision brief
You are the main implementation agent. Execute the full 4-phase lifecycle for a GitHub issue, holding continuous context from discovery through documentation.
Compatibility matrix
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/The01Geek/prflow --skill "skills/implement"Inspect the Agent Skill "implement" from https://github.com/The01Geek/prflow/blob/cccf0e5f7038c5e5460383ce3c7bdd962b3e21a7/skills/implement/SKILL.md at commit cccf0e5f7038c5e5460383ce3c7bdd962b3e21a7. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
Orientation only (the phase file is authoritative): fetch the issue and parse its acceptance criteria; create-or-resume the single workpad comment and mirror the ACs into it; create or detect the feature branch and fill in the workpad Branch line; push the branch; then run the i…
Orientation only (the phase file is authoritative): explore the codebase; reproduce first when the recorded classification is bug-report; assess complexity and write the plan (using the architect for complex work); implement against the plan while running the mandatory code swee…
Orientation only (the phase file is authoritative): open the draft PR; run the self-review and the review-and-fix loop; then enforce the acceptance-criteria gate before advancing.
Orientation only (the phase file is authoritative): file follow-up issues for any deferred work; update the documentation; generate the PR description; then finalize the PR (publish or leave a draft per config) and the workpad.
Every phase is mandatory regardless of issue complexity or size. A one-line fix still needs review (Phase 3) and a proper PR description (Phase 4). The PR stays a draft until Phase 4.3 — that ordering keeps docs and description in place before downstream workflows see "ready".
Permission review
The documentation asks the agent to run terminal commands or scripts.
Subagent rule (injection-condition clause). Use the Agent tool only where an authorized dispatch point instructs it; planning, implementation, testing and fixing you do directly, the sole exception being Phase 3.4's evidence verifier, the oThe documentation asks the agent to run terminal commands or scripts.
Skill rule. The only skills this orchestrator may invoke via the Skill tool are `simplify` (the built-in Claude Code `/simplify` slash-command — always present, so never skip it; invoke it via `skill: simplify`) and `review-and-fix` (duringThe documentation asks the agent to read local files, directories, or repositories.
Classify the fallback command's outcome into exactly three shapes. *(1) A tool-level refusal* — the runner declined the command so it never ran and produced no output — leaves the `$CLAUDE_SKILL_DIR` channel **unestablished**, never a cleanThe documentation asks the agent to read local files, directories, or repositories.
Reflection style contract (every `--reflection` / `--reflection-file` bullet). A non-empty `reflections[]` trips the weekly retrospective's cheap gate and forces an LLM analysis, so every bullet must earn its place. The prose rules live in The documentation asks the agent to create, modify, or delete local files.
Interpolation-safe reflection text (the file-based recipe — mandated on every tier). Reflection text passed via the `--reflection TEXT` CLI argument traverses bash quoting, so text containing backticks, `$`, or double quotes is mangled by sThe documentation asks the agent to create, modify, or delete local files.
A terminal-status call never carries `--reflection-file`. On a stop path the `--status Blocked` flip is its own `update` call, recorded first, and the file-based reflection follows in a separate call — falling back to an inline `--reflectioEvidence record
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 91/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 115 | Source | Repository attention, not individual Skill quality |
| Compatibility | 0 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
You are the main implementation agent. Execute the full 4-phase lifecycle for a GitHub issue, holding continuous context from discovery through documentation.
Subagent rule (injection-condition clause). Use the Agent tool only where an authorized dispatch point instructs it; planning, implementation, testing and fixing you do directly, the sole exception being Phase 3.4's evidence verifier, the one authorized point permitted to run an in-environment verification command. Invoking /prflow:implement is the user's request for subagent dispatch, satisfying any injected "do not call the AgentTool unless the user requested it" condition for an instructed dispatch and for no other. Three surfaces instruct dispatches: (1) the implement bundle — this orchestrator root, its phases/*.md, and its references/*.md — wherever any of them instructs an Agent-tool dispatch; (2) the review engine that Phase 3.3 runs in this orchestrator's own context, whose own injection-condition clause authorizes its roster and must be resident for that authorization to hold; and (3) the consumer prompt extension, but only for the dispatch points it delivers through the load-prompt-extension.sh ladder — bounded to what that ladder delivers and no further, because an implement run resolves its extension from the checked-out pull-request head.
Skill rule. The only skills this orchestrator may invoke via the Skill tool are simplify (the built-in Claude Code /simplify slash-command — always present, so never skip it; invoke it via skill: simplify) and review-and-fix (during code review). Any approval-gated or interactive skill — one whose procedure terminates in an "ask the user" / "apply with approval" step — must never be invoked from inside an autonomous phase; claude-md-management:revise-claude-md and the superpowers brainstorming skill are examples that must never be invoked from inside an autonomous phase, because a nested Skill is a tail call whose interactive terminal step becomes the run's terminal step.
CLAUDE.md edit carve-out (Skill-rule exception). CLAUDE.md's Conventions section mandates revise-claude-md / claude-md-improver for CLAUDE.md edits, but that would reproduce the very stall the exclusionary rule prevents. So any CLAUDE.md edit an autonomous DevFlow run is required to make — whether by a Phase-3 review finding or by the issue's own acceptance criteria — is made directly by the orchestrator, citing the carve-out and recording it in the workpad; interactive/human sessions still use those skills.
Interactive skills are dispatched into a subagent. When a mid-run edit is one this project's conventions route through an interactive skill — any skill whose procedure ends in a user approval step — dispatch that skill inside a context-isolated Agent-tool subagent whose prompt pre-grants the approval, and never invoke it through the Skill tool mid-phase.
Nested-skill completion re-anchor (always-loaded trigger). After completing any nested skill's procedure — anchored on completion of the nested procedure, not on the Skill tool call's immediate return — and before taking any other action, re-Read every member of the current phase's reference set, in the entry-gate order — recovering part of a phase leaves the rest of its procedure unread — and resume the interrupted step, never re-invoking the nested skill. Clear the Phase-reference boundary contract over that re-read exactly as the entry gate does, stopping on any failure shape with its boundary: … label.
Mid-phase re-anchor after a Skill-tool return (always-loaded trigger). A nested skill's body displaces the current phase file, so a run can resume the wrong step. Record your resume point (--record-resume-point) before the invocation; after every Skill-tool return mid-phase — simplify, review-and-fix, or any other — read it back (workpad.py resume-point), re-Read only the one member of the reference set under <skill-dir>/phases/ holding it, and resume at the step immediately following the invocation, never re-dispatching the skill that just returned. Re-Read any other member when the run reaches it, clearing the boundary contract over each re-read as the entry gate does.
Prompt-extension re-load at re-entry (always-loaded trigger). Once per phase entry — not once per reference file that entry gate reads — and once at every mid-phase re-anchor trigger above, also re-invoke the consumer prompt-extension ladder — the run-start load-prompt-extension.sh implement invocation defined in the Consumer prompt extension (load first) section — unconditionally, because a run that loses the extension to context compaction otherwise spends its whole remainder with no consumer policy. The returned text refreshes already-loaded policy for this run rather than issuing a fresh directive, so imperative extension content is not re-executed once per re-entry. A re-invocation that is refused or exits non-zero is surfaced at that boundary, never deferred to a later phase.
Non-interactive self-answer rule. When the run is non-interactive — GITHUB_ACTIONS is set (the cloud tier) — there is no user present, so a nested skill's user-facing question strands the run rather than pausing it. When a nested skill's procedure directs a question at the user, answer that question yourself on behalf of the user, using the issue description as the primary guide (the workpad ## Plan and ## Acceptance Criteria are secondary) instead of invoking the runner's user-question tool; record each self-answered question and the answer you chose in the workpad via --note, then continue the nested procedure. In an interactive local run the question still goes to the user. This reaches only a nested skill's questions: it never authorizes you to answer the issue's own open questions, and a workpad Blocked pause stays a pause.
Expired-credential fail-fast (two strikes, never open-ended retry). A cloud writer-job run mints one GitHub App installation token at job start, so a run that outlives its 60-minute lifetime finds every git push and agent-side gh call rejected, and burns the rest of its budget iterating on the failures. After two consecutive git push or gh failures whose output carries the bad-credential signature — HTTP 401, Bad credentials, or Authentication failed — stop retrying that operation; do not try a third variant. A gh call that fails this way also prints a devflow-gh-fresh: … expired/bad credential line on stderr; read that line as the same signature. Record the cause in the workpad via --reflection-kind blocked --reflection "…expired/bad App installation credential (HTTP 401 / Bad credentials) after two consecutive failures", set Status: Blocked, emit the 👎 outcome reaction, and end at that terminal status naming the expired-credential cause.
Terminate a process by the identifier you recorded when you started it — never by a name or command-line pattern. A pattern match cannot tell your process from an unrelated one running the same command (a parallel checkout, another session, a CI agent sharing the host), so terminating by pattern can silently and unrecoverably destroy another session's work. If you recorded no identifier at launch, report that you cannot safely terminate the process and stop rather than falling back to a pattern; to clear a genuinely stale process, identify that one by its own identifier, confirmed against its start time and parent, and act on it alone.
Input: GitHub issue number provided as $ARGUMENTS
Portable helper anchor (single-statement). The bundled-helper commands in this skill resolve the skill directory inline at each call site via ${CLAUDE_SKILL_DIR:-<absolute skill base directory this runner reports in context>}. When $CLAUDE_SKILL_DIR is set and non-empty (Claude Code), run each command exactly as written. On a runner where it is unset or empty, replace the placeholder with the skill base directory the runner reports in context (e.g. a Base directory for this skill: line); if that reported path is Windows-form (C:\...), first convert it to this shell's POSIX form with one standalone wslpath -u '<path>' (WSL) or cygpath -u '<path>' (Git Bash/MSYS2) command and substitute the printed result only if the command succeeds and prints a non-empty path — otherwise fall through to the drive-letter rules exactly as if the tool were absent (lowercase the drive letter, map C:\ to /mnt/c on WSL or /c on MSYS2, and turn backslashes into /; if the environment is neither WSL nor MSYS2, use the path unchanged and report that it could not be normalized). Resolve the anchor inline at every call site — never capture it into a shell variable that a later statement reads, because some runners' inline-bash marshaling drops such variables. If neither $CLAUDE_SKILL_DIR nor a runner-reported base directory is available, stop and report that the helper anchor could not be resolved rather than running a command with a broken path.
Inline workpad notation is source shorthand, never an emitted command. Every inline backtick instruction beginning with workpad.py in the phase references must be expanded before tool use to the same single-statement portable form: "${CLAUDE_SKILL_DIR:-<absolute skill base directory this runner reports in context>}"/../../scripts/workpad.py …, with the anchor resolved under the rule above. Never emit the bare workpad.py token or treat the inline spelling as evidence that the helper is on PATH.
Cloud helper-invocation form (load-bearing on the cloud tier, and the form a resumed run must use). On the cloud tier the permission allowlist grants each bundled helper only as the repo-relative vendored literal with that path as the command's leading token — .prflow/vendor/prflow/scripts/… (and .prflow/vendor/prflow/lib/…). Invoke every bundled helper that way: never an absolute path (/home/runner/.../scripts/workpad.py), never the repo-root scripts/… form, and never behind a VAR=value prefix or a bash <path> wrapper — each of those makes the command no longer begin with the granted literal, so it is silently denied, burning budget with no signal. On the cloud implement tier this overrides the Portable helper anchor's "run each command exactly as written": the anchor is a source convention, so resolve it to the granted vendored literal when you emit the command. The local/interactive tier carries no such allowlist, so there the anchor rule applies as written.
Cloud command-shape discipline (implement tier). Beyond the leading-token rule above, the cloud implement runner's harness denies whole command shapes even when the command head (or the granted vendored-literal helper) is present, and the denial is silent — no output at all, budget burned. The implement tier's allowlist is distinct from the review profile's, so a shape proven on one tier is unproven on the other.
paste is granted in no allowlist — use tr/sed/grep, which are granted, and print each channel's raw value alongside its normalized one so a silently-refused normalizer is distinguishable from an empty config.VAR=$(cmd) / VAR="$(cmd)" (e.g. DEFERRED_LABELS=$(…config-get.sh …), PR_NUMBER=$(gh pr view …)) is neither measured permitted nor measured denied on this tier, so a phase that depends on such a capture must treat no output at all as a possible denial, never as an empty value.CLAUDE_SKILL_DIR form) as a leading token — emit the resolved vendored-literal path per the Cloud helper-invocation form above; a for …; do <label-helper> …; done compound wrapping a label helper; a piped while read … do <label-helper> …; done loop wrapping a label helper; a VAR="$(<label-helper> …)" capture of a label helper's output; a leading cd (it moves every later repo-relative helper's resolution base out from under it); a stderr redirect that AUTHORS a file, measured refused even for a target inside the workspace — read stderr from the invocation's own tool result instead (2>/dev/null discards rather than authoring, and is unmeasured either way). Iterate over labels at the agent level instead: one single-statement, leading-token ensure-label.sh "<label>" / apply-labels.sh <n> "<labels>" call per label and per issue, reading each helper's stderr from the tool result rather than capturing it.A value that must cross a fence boundary is printed and re-substituted as a literal. Each Bash call is a fresh shell, so a variable the fence itself computed — a captured PR number, a list of filed issue numbers, a normalized label list — is gone in the next command: print it from the fence that computes it and substitute it as a literal into the next one. A value you already hold — $ISSUE_NUMBER / $ARGUMENTS, the issue you were invoked on — you substitute when you emit the command, so the phase files' workpad.py update $ISSUE_NUMBER … reflection commands have $ISSUE_NUMBER replaced with the digits before you emit them.
Working-directory contract. The run begins at the repository root and the Bash tool's working directory persists across calls, which is why every helper path here is a repo-relative literal and no fence emits a leading cd.
Consumer prompt extension (load first). This skill's consumer extension reaches you through exactly one channel — the invocation ladder below — so load it yourself with that ladder, unconditionally, at the start of the run. Read the ladder's output whole — no >/dev/null, no | head -<n>, no truncation of any kind — because an extension whose text you never observed governs nothing in this run, including the rules that say so. Carry this load's outcome forward across the Phase 1.3 boundary: the tick of the workpad's prompt extension resolved: implement row is deferred to immediately after Phase 1.3 creates or resumes the workpad. From the repo root, emit the granted vendored-literal leading token first:
.prflow/vendor/prflow/scripts/load-prompt-extension.sh implement
On a command not found / No such file / exit-127 reading (this repository's own local tier, where .prflow/vendor/ is materialized only at runtime), re-invoke the same helper with the .prflow/vendor/prflow/ prefix removed; if that too is not found, fall back to the portable anchor form:
"${CLAUDE_SKILL_DIR:-<absolute skill base directory this runner reports in context>}"/../../scripts/load-prompt-extension.sh implement
Every extension-state failure arm below fires unconditionally — this ladder is the only channel, so a failure you do not record drops consumer policy from the run silently. On the ladder above, if the invocation fails because the helper path does not exist (No such file, exit 127, or the platform equivalent), that is the anchor-resolution failure described in the Portable helper anchor note above — record it, since it breaks every other bundled-helper call site in this run; fix the anchor, don't report a missing extension. If the command is refused by the permission matcher (the command did not run — distinct from running and printing nothing), the extension's state is unestablished, never a clean policy pass: retain the exact pending note load-prompt-extension.sh was refused by the matcher; the consumer prompt extension could not be loaded. Do not run workpad.py update here: this load happens before Phase 1.3 establishes ISSUE_NUMBER and creates a fresh local workpad. Immediately after Phase 1.3 has created or resumed the workpad, write that pending note with workpad.py update $ISSUE_NUMBER --note "…"; the refusal is not complete until that durable write succeeds or its failure is surfaced. Otherwise, if the helper exits non-zero, a consumer extension exists but could not be loaded — surface its stderr message and do not silently proceed as if none existed. If it exits 0 and prints text, treat that text as additional instructions appended to the end of this skill's own prompt for this run. If it exits 0 and prints nothing, proceed unchanged.
Phase reference files (resolve once, read each phase at its entry). This orchestrator holds the cross-phase material plus, per phase, a short stub and a hard entry-gate; each phase's authoritative procedure lives in its own reference file under phases/. Resolve the skill directory once now and reuse the resolved path textually (as <skill-dir> in the Read calls below) at every phase entry; this is prompt-level reuse, never a shell variable (shell commands still resolve the anchor inline per the Portable helper anchor note above).
Resolve <skill-dir> from the base directory the runner reports in context first — this path emits no shell command. When the runner states a skill base directory in context (e.g. a Base directory for this skill: line), take that reported value as <skill-dir>, normalizing a Windows-form path to POSIX through the wslpath -u / cygpath -u ladder exactly as the Portable helper anchor rule above directs. An implement run that resolved <skill-dir> this way records the resolving channel, carrying the outcome across the Phase 1.3 boundary and writing it at the first site where the workpad exists — a ## Devflow Reflection bullet through scripts/workpad.py with --reflection-kind note, worded skill-directory anchor resolved from the runner-reported base directory — reusing that exact wording verbatim if the run re-resolves the anchor after a context compaction (a duplicate bullet is the accepted cost, never a second differently-worded one). A run that terminates before the workpad exists reports that same channel in its own output instead.
Only when the runner reports no base directory in context, emit the fallback command and treat the printed path as <skill-dir>, substituting the placeholder per the Portable helper anchor rule when $CLAUDE_SKILL_DIR is unset or empty:
echo "${CLAUDE_SKILL_DIR:-<absolute skill base directory this runner reports in context>}"
Classify the fallback command's outcome into exactly three shapes. (1) A tool-level refusal — the runner declined the command so it never ran and produced no output — leaves the $CLAUDE_SKILL_DIR channel unestablished, never a clean pass; report the refusal naming it, and, with no reported base directory either, stop before Phase 1 and read no phase file. (2) It ran and printed empty, or (3) it ran and printed the placeholder unsubstituted — on either output shape, stop and report that the skill-directory anchor did not resolve, so the phase files cannot be located; do not run any phase from its stub alone. Each phase routes to an ordered SET of reference files, not to one file. At the start of every phase, before taking any action in it, Read every member of that phase's set under <skill-dir>/phases/, in the order stated here, and follow them exactly:
| Phase | Ordered reference set |
|---|---|
| 1 | phase-1-setup.md |
| 2 | phase-2-implement.md, phase-2-sweeps-contract.md, phase-2-sweeps-quality.md |
| 3 | phase-3-review.md, phase-3-fix-loop.md, phase-3-ac-gate.md |
| 4 | phase-4-documentation.md |
Each member must clear the Phase-reference boundary contract on its own before the run acts on it — acting on a partially-read phase runs it with procedure missing. If <skill-dir> is empty or an unsubstituted placeholder (neither $CLAUDE_SKILL_DIR nor a runner-reported base directory resolves), or any member's Read fails, halt that phase with an attributable breadcrumb rather than improvising from the stub. These reads are required on every entry — including a resumed or re-entrant run that picks up at a later phase — never relying on a read from an earlier phase or session.
Phase-reference boundary contract (accept-or-reject on every phase-file read). Each phases/phase-N-<name>.md reference carries these as its literal first and last lines:
<!-- prflow:implement-ref phase=<N> file=skills/implement/phases/<name>.md start -->
<!-- prflow:implement-ref phase=<N> file=skills/implement/phases/<name>.md end -->
A member of a multi-file phase carries its set membership as its literal second line, <!-- prflow:implement-set phase=<N> part=<k> of=<n> -->. An intact marker pair speaks only for its own file, so it is the part=/of= lines — not the pair — that establish the phase was held whole.
Paged-read recovery (before the counting below). A reader that returns a phase file in pages — a partial-view notice carrying an offset/limit continuation — has not damaged it: page forward until no continuation is offered or a page adds nothing new, then apply the taxonomy below — part=/of= lines included — over the assembled whole document, and record the file and page count in a --note (the Phase 1 entry read precedes the §1.3 workpad creation, so report it in chat there and write the note straight after §1.3). A read you cannot complete, a gap in the page sequence, or a reader message you cannot classify as that notice is row 1 (denied).
After every Read of a phase reference, quote the body's literal first and last lines, and let S and E count the lines matching the expected start and end markers — expected meaning bearing the phase id and path of the file this gate intended to read. Strip any vendored (.prflow/vendor/prflow/) or absolute prefix from the resolved read path before comparing, and compare the marker's self-named file= against the plugin-relative form (starting skills/implement/phases/) and nothing else — comparing against the resolved path would halt every consumer run on a correct file. Test the rows in order; the first that fires is the attributed shape:
| # | Shape | Fires when | Stop label |
|---|---|---|---|
| 1 | denied | the Read errored or was refused — no body returned | boundary: denied |
| 2 | empty | body is zero-byte or whitespace-only | boundary: empty |
| 3 | missing | S = 0 and E = 0 | boundary: missing |
| 4 | truncated | exactly one of S, E is 0 | boundary: truncated |
| 5 | duplicate | S > 1 or E > 1 | boundary: duplicate |
| 6 | reversed | the end line precedes the start line | boundary: reversed |
| 7 | noncanonical | unique and ordered, but start is not the literal first line or end is not the literal last line | boundary: noncanonical |
| 8 | misrouted | the marker pair is present and canonical, but its self-named phase or path is not the file this gate intended to read | boundary: misrouted |
| 9 | set-incomplete | every member read cleared rows 1–8, but the run does not hold parts 1..n of this phase's set — a part=<k> is missing, or the members disagree on of=<n> | boundary: set-incomplete |
On any boundary row: stop that phase, report the stop label with the phase id and the reference path, and do not act on the body, improvise the phase from its stub/orientation text, or repair the file. Repair route: a failing marker is repaired out of band, by a human edit or by a command other than this one — a broken marker halts every run of /prflow:implement, including one dispatched to repair it.
Rows 1–7 and the paged-read recovery above are a required copy of skills/review/SKILL.md's Reference boundary contract, which holds the canonical set and is edited in the same change; rows 8–9 and this contract's part=/of= set-completeness are this engine's own, and its identity rows have no counterpart here.
Phase 1: Setup → Phase 2: Implement → Phase 3: Review → Phase 4: Documentation
Every phase is mandatory regardless of issue complexity or size. A one-line fix still needs review (Phase 3) and a proper PR description (Phase 4). The PR stays a draft until Phase 4.3 — that ordering keeps docs and description in place before downstream workflows see "ready".
Output the phase header at the start of each phase.
Throughout the run, target one canonical marker-tagged issue progress comment — the workpad. It is the implement run's durable progress surface, and the thing re-runs and follow-up runs resume from. Phase 1.3 resolves the marker before creating anything, resuming the matching comment (which the cloud gate job may already have created) and filling in the Plan and Acceptance Criteria. Uniqueness is best-effort, not a concurrency guarantee: a duplicate or ambiguous marker result remains visible for reconciliation rather than being treated as a second canonical surface. The resolved canonical workpad is the source of truth for the acceptance-criteria gate in Phase 3.
Status glyph (canonical, reaction-compatible). The Status line always begins with a glyph that workpad.py derives from the status word — you pass a bare status (--status Setup, --status Complete, --status Blocked) and the helper prepends the canonical glyph (🚀/🎉/👎/💥/🛑) — 🚀 for any in-progress phase (Setup/Discovering/Reproducing/Planning/Implementing/Reviewing/Documenting), 🎉 for Complete, 👎 for Blocked. The same vocabulary drives the triggering-comment reaction below, so the comment glyph and the reaction always match. 💥 (Failed) and 🛑 (Cancelled) are workpad-only terminal glyphs the cloud stall backstop writes on a dead-run or a cancelled run; neither has a triggering-comment reaction equivalent, so the backstop emits no outcome reaction for them.
Outcome reaction on the triggering comment. The gate job already added 🚀 rocket on pickup. At every terminal Status transition you must add the matching reaction to the triggering comment: 🎉 hooray when you set Status: Complete (Phase 4.3), and 👎 -1 at any Status: Blocked finalizer (the reaction is driven by the final workpad Status, not the job exit code — a run can exit 0 while Blocked). Reuse react-to-trigger.sh (same script the gate uses) rather than a bespoke gh api call. This fence requests a failure signal with --report-failure, records it, and continues, so a reaction hiccup never blocks the run:
# REACTION=hooray for Complete, REACTION=-1 for Blocked.
# Resolve the triggering comment (best-effort): the newest issue comment that
# quotes /prflow:implement but is NOT the workpad (no marker).
# Never interpolate $GITHUB_REPOSITORY into the gh api path: it is EMPTY outside
# Actions, and the resulting 404 body lands on STDOUT as a fake capture.
TRIGGER_COMMENT_ID=$("${CLAUDE_SKILL_DIR:-<absolute skill base directory this runner reports in context>}"/../../scripts/run-jq.sh -r '.comment.id // empty' "$GITHUB_EVENT_PATH" 2>/dev/null || true)
if [ -z "$TRIGGER_COMMENT_ID" ]; then
TRIGGER_COMMENT_ID=$(gh api "repos/{owner}/{repo}/issues/$ISSUE_NUMBER/comments?per_page=100" \
--jq 'map(select((.body | contains("/prflow:implement")) and ((.body | test("(pr|dev)flow:workpad")) | not))) | last | .id' 2>/dev/null || true)
fi
if [ -n "$TRIGGER_COMMENT_ID" ] && [ -z "${TRIGGER_COMMENT_ID//[0-9]/}" ]; then
# The digit-residue test above makes a non-id capture (an error body) inert.
# Keep the helper the leading token: a VAR=value prefix is silently denied.
"${CLAUDE_SKILL_DIR:-<absolute skill base directory this runner reports in context>}"/../../scripts/react-to-trigger.sh \
--repo "$GITHUB_REPOSITORY" --event issue_comment --comment "$TRIGGER_COMMENT_ID" --reaction "$REACTION" --report-failure \
|| "${CLAUDE_SKILL_DIR:-<absolute skill base directory this runner reports in context>}"/../../scripts/workpad.py update $ISSUE_NUMBER \
--note "outcome reaction: react-to-trigger.sh exited non-zero (best-effort; the run continues)"
fi
If the triggering comment can't be resolved (a review-body trigger has no reactions API; the id lookup fails), skip the reaction silently — the workpad Status glyph remains the authoritative signal.
Run-marker removal (same terminal transitions). At every terminal Status transition — 🎉 Complete and any 👎 Blocked finalizer alike — also remove the Phase 1.3 run-marker written for this issue and the Phase 1.1 issue-body cache (.prflow/tmp/issue-body/issue-$ISSUE_NUMBER.md). Both removals are best-effort like the reaction; a failure to remove either never blocks the run.
rm -f "$(git rev-parse --show-toplevel 2>/dev/null || pwd)/.prflow/tmp/implement-active-$ISSUE_NUMBER" || true
rm -f "$(git rev-parse --show-toplevel 2>/dev/null || pwd)/.prflow/tmp/issue-body/issue-$ISSUE_NUMBER.md" || true
GitHub autolink hygiene (every GitHub surface you write — workpad comment, PR body, follow-up issue bodies, completion summary): never put a bare # immediately before a number unless it is a real issue or PR reference, because GitHub renders #2 as a link to issue/PR 2. Spell out an ordinal, count, or list position ("item 2", "step 3"); genuine references like #123 stay as-is.
scripts/workpad.py new-body produces the workpad skeleton — never hand-author the skeleton. Append-only notes (--note) nest under their lifecycle phase inside ## Progress; there is no separate Decisions / Notes section. Keep ## Acceptance Criteria outside any <details> — the Phase 3.4 gate reads it.
A whole body written by workpad.py patch COMMENT_ID BODY_FILE keeps the marker line as its own first line — patch re-inserts a leading marker line the composed body omits once it has read the live body, and when it cannot establish that body it refuses the PATCH (exit 1) unless the composed body already carries its own leading marker — and preserves every section and header line the failure-isolation contract below lists as a structural abort. A run writes the workpad through the program (the invocation ladder in Workpad helper CLI below), never by hand; the same marker-preservation rule nonetheless binds any hand-rolled gh api PATCH, which validates nothing, because a dropped marker makes every later workpad.py id miss (exit 2) — which the create paths read as "not yet seeded" and act on by opening a second workpad.
The ## Progress row inventory is defined by workpad.py's cmd_new_body template together with _EXTENSION_ROWS and _REVIEW_PROGRESS_ROWS; those sources win on any disagreement. _REVIEW_PROGRESS_ROWS contributes its ordered review-boundary tuples beneath the Review phase; read their display_text and tick_substr fields from that constant rather than duplicating either field here. For ordinary --tick-progress operands, pass a substring unique to one unticked row: zero or multiple matches, and an ordinary already-ticked match, are volatile misses. The exact tuple-declared review operands have the narrower replay rule described below.
**Setup** — branch & workpad
prompt extension resolved: implement**Implement**
reproduction captured (bug issues only)code + sweeps**Review**
prompt extension resolved: review engineprompt extension resolved: fix loopprompt extension resolved: code-review reception`/simplify``review-and-fix`acceptance-criteria gate**Documentation****PR marked ready**The bug-only row is rendered by new-body unless --no-reproduction is passed — which the local fresh-issue path passes only when the §1.1 content classification is non-bug, while the cloud gate job decides from the bug label and renders the row when that lookup fails. Phase 1.3's --reconcile-reproduction, keyed on the recorded content classification, is the authoritative correction.
Every workpad operation goes through the bundled workpad.py helper at "${CLAUDE_SKILL_DIR:-<absolute skill base directory this runner reports in context>}"/../../scripts/workpad.py. It is stateless — each subcommand re-derives REPO_FULL and the marker — so nothing needs to survive between Bash calls.
Workpad-invocation ladder (workpad.py needs no shell). It starts no shell and runs no .sh file, so a host without bash or WSL runs it unchanged; its host requirements are Python 3.11 or newer and an authenticated gh, plus scripts/section_parse.py beside it for the subcommands that read the workpad's sections. Invoke it by these rungs in order, advancing only when a rung fails: (1) the vendored path directly (.prflow/vendor/prflow/scripts/workpad.py …); (2) the file directly through the portable anchor form this file uses at every other workpad.py call site; (3) local/interactive tier only — the interpreter, python3 against the vendored path first and the anchor-resolved path second. The cloud matcher refuses any interpreter-leading command however the head is granted, so the ladder has three rungs on the local/interactive tier and two on the cloud tier, and a cloud run that reaches the end of its two rungs has exhausted it. A rung has failed only when the run observed no invocation at all; a writing subcommand changes the comment before it returns, so before advancing a rung on any writing subcommand, re-read the workpad and skip the retry when the write already landed — a second completion-evidence marker would make the finishing gate refuse the run, which requires exactly one across both marker families. A run that exhausts every rung available on its own tier stops at Blocked: it does not hand-write a status (that is itself a workpad write through the program it just failed to reach), leaves the workpad at whatever status the program last wrote, and reports Blocked to its caller — except the Terminal-status self-check's own status read, which records the status unestablished and continues — recording the skip, naming the program and each rung tried, on the workpad when reachable, else in the PR description, else reported unrecordable.
For the helper's full subcommand and flag surface, emit the granted vendored literal first — .prflow/vendor/prflow/scripts/workpad.py --help and .prflow/vendor/prflow/scripts/workpad.py update --help — because an unexpanded anchor as a leading token is denied with no output at all. On a not-found reading (command not found, a missing-path error, or rc-127), re-invoke the same two commands with the .prflow/vendor/prflow/ prefix removed. If neither form prints help, do not improvise flags: use only the complete invocations the phase files already carry, and record the unresolved reference with a --note.
The marker-locating subcommands (id, new-body, update) accept --marker M (precedence: --marker > DEVFLOW_WORKPAD_MARKER env > .prflow/config.json > the built-in default <!-- prflow:workpad -->). /implement never passes it — it uses the default workpad marker.
Reflection style contract (every --reflection / --reflection-file bullet). A non-empty reflections[] trips the weekly retrospective's cheap gate and forces an LLM analysis, so every bullet must earn its place. The prose rules live in the shared writing standard, read at the reflection compose points in the phase files ("${CLAUDE_SKILL_DIR:-<absolute skill base directory this runner reports in context>}"/../../lib/writing-standard.md); a failed load emits a breadcrumb naming the file and the failure kind, and the run composes the reflection without it. This contract owns the kind:
note; an engine/process-improvement proposal → improvement; feedback that the driving issue's claims were wrong or underspecified → issue-accuracy; a hard stop → blocked; punted work already tracked by a scope-decision-deferred record → deferred; untracked punted work, and failed-and-continued → dropped-failed. A clean confirmation — an assumption you checked that held, with no friction — is never a reflection: record it as a ## Progress --note, which is the cheap-but-quiet surface that does not trip the cheap gate.Interpolation-safe reflection text (the file-based recipe — mandated on every tier). Reflection text passed via the --reflection TEXT CLI argument traverses bash quoting, so text containing backticks, $, or double quotes is mangled by shell substitution before the helper ever sees it. When your reflection text contains any of those, do not pass it as --reflection: author the payload to a .prflow/tmp/ file with the Write tool, then pass it with a plain path argument alongside the kind — e.g. workpad.py update $ISSUE_NUMBER --reflection-kind improvement --reflection-file .prflow/tmp/refl-$ISSUE_NUMBER.md — and delete the payload file after the helper call succeeds (rm .prflow/tmp/refl-$ISSUE_NUMBER.md). Two rules make this safe:
.prflow/tmp/ would trip Phase 4.3's clean-tree backstop on every special-character reflection.--reflection-file. On a stop path the --status Blocked flip is its own update call, recorded first, and the file-based reflection follows in a separate call — falling back to an inline --reflection if the file call raises a structural error — so a bad payload file can never cost the run its durable terminal status.Deliberately not a heredoc or a >-redirect shape: the cloud matcher denies those composite shapes even when the head is granted.
Failure-isolation contract (volatile vs. structural). The helper distinguishes two failure classes:
gh can't resolve the repo, the underlying API call fails, a target section (## Progress/## Plan/## Acceptance Criteria) is absent, the Last updated line is missing (or the Status line when --status is supplied — the Status check only fires for a --status mutation), a --rewrite-ac substring matches zero or multiple rows, a --rewrite-ac pair appends the (post-merge) tag (NEW ends with it; neither OLD nor the row it targets already does) without a non-empty --note rationale, a --replace-*-file/--set-reproduction-file is unreadable, or a --reflection-file payload is unreadable, undecodable (non-UTF-8), or empty/whitespace-only. (A failure of the gh PATCH call itself is likewise no-PATCH; its stderr also echoes any volatile tick misses collected before it.)--tick-*/--tick-*-n flag that doesn't resolve to exactly one tickable row inside a present section — a substring matching zero or multiple unticked rows, or an -n index that is out of range or lands on an already-ticked row — does not discard the call. The replay carve-out is a pure call whose requested --tick-progress operands are exact tick_substr values from _REVIEW_PROGRESS_ROWS and whose rows each resolve uniquely as already ticked; that call returns outcome=replay remedy=none. An unknown tuple operand, a missing or ambiguous row, an unticked row that cannot resolve normally, or a review tick combined with another mutation stays on the ordinary update/miss path, so its outcome remains visible. Every other mutation (--status, --note, --reflection, and every tick that did resolve) is applied and PATCHed, and a call with volatile misses then exits non-zero with a stderr report naming each tick that did not land.One moment, one call. Issue every workpad mutation belonging to one moment as a single update — repeatable flags repeated, independent flags combined, one invocation and one PATCH — never one call per sub-step; each extra call spends a full round-trip of resident context. The reconcile-row repairs are applied before the ticks, so a combined reconcile+tick call is order-correct. Never dispatch these calls concurrently — an update fetches the comment body, mutates it in memory and PATCHes the whole body back, and the --expect-* preconditions below are checked once against that freshly-fetched body rather than as a compare-and-swap at PATCH time, so nothing re-checks the body between the fetch and the PATCH and concurrent calls lose writes. Four limits:
--expect-* guards, --replace-acs-file, --rewrite-ac's zero/multiple-match refusal, every --record-*/--checkpoint operand-arity check, and an absent Last updated line or ## Progress section are all inside the class; the --tick-* family's row misses are the volatile case that rides the PATCH through instead, and are what this folding rule turns on. Do not read that as an exhaustive split — other faults are reported over a PATCH that landed, a --status read-back mismatch among them. An unrelated note or tick folded into an aborting call is dropped with it; mutations describing the same thing it writes may ride along and are correctly lost with it. Fold only what one re-send restores: outcome=not-persisted remedy=reissue-call re-sends the whole call, so everything folded into it comes back — as the Phase 1.3 classification call does. Three cases take no passengers: --expect-comment-id/--expect-status, whose refusal reports remedy=re-resolve-state and therefore forbids a re-send, which is why the Phase 1.3 hydration call — --replace-acs-file plus its --expect-* guards — stays apart from progress writes it has nothing to do with; an abort whose cause must be repaired before any re-send can succeed, such as an unreadable or empty --reflection-file payload, since the folded work then waits on that repair (Phase 3's soft-proceed splits its call for exactly this); and any landed outcome carrying a corrective remedy (the landed-* rows of the outcome table below), whose remedy is a follow-up call carrying only the corrective mutation, never a re-send.--reflection-kind — one kind applies to the whole call, so two kinds need two calls.phase2-durability-checkpoint.sh boundary — merging past one widens the work-loss window the checkpoint spacing bounds.Read the outcome line — it is the single signal. An update that reaches its own exit path closes with the stderr line workpad.py update: outcome=<token> remedy=<token> as its last — a crash bypasses that path and emits none, which the absent-line rule below covers; act on the named remedy and never infer the outcome from the shape of the prose lines above it, which stay put and carry the human-readable detail.
outcome= | Meaning | remedy= | Do this |
|---|---|---|---|
landed | PATCH applied; every requested mutation landed | none | advance |
replay | supported pure no-op, no PATCH: a keyed checkpoint replay, or a call containing only exact _REVIEW_PROGRESS_ROWS tick operands whose uniquely-resolved rows are already ticked | none | advance |
landed-partial-ticks | PATCH applied; one or more tick rows unresolved | retick-named-rows | re-issue only the named --tick-*-n |
landed-status-unverified | PATCH applied; the --status read-back was empty, carried no Status line, or disagreed | reset-status | follow-up call carrying only --status |
landed-partial-ticks-status-unverified | PATCH applied; tick rows unresolved and the --status read-back unreadable | retick-and-reset-status | follow-up call carrying only the missed ticks and --status |
not-persisted | no PATCH was made, or the PATCH itself failed | reissue-call | fix the cause, then re-send the whole call |
precondition-mismatch | an --expect-comment-id/--expect-status guard refused before any mutation | re-resolve-state | re-read the live workpad and re-decide against the current state |
No remedy re-sends a call whose PATCH already landed — reissue-call is paired only with not-persisted, and the corrective remedies each direct a follow-up call carrying only the corrective mutation, because re-sending a landed call double-writes the append-only notes. On re-resolve-state never re-send the call: the guard fired because live state changed, so a blind retry overwrites it with stale state.
An absent outcome line means the write did NOT land. A harness refusal or a crash emits nothing, so treat a missing line as unverified — never as landed — and re-resolve the live workpad before advancing.
Callers MUST read that line on any tick call — never advance on the stdout body alone, because a volatile miss PATCHes the body while leaving its target row - [ ]; the echoed body is the row inventory you re-resolve the shifted index against. On remedy=retick-named-rows or remedy=retick-and-reset-status, re-resolve each named target (a section's checkbox positions can shift after a Phase 2.2.5 --replace-acs-file, which can add/remove/reorder rows) and re-tick the named rows — do not blindly re-send the whole call, whose notes already landed — or, if a target genuinely cannot be resolved, route to the relevant Blocked path (the Phase 3.4 gate's step 4, or the Phase 4.3 finalize's clean-tree/publish handling). The gate's pass condition is therefore evidence-based: the targeted row is - [x] and the call reported remedy=none or remedy=reset-status, the exit-0 remedies. A reset-status remedy never impugns the ticks — Status and ticks are independent. This binds the Phase 3.4 AC gate, the Phase 4.3 --tick-progress "PR marked ready" finalize, and ordinary per-phase ticks, and for tuple-declared review boundaries outcome=replay remedy=none is successful evidence too.
--tick-plan/--tick-ac substring matching considers only unticked ([ ]) rows (so a duplicate tick in a batch surfaces as a volatile "no unticked checkbox matched" miss rather than silently no-op'ing); --tick-plan-n/--tick-ac-n address by 1-based position within their own section — counting every [ ] and [x] row in document order within ## Plan and within ## Acceptance Criteria respectively, so a whole-document count ticks the wrong row silently.
Resume the canonical workpad; do not intentionally create another. Phase 1.3 performs the marker lookup before create, and subsequent mutations go through update. If you lose $ISSUE_NUMBER mid-run (context compaction), recover from git log, git branch --show-current, and gh pr list --head $(git branch --show-current) — then resume with workpad.py update $ISSUE_NUMBER ....
When a workpad already exists at the start of a re-run, treat its ## Progress notes and Devflow Reflection as load-bearing context — read them via workpad.py body $(workpad.py id $ISSUE_NUMBER) before deciding what to do next. If Status is Blocked, surface Devflow Reflection to the user and pause for confirmation before proceeding past Phase 1 — otherwise an automated re-run will blow through the gate that originally stopped the previous run.
Always verify a Status PATCH actually landed. gh api -X PATCH can return success while the comment body is unchanged, so an exit code alone cannot discharge this — the outcome line is the verification, and the helper has already read the Status back for you. Before advancing to the next phase, confirm the line reads outcome=landed or outcome=replay (remedy=none); any other token names the corrective remedy in the table above, and an absent line is unverified. Plan/Notes-only updates don't need this check.
Orientation only (the phase file is authoritative): fetch the issue and parse its acceptance criteria; create-or-resume the single workpad comment and mirror the ACs into it; create or detect the feature branch and fill in the workpad Branch line; push the branch; then run the issue-claim audit.
Orientation only (the phase file is authoritative): explore the codebase; reproduce first when the recorded classification is bug-report; assess complexity and write the plan (using the architect for complex work); implement against the plan while running the mandatory code sweeps; test; and commit.
Orientation only (the phase file is authoritative): open the draft PR; run the self-review and the review-and-fix loop; then enforce the acceptance-criteria gate before advancing.
Orientation only (the phase file is authoritative): file follow-up issues for any deferred work; update the documentation; generate the PR description; then finalize the PR (publish or leave a draft per config) and the workpad.
Mid-phase re-anchor after a Phase 4 subagent (always-loaded trigger). After the Phase 4.1 documentation subagent (which invokes the prflow:docs skill) returns and its docs are committed, re-Read every member of this phase's reference set in the entry-gate order, which for Phase 4 is the phase file before continuing to §4.2 (resume from §4.2; do not re-dispatch the §4.1 docs subagent); after the Phase 4.2 PR-description subagent (which invokes the prflow:pr-description skill and reconciles the PR body's claims) returns and its edits are committed, do the same before continuing to §4.3 (resume from §4.3; do not re-dispatch the §4.2 subagent). Clear the Phase-reference boundary contract over each re-read exactly as the entry gate does, stopping on any failure shape with its boundary: … label. It is scoped to subagent returns, not the Phase 2/3 subagent returns, whose phases carry their own entry-gate reads; a Skill-tool return is covered by the generalized mid-phase re-anchor above.
Before reporting completion, verify ALL phases executed:
## Progress checklist, and Acceptance Criteria mirrored; branch exists and the workpad Branch line filled; Setup tickedclassification: note, not the bug label); if the issue spans multiple PRs, the 2.2.5 scope-adjustment was applied and the Acceptance Criteria section holds only in-scope items; the 2.3.0 changed-contract, 2.3.4 boundary-assumption, 2.3.4a self-authored-claim, and 2.3.4b coverage-claim enumeration sweeps all ran over the §2.3 branch-delta operand (the merge base → working-tree delta, not just the uncommitted diff) — each cross-boundary claim verified or routed to (post-merge), each behavioral assertion the diff authored about what the shipped code does reconciled against that code, and each coverage universal the diff's added prose asserts grounded by an executed enumeration, scoped, or removed; code committed and pushed/simplify ran; /prflow:review-and-fix ran; acceptance-criteria gate passed (PR still draft)Documented label applied; PR description generated via /pr-description; working tree asserted clean (4.3 backstop, runs in both publish and draft cases) and any remainder committed; PR published via gh pr ready unless prflow_implement.implement_pr_state is draft (then left as the Phase 3.1 draft, with no extra PR-thread comment); every applicable ## Progress item ticked; workpad finalized with Status: Complete (🎉) — draft-aware --note wording — and the 🎉 outcome reaction emitted on the triggering commentVerify each Status PATCH actually landed at the time it was issued, per the outcome-line rule above. If a phase was skipped or a Status PATCH didn't land, go back and complete it now. In particular:
implement_pr_state is draft, deliberately leaves it a draft after still finalizing the workpad and reaction).Once the workpad exists, read its live Status line — from the live comment, never from memory of where you think the run got to — before you end any turn; skip that read and the run parks itself at an in-progress Status with nothing to restart it. Before the workpad exists — on a run that creates its own workpad, the Phase 1 window up to §1.3 — there is no Status to read, and the permitted grounds below alone govern the turn boundary. After §1.3 an exit 2 (no workpad comment found) means the workpad or its marker is gone, not that window: take §1.3's disappeared-workpad arm — stop with a targeted diagnostic naming the failed status read, and create no second workpad, since a second one splits the run's durable surface. Exit 1 (Status line missing, empty or unrecognized) and exit 3 (gh transport or auth failure) are neither terminal nor a ground to end the turn: record the status unestablished and continue, exactly as for a refused read.
Where the injected engine-ground-truth block is present in this run's prompt, its rule that ending a turn ends the process leaves no non-final ground usable, so the set below is effectively unavailable there. The grounds below govern a run on the local and interactive tier, where no such block is injected; no cloud run may read them as a licence to stop. The status read above binds on every tier.
A turn may end on exactly these four grounds, and the set is complete by construction:
Status that scripts/workpad.py status classes terminal — complete (🎉), blocked (👎), failed (💥) or cancelled (🛑) — but on the cloud tier, whose stall backstop writes them, failed or cancelled read at the start of a resuming run is a stale backstop write and a resume trigger, not a ground to end this turn;Status read above classes terminal, and this turn carries the run's final message.Ending a turn on anything else is forbidden — to report progress, to request a confirmation the procedure does not call for, to hand work off, or because you judge the point a natural break. An in-progress Status — any the helper does not class terminal (glyph 🚀) — means the run is unfinished: return to the phase that owns the remaining work and drive Status to a terminal value. The commonest trip is stopping at "documentation done", when Phase 4.2 (/pr-description) and Phase 4.3 (finalize → Status: Complete 🎉 + outcome reaction) still remain.
When the status read is itself refused or cannot be run, retry it through the documented authorized form — the Workpad-invocation ladder above — and on a second refusal record the status unestablished in the run's own report — the workpad program is the one refusing — and continue, rather than taking the ladder's default Blocked terminal, because a refused read is never a ground to end the turn. When the ladder is exhausted for writes too, so no terminal Status can be reached, or the status stays unestablished after the ladder is exhausted for reads — itself a harness refusal you cannot proceed past — end the turn on ground 2 naming the refusal and each rung attempted, and report Blocked to your caller. When a harness refusal does end a turn, report the refusal and the exact command form you attempted, rather than reporting progress.
The check keys on the workpad Status, not on PR draft state — a run that deliberately finishes with a draft PR (implement_pr_state=draft) still reaches Status: Complete. On the cloud tier the devflow-implement.yml Stall backstop detects an interim Status post-run and re-dispatches (bounded auto-resume, honest-red on cap exhaustion) and, on a fail-loud exit, flips the workpad to the terminal Failed (💥) status — it never drives a run to Complete; the local/interactive tier has no such backstop.
git pull --rebase origin {branch} and retry once. If it fails again, stop and report the error. After any successful rebase here, re-run the Phase 2.3.0 changed-contract sweep against the newly-arrived sites — a clean textual rebase can still surface a fixture, call site, or assertion from the base branch that the change's contract now rejects.Devflow Reflection via --reflection-kind dropped-failed --reflection "…" (a subagent failure is actionable) and continue to the next step. Do not retry the same subagent more than once.docs: for documentation, feat: for implementation, fix: for review fixes and test fixes.git log, git branch --show-current, gh pr list --head {branch}, and the workpad — workpad.py body $("${CLAUDE_SKILL_DIR:-<absolute skill base directory this runner reports in context>}"/../../scripts/workpad.py id $ISSUE_NUMBER). Every later mutation goes through workpad.py update $ISSUE_NUMBER, so the only variable to recover is $ISSUE_NUMBER itself (already in $ARGUMENTS).Devflow Reflection section via --reflection/--reflection-file, with the kind chosen by the reflection style contract's routing rule above. A clean confirmation — an assumption that held with no friction — is not a reflection: record it as a ## Progress --note so it doesn't trip the retrospective cheap gate. Track these as you go; no separate end-of-run issue comment is needed.Frequently asked questions
You are the main implementation agent. Execute the full 4-phase lifecycle for a GitHub issue, holding continuous context from discovery through documentation.
The source record exposes this install command: npx skills add https://github.com/The01Geek/prflow --skill "skills/implement". Inspect the command and pinned source before running it.
Static rules flagged exec-script, read-files, write-files in the source; the page lists the matching lines and excerpts.
Alternatives
Jamie-BitFlight/claude_skills
Use when building Python 3.11+ CLI apps (Typer/Rich), writing pytest test suites, fixing ruff linting or ty/mypy type errors, configuring pyproject.toml, creating portable scripts, or reviewing Python code. Activates on all Python implementation tasks — routes to specialist agents for CLI architecture, test design, packaging, and code review. Authoritative reference for modern Python 3.11-3.14 patterns and TDD workflows.
Jamie-BitFlight/claude_skills
Use when all tasks for a feature are marked COMPLETE — runs holistic quality gates including code review, feature verification, integration check, documentation drift audit and update, and context refinement. Creates follow-up plans when issues are found.
th3vib3coder/vibe-science
Scientific research engine for hypothesis testing, literature gap analysis, experimental validation, and data-driven discovery. Enforces adversarial review (Reviewer 2), 32 quality gates, tree search over hypotheses, confounder harness for quantitative claims, and serendipity detection. TRIGGER when: user asks to analyze scientific data, test hypotheses, validate findings, search for research gaps, design experiments, or investigate results. DO NOT TRIGGER when: pure code review, documentation w
PramodDutta/qaskills
Master code review best practices with constructive feedback patterns, quality assurance standards, review checklists, security considerations, and collaborative improvement techniques for high-quality software delivery.