/execute-task
The execution layer of the planwright pipeline (REQ-E1.1–REQ-E1.5): take one
ready unit (a single task or a cohesion bundle) from a Ready or Active spec with
a signed-off kickoff brief and carry it from a failing test to a draft PR.
/orchestrate dispatches it into a prepared worktree; a human may also run it
inside one. It works from the kickoff
brief, the durable contract (D-3), not by re-reading the spec; sign-off and
merge are the human's two reserved controls (see Invariants).
Doctrine
This skill is procedure, not doctrine. Read the manifest's rule docs via
scripts/resolve-rule-doc.sh <doc-name> (under the resolved planwright root);
their definitions govern the concepts this skill names. Per
doctrine/instruction-hygiene.md, run-start entries load before work begins,
point-of-use entries at the named step or branch.
Invoking plugin scripts (REQ-D1.1, D-7). Call scripts/<name>.sh by the
resolved literal absolute path, never $VAR/scripts/<name>.sh —
doctrine/plugin-script-invocation.md.
If a manifest doc does not resolve — at run start or its point of use — halt
naming the missing doc and the chain consulted (REQ-K1.7). decision-domains
degrades gracefully instead: absent, note it in one line, skip the drift check,
and use engineering judgment.
Doctrine: run-start spec-format (status lifecycle, anchors, freshness gate)
Doctrine: run-start proportionality
Doctrine: point-of-use research-rigor
Doctrine: point-of-use security-posture
Doctrine: point-of-use validation-rigor
Doctrine: point-of-use finding-categorization
Doctrine: point-of-use gate-wiring
Doctrine: point-of-use decision-domains
Pre-flight
Run once per invocation, in order. Any halt records the unit to the spec's
tasks.md ## Awaiting input section with the reason — on a format-version 2
bundle as a committed reference bullet, **Task <id>** — <reason>, the block
staying in ## Tasks (a halting-skill human-payload write, D-3) — and ends the
step (the gate-wiring pause protocol's dispatched arm); attended, present and
wait instead.
- Parse
$ARGUMENTS. Extract one or more task IDs (5, 3.5, or 5 6
for a bundle) and an optional spec path, given as either specs/<spec> or
the bare <spec>. Validate each
<id> against ^[0-9]+(\.[0-9]+)?$, and the extracted <spec> against the
anchored identifier pattern ^[a-z0-9][a-z0-9-]*$ (≤64 chars, REQ-A1.8)
before it appears in any path or command; a failing token is never
interpolated. No task ID: halt and ask which task to execute.
- Resolve the spec path, in order: (a) an explicit spec-path argument
(
specs/<spec> or bare <spec>, validated in step 1); (b) the branch name
parsed against planwright/<spec>/task-<ids> (D-36); (c) the current
checkout when it holds exactly one specs/*/ bundle whose Status: is
Ready or Active; (d) ask, listing the available bundles
(underscore-prefixed accumulators are not bundles). Verify the directory
holds requirements.md, design.md, tasks.md, and test-spec.md.
- Resolve the run-start doctrine docs (above); halt on a resolution
failure. Point-of-use docs resolve at their named steps.
- Verify the spec is Ready or Active (REQ-C1.1, superseding the bootstrap
non-Active refusal REQ-J1.2, D-33; kickoff-lifecycle D-2, D-3). Read the
**Status:** line in requirements.md. Ready (signed off, no work
started) and Active (work in flight) are both executable; refuse
Draft, Done, Retired, and Superseded. The spec file stays Ready during
execution: Ready↔Active is derived, not stored (D-2), written only by
orchestration-concurrency's single reconcile writer (D-3), so a task
normally runs against a Ready spec, not the stored-Active demand this
gate must not reintroduce. On Draft, halt and suggest
/spec-kickoff; a terminal (Retired/Superseded) or Done spec has nothing to
execute. A Ready spec runs on the same terms as Active: the freshness gate
(step 7) still applies (REQ-C1.3); the two gates compose. There is no bypass
flag.
- Run the validator.
scripts/spec-validate.sh specs/<spec>. On this
dispatch path a missing or non-executable validator fails closed and halts
(REQ-K1.7). A Ready or Active bundle's findings are errors: surface them and
halt.
- Verify the kickoff brief.
specs/<spec>/kickoff-brief.md must exist and
carry a final sign-off record with an anchor line (D-36). Absent, or partial
(sections signed but no sign-off record, or a record without its anchor line
— anchor-written-last makes a killed kickoff look absent, by design): halt
and prompt /spec-kickoff.
- Run the execution freshness gate (REQ-F1.9, REQ-F1.10, D-45; the
spec-format anchor rules; fleet-hardening D-9). It stops execution against
content changed since sign-off and against a stale local main:
- Fetch-before-gate (D-9, REQ-D1.1). Run
scripts/dispatch-fetch.sh --spec specs/<spec> <primary-checkout>: it fetches origin (bounded, no
local-main advance) and prints the fetched origin/main anchor
(re-pointing spec-anchor.sh). Exit 0 → gate vs origin/main; 3
(no-remote, offline) → gate vs local main; 4 (stale-transient) or
any other nonzero → do not silently proceed: park to Awaiting input.
- Validate the entry (brief's most recent, from the resolved ref): it
parses, uses a sanctioned command form (any form on
spec-format's
Sanctioned command forms list), a sanctioned writer (a
/spec-kickoff sign-off or the marked Class: expression-only ritual), and
— meaning-class — a dispositioned Lens-pass:.
- Compare the recorded anchor against the one
dispatch-fetch.sh
recomputed. Match → proceed. Mismatch → halt (remedy: a
/spec-kickoff delta re-walkthrough). No / unparseable / non-sanctioned /
wrong-writer entry → halt (repair the record per REQ-F1.10). A
pre-change entry (predating the header-**Status:** exclusion, or
whole-file form) mismatches over unedited content; remedy: the one-time
classify-then-self-re-anchor. Halts go to
Awaiting input; no bypass flag.
- Read the brief slice and task block(s). From the brief: the signed-off
goal restatement, the task graph, and the unit's risk entries. From
tasks.md: each
block's Deliverables, Done when, Dependencies, and Citations. Confirm
every dependency is completed — on a v1 bundle it sits in ## Completed; on a
v2 bundle it derives Completed via the derivation engine
(scripts/orchestrate-state.sh); if one is not, halt naming it.
- Derive the full-CI command (D-19). Pick the most comprehensive guard the
repo ships, checking in order: a
mise.toml aggregate task (planwright's own
is mise run check); a package.json ci/test script; a Makefile
ci/test target; a lefthook.yml pre-commit stack; a language
toolchain's check. Prefer the aggregate over a bare test run. If none can be
derived, ask.
- Resolve
dispatch_isolation (D-5, REQ-C1.3). Run
scripts/resolve-dispatch-isolation.sh (under the resolved planwright root)
to read the knob through the four-layer overlay; it prints per-step (the
assigned-decision default) or per-unit and applies the REQ-E1.4 by-layer
malformed policy. A hard-fail (exit 4 — a malformed team-shared value or
config; exit 5 — a broken install whose core default is unresolvable) is a
stop condition: record to tasks.md Awaiting input and halt. A
warn+degrade (an adopter/machine-local value degraded to the core default,
exit 0) proceeds. Record the mode; it governs how Implementation and
Convergence host this unit's steps (see Step isolation).
- Update Last activity (v1); write no placement or
Status. On a
format-version 2 bundle this step writes nothing — a v2 block carries no
annotations, and derived execution state never produces commits (version
keying, here and throughout this skill, reads the declared Format-version:
as the scripts do; unparseable fails closed, never the v1 arm — D-7). On v1:
the dispatch record (task branch + runtime marker) already makes the unit
derivable as In progress, so write no section placement and no
Status line (REQ-B1.1, D-1); a
block still in ## Forward plan while its branch is in flight is intentional
snapshot lag, not corruption (REQ-B1.2). The only edit is the block's
- **Last activity:** <today> annotation, anchor-excluded (spec-format
canonical extraction) and not a Status line, so it trips neither
corruption guard (full race rationale at PR step 3). Commit it when
commit_on_state_move is true (read config/defaults.yml overridden by
<repo>/.claude/planwright.local.yml, local wins; absent/malformed falls
back to the default with a one-line warning).
Implementation
Step isolation (dispatch_isolation, REQ-C1.3, REQ-C1.4, D-5)
The mode resolved in pre-flight step 10 governs how this unit's steps — the
implementation phase (test-first loop, research, security pass, CI), then each
review_sequence skill — are hosted. It changes hosting, not work or order.
per-unit (strictly preserved): the whole unit runs in one session —
implement, run CI, invoke each review_sequence skill inline with --nested,
then push and open the PR. Context carries across steps.
per-step (the assigned-decision default): each step runs in its own
fresh session, seeded by /resume from durable state alone (brief,
tasks.md snapshot, git log, open PR), so context stays bounded and each
review's perspective is uncontaminated by prior steps. Each step commits its
work with the Planwright-Task: trailer. Realization is
the backend's job (D-2): a session-grade backend spawns a session per step; the
terminal rung (D-3) approximates it with a context clear + /resume reseed; a
backend doing neither degrades to per-unit (degrade capability, never
safety).
Launch tier. A per-step session is a launch: resolve
scripts/allocation-apply.sh plan --key execute_step --backend <backend> --unit <spec>:task-<id> --step <step> and apply per backend-capability-contract's
Applying a resolved tier. Exit 3 is withheld: do not launch; only exit 6
degrades. The terminal rung advertises none, inheriting the operator's
session.
State-safety holds in both modes (REQ-C1.4): every tasks.md placement move
goes only through the sibling reconcile under the per-spec lock, no per-step
session writes dispatch/progress state or opens a PR — push and PR creation
remain this skill's single terminal step (see Invariants).
Commit convention (REQ-C1.4, D-2)
Every commit this skill authors for the unit (test-first action commits, the
observation chore commit, any expression-only amendment commit) carries a
Planwright-Task: <spec>/<id> footer trailer: the durable completion anchor the
orchestration-state derivation reads by scanning the whole commit message, so it
survives a squash/rebase merge, branch deletion, and direct-to-main commits.
Stamp it through the shared helper, not by hand, so it is grammar-validated and
identical everywhere:
printf '%s\n' "$message" \
| scripts/planwright-commit-trailers.sh <spec>/<id> \
| git commit -F -
For a bundle, pass one ref per task (… <spec>/<id1> <spec>/<id2> …); the
helper emits one trailer per task. The trailer is footer-only and additive — no
subject-line change, no Claude/co-author attribution — so the no-attribution
rule is unaffected.
Test-first development (REQ-E1.1, validation-rigor)
Read test-spec.md for the unit's cited REQs first: each entry describes the
verification path — what to test and which edge cases matter. Then, for every
piece of new behavior or bug fix the unit introduces:
- Write the test, grounded in the
test-spec.md entry and the Done when:
conditions. It must be specific enough to fail for the intended reason and
pass only when the implementation is correct.
- Run it and confirm it fails for the right reason — the failure message
corresponds to the behavior being implemented, not a syntax, import, or
unrelated error. A test that passes immediately, or fails for the wrong
reason and cannot be isolated, is a stop condition.
- Implement to make the test pass, consulting the brief's goal restatement
and risk register.
- Confirm the test passes — the same test, unchanged. Iterate on the
implementation, never the test.
Validate the solution per validation-rigor: the targeted test, the wider
project suite (the CI step below), and the altitude check (fix the cause at the
right layer, not the symptom). A unit that is purely configuration,
documentation, or infrastructure with no testable behavior per test-spec.md
skips the loop; note in the PR body why no test was added.
Research Rigor (REQ-D1.5, research-rigor)
Research fires before implementation when a trigger holds — a new
dependency, an unfamiliar domain, a security-touching pattern, a
version-sensitive API, or a "how do mature projects do this" question. Consult
current sources in order (official docs for the pinned version, then the
library's own source and tests, then issues/RFCs), honor recency over model
memory, and run the antipattern check before adopting a pattern. Record the
findings, tradeoffs, and sources in the brief's risk register, appended to a
named section — never overwriting existing rows, never as an anchor entry.
Declare the research depth's scoping per proportionality. A significant risk
the brief did not anticipate is a stop condition: record it and hand off.
Write-time security pass (REQ-D1.6, security-posture)
When the diff touches a write-time trigger class — untrusted input, subprocess
or shell construction, path handling, authorization, crypto, or serialization —
run a focused security pass on that risk class before opening the PR, distinct
from the general review lens, with Research Rigor consulted. Apply artifact
data-hygiene to everything committed (brief, risk register, observations log, PR
body): no secrets, credentials, internal hostnames, or sensitive detail. Work in
a hard-disqualifier zone (security-sensitive code, migrations or destructive
ops, CI config, lockfiles, secrets files) follows the gate-wiring pause
protocol rather than landing autonomously.
Decision-domains drift triggers (REQ-G1.8, decision-domains)
When implementation is about to cross a catalogued decision domain the brief did
not decide, the drift trigger fires: if the brief or spec already decides it,
proceed citing that decision; otherwise research per stake, then recommend (a
low-stake, reversible call, considerations recorded) or escalate (a
load-bearing or hard-disqualifier-adjacent call) rather than auto-defaulting. A
decision in an uncatalogued domain writes an observation (the catalog grows
through the drain loop). The catalogued domains are the prose seed unioned with
adopter/team/machine-local additions via scripts/resolve-catalog.sh decision-domains (REQ-D1.1), so overlay domains trigger drift too. If
decision-domains did not resolve, note the skipped check and use engineering
judgment.
Run the full project CI (REQ-E1.2)
Run the command derived in pre-flight step 9. The full suite must pass before
convergence; capture its output.
Adaptive CI-failure handling (REQ-E1.2, D-25)
On a CI failure, classify it with scripts/classify-ci-failure.sh over the
captured output (it prints transient or logic; unknown patterns default to
logic):
transient (network/DNS errors, registry failures, rate limits,
timeouts): retry up to twice, waiting 30s before the first retry and 90s
before the second. A retry that goes green proceeds; if both still fail,
reclassify as logic and escalate.
logic (assertion mismatches, type/compile/syntax errors, lint/format
violations, test-runner failures): escalate immediately, never retried. Record
the failure with the full CI output to tasks.md Awaiting input and halt
(attended: surface and wait).
Convergence (REQ-E1.4, REQ-D1.3, D-39, D-6)
After CI passes, run the review sequence. The sequence is the
review_sequence config knob (D-6, REQ-D1.3): an ordered list of nestable
review-skill names, resolved through the four-layer config overlay. The default
is polish (today's /polish --nested convergence); an overlay can reorder or
extend it.
Resolve the sequence. Run scripts/resolve-review-sequence.sh (under the
resolved planwright root). It reads review_sequence through config-get
(REQ-D1.1), validates each name against the nestable-review-skill predicate,
applies the REQ-E1.4 by-layer malformed policy, and prints the validated ordered
names. By exit code:
- 0 — the printed names are the review sequence, in order. A stderr warning
may note an overlay was degraded to the core default; surface it but proceed.
- 4 — a repo-tracked overlay set a malformed value, or the repo-tracked
config is structurally malformed: a hard-fail stop condition — record to
tasks.md Awaiting input and halt.
- 5 — broken install (the core default is unresolvable): a stop
condition — halt and hand off.
Sync main first (merge-currency-guard REQ-B1.1, REQ-B1.4, D-4): once per
pass, before the first skill runs, run scripts/converge-sync-main.sh (under
the resolved planwright root); a non-zero exit halts the unit to Awaiting input
with the reason it printed. The sync changes the head a later ready-flip lands
on, never who flips.
Run each named skill in order, with --nested. Every review skill runs
--nested — it drains every action disposition per act-then-review and returns
its audit record without pushing or creating a PR (this skill's job, which is
why --nested is mandatory). The dispatch_isolation mode sets only where each
--nested call is hosted — per-unit in-session composition (REQ-E2.2,
D-13) or a fresh /resume-seeded per-step session — never the --nested
contract.
After each returns:
- Normal exit (converged, or handed off with queued forks): continue to the
next skill; once the sequence has run, proceed to PR creation, folding each
skill's audit record — the four bucket tables (per
finding-categorization),
the declined log, the pending-sign-off checklist, and any queued
Needs-human-judgment forks — into the PR body. One queued fork stops PR
creation: a meaning-class spec finding is contract drift, and the
meaning-class refusal below governs it.
- Safety stop (wider-suite failure, loop detection, iteration cap): the
branch may be known-broken. Surface the stop reason and halt; do not run later
review-sequence skills or open a PR over a broken branch.
- Hard-disqualifier finding a review-sequence skill surfaced but could not
resolve autonomously: a stop condition — hand off for human direction.
A convergence finding whose fix edits this spec's anchored content is an in-flight
amendment, never a direct edit: it takes the ritual below — the stale-anchor
pre-flight first, then the expression-only lane or the meaning-class refusal.
In-flight amendments (D-19, REQ-A3.3, REQ-F1.10)
If implementation or convergence reveals the spec itself needs an edit, the
meta-spec's writer prose (spec-format, Sign-off records and content
anchors) governs what this skill owes. Pre-flight first: before the first
edit, recompute the anchor with the brief's most recent recorded command; a
mismatch, an absent or unparseable entry, and a failed recompute each block the
edit alike — surface the condition instead of editing on top of it. A blocked
edit takes its disposition from its route: a convergence finding queues as an
irreducible fork routed to the anchor repair, folded into the PR body; an edit
this task's own implementation work revealed is a stop condition — record
the unit to tasks.md Awaiting input and halt. With the pre-flight clean,
classify the edit on the amendment axis:
- Expression-only (a typo, ambiguity, or gap-fill consistent with the
accepted decisions): fix it in place in one commit with a dated
## Changelog entry, and a marked self-re-anchor entry to the brief's
amendment log — Class: expression-only, citing the changelog line, anchor by
scripts/spec-anchor.sh specs/<spec> written last. This is the one anchor
entry an execution skill may write.
- Meaning-class (contradicts an accepted decision, alters a REQ's meaning,
or adds a REQ/D-ID): contract drift — do not edit the contract from
execution. Halt, surface the drift with the conflicting reading, and route the
human to a
/spec-kickoff delta re-walkthrough. There is no silent proceed.
PR creation (REQ-E1.5, D-21)
Push the branch: git push origin <branch> (with -u on first push).
New commits only — never force-push, amend, squash, or rebase (REQ-J1.4). On
push or gh auth failure, degrade gracefully (REQ-K1.6, REQ-K1.7): the local
work is committed; record an Awaiting-input note in tasks.md naming the
pending step and the failure, surface it, and stop. Never retry into an opaque
failure.
Open or update a draft PR. If a PR already exists for the branch, update
its body in place; otherwise gh pr create --draft with an explicit
--title and --body (headless gh prompts or fails without them). The
title is conventional and passes the PR-title lint
(scripts/check-commit-msgs.sh): feat(<scope>): <task title> or the fitting
type. Assemble the body per the PR-body assembly section of the
gate-wiring doctrine — the single normative home for the layout (D-2). This
skill supplies the summary inputs: the kickoff brief path
(specs/<spec>/kickoff-brief.md), the task IDs, the REQs satisfied (from the
task Citations:), the test additions and what they verify, and
implementation notes (key decisions). The audit record is the review
sequence's output: the four tables, declined log,
pending-sign-off checklist, and any queued forks. At PR review the human
approves each checklist item by leaving its commit, or rejects it with the
named revert.
The PR is always a draft. Never mark it ready and never merge.
Annotate the unit (v1 bundles only). On a format-version 2 bundle no
annotation exists to write — skip this step. Update only the task
block's - **Last activity:** <today> annotation; write no Status
line. Section placement is the tasks-pr-sync reconcile's sole job
(REQ-B1.1, D-1); the reconcile preserves annotations untouched and does not
author the Status text. Writing a PR #<N> draft Status here would race
the reconcile: the hook is fail-soft on a busy lock (a clean no-op), so the
block can still sit in ## Forward plan, an in-progress Status there being
exactly the section/status contradiction scripts/check-ledger.sh flags
(REQ-E1.1, REQ-E1.2).
Hand off. Report: the unit and spec, the freshness-gate result, tests
written and CI outcome, the convergence summary, the verified anchor, the
push/PR outcome (or degradation note), and what the human decides at PR review —
the pending-sign-off checklist and any queued forks. Apply artifact data-hygiene
to everything surfaced.
Stop conditions (mandatory human handoff)
Halt and hand back when any of these fires, recording the unit to tasks.md
Awaiting input with the reason (the pre-flight halt protocol above). Each is
described in full at its point of use:
- Spec not Ready or Active: pre-flight step 4 (Draft/Done/Retired/Superseded;
suggest
/spec-kickoff for Draft).
- Missing or erroring validator: pre-flight step 5.
- No or partial kickoff brief: pre-flight step 6.
- Freshness-gate halt: pre-flight step 7, which enumerates the cases.
- Dependency not completed: pre-flight step 8.
- Malformed
dispatch_isolation: pre-flight step 10 (exit 4/5).
- Test cannot fail for the right reason: test-first step 2.
- CI logic failure: a logic-classified failure, or transient retries
exhausted then reclassified.
- Research reveals an uncovered risk: one the brief did not anticipate.
- Contract drift: a meaning-class spec change is needed; route to
/spec-kickoff.
- Ambiguity in the task definition:
Done when: or Deliverables: admit
multiple valid interpretations.
- Hard-disqualifier finding in convergence: a review-sequence skill could
not resolve it.
gh not authenticated or push rejected: the PR step cannot reach GitHub;
local work is complete.
Invariants
These hold at every step:
- Never act on a spec whose status is neither Ready nor Active, and
never bypass the execution freshness gate that composes with it — no
bypass flag for either (REQ-C1.1, superseding REQ-J1.2, D-33; D-2, D-3,
REQ-F1.9, REQ-C1.3).
- Never create a non-draft PR, mark a PR ready, or merge — the draft→ready
flip and merge are the human's (D-21, REQ-J1.1).
- Never create a worktree; this skill runs inside one (D-37, D-44).
- Never invoke a
review_sequence skill (/polish by default) without
--nested: this skill owns push and PR creation (D-39, REQ-E1.4, REQ-D1.3).
- Never let
per-step isolation weaken state-safety: every tasks.md
placement move goes through the sibling reconcile under the per-spec lock, and
no step session opens a PR (REQ-C1.4).
- Never skip the test-first loop for a behavior-introducing unit with a
test-spec.md verification path (REQ-E1.1).
- Never retry a logic CI failure; transient retries cap at two; unknown
classifications default to logic (REQ-E1.2).
- Never silently proceed past a meaning-class contract drift; route to
/spec-kickoff (REQ-A3.3).
- Never write a meaning-class anchor entry; the only one this skill writes
is the marked
Class: expression-only self-re-anchor (REQ-F1.10).
- Never force-push, amend, squash, or rebase; new commits only (REQ-J1.4).
Observations
When something outside the unit's scope surfaces during implementation or
convergence (complexity growth, an outdated pattern, a newly available
dependency feature, an uncatalogued decision domain), record it as its own
fragment through the shared helper: scripts/obs-record.sh --slug <topic> --scope <repo> --text '<observation>' (resolved under the planwright root; it
writes one file under specs/_observations/entries/). Commit the fragment
within the iteration that produced it so the tree returns to clean; on a
non-zero helper exit, surface the failure rather than dropping it. Do not act on
observations during the unit; they are seed material for /spec-draft
(REQ-E2.1, REQ-H1.6).
Maintenance
After the run completes (or halts), compare these instructions against the
resolved doctrine docs (REQ-B3.2, D-42) — especially spec-format and
gate-wiring. If a concept this skill names changed meaning, gained or lost a
step, or moved between docs, record a drift observation via the shared helper
(scripts/obs-record.sh --slug skill-drift --scope <repo> --text 'skill-drift(execute-task): <what>', keeping the skill-drift(...) prefix),
commit it as its own chore commit, and tell the user. Do not edit this skill or
the doctrine docs to resolve the drift; /spec-draft owns folding drift into
spec amendments.
1---2name: execute-task3description: Implement one task (or a cohesion bundle) from a signed-off spec (Ready or Active): recompute the execution freshness gate, write the verifying test first, implement to green, run the project's full CI with adaptive retry, converge via the configured review_sequence (default /polish --nested), then open a draft PR referencing the brief, tasks, REQs, and tests. The execution workhorse of the planwright pipeline. Assumes the worktree already exists; never creates worktrees, never merges, never marks a PR ready.4---56# /execute-task78The execution layer of the planwright pipeline (REQ-E1.1–REQ-E1.5): take one9ready unit (a single task or a cohesion bundle) from a Ready or Active spec with10a signed-off kickoff brief and carry it from a failing test to a draft PR.11`/orchestrate` dispatches it into a prepared worktree; a human may also run it12inside one. It works from the kickoff13brief, the durable contract (D-3), not by re-reading the spec; sign-off and14merge are the human's two reserved controls (see Invariants).1516## Doctrine1718This skill is procedure, not doctrine. Read the manifest's rule docs via19`scripts/resolve-rule-doc.sh <doc-name>` (under the resolved planwright root);20their definitions govern the concepts this skill names. Per21`doctrine/instruction-hygiene.md`, `run-start` entries load before work begins,22`point-of-use` entries at the named step or branch.2324**Invoking plugin scripts (REQ-D1.1, D-7).** Call `scripts/<name>.sh` by the25**resolved literal absolute path**, never `$VAR/scripts/<name>.sh` —26`doctrine/plugin-script-invocation.md`.2728If a manifest doc does not resolve — at run start or its point of use — halt29naming the missing doc and the chain consulted (REQ-K1.7). `decision-domains`30degrades gracefully instead: absent, note it in one line, skip the drift check,31and use engineering judgment.3233Doctrine: run-start spec-format (status lifecycle, anchors, freshness gate)34Doctrine: run-start proportionality35Doctrine: point-of-use research-rigor36Doctrine: point-of-use security-posture37Doctrine: point-of-use validation-rigor38Doctrine: point-of-use finding-categorization39Doctrine: point-of-use gate-wiring40Doctrine: point-of-use decision-domains4142## Pre-flight4344Run once per invocation, in order. Any halt records the unit to the spec's45`tasks.md` `## Awaiting input` section with the reason — on a format-version 246bundle as a committed reference bullet, `**Task <id>** — <reason>`, the block47staying in `## Tasks` (a halting-skill human-payload write, D-3) — and ends the48step (the `gate-wiring` pause protocol's dispatched arm); attended, present and49wait instead.50511. **Parse `$ARGUMENTS`.** Extract one or more task IDs (`5`, `3.5`, or `5 6`52 for a bundle) and an optional spec path, given as either `specs/<spec>` or53 the bare `<spec>`. Validate each54 `<id>` against `^[0-9]+(\.[0-9]+)?$`, and the extracted `<spec>` against the55 anchored identifier pattern `^[a-z0-9][a-z0-9-]*$` (≤64 chars, REQ-A1.8)56 **before** it appears in any path or command; a failing token is never57 interpolated. No task ID: halt and ask which task to execute.582. **Resolve the spec path**, in order: (a) an explicit spec-path argument59 (`specs/<spec>` or bare `<spec>`, validated in step 1); (b) the branch name60 parsed against `planwright/<spec>/task-<ids>` (D-36); (c) the current61 checkout when it holds exactly one `specs/*/` bundle whose `Status:` is62 `Ready` or `Active`; (d) ask, listing the available bundles63 (underscore-prefixed accumulators are not bundles). Verify the directory64 holds `requirements.md`, `design.md`, `tasks.md`, and `test-spec.md`.653. **Resolve the run-start doctrine docs** (above); halt on a resolution66 failure. Point-of-use docs resolve at their named steps.674. **Verify the spec is Ready or Active** (REQ-C1.1, superseding the bootstrap68 non-Active refusal REQ-J1.2, D-33; kickoff-lifecycle D-2, D-3). Read the69 `**Status:**` line in `requirements.md`. `Ready` (signed off, no work70 started) and `Active` (work in flight) are both executable; refuse71 Draft, Done, Retired, and Superseded. The spec file **stays `Ready`** during72 execution: Ready↔Active is **derived, not stored** (D-2), written only by73 `orchestration-concurrency`'s single reconcile writer (D-3), so a task74 normally runs against a `Ready` spec, not the stored-`Active` demand this75 gate must not reintroduce. On **Draft**, halt and suggest76 `/spec-kickoff`; a terminal (Retired/Superseded) or Done spec has nothing to77 execute. A `Ready` spec runs on the same terms as Active: the freshness gate78 (step 7) still applies (REQ-C1.3); the two gates compose. There is no bypass79 flag.805. **Run the validator.** `scripts/spec-validate.sh specs/<spec>`. On this81 dispatch path a missing or non-executable validator fails closed and halts82 (REQ-K1.7). A Ready or Active bundle's findings are errors: surface them and83 halt.846. **Verify the kickoff brief.** `specs/<spec>/kickoff-brief.md` must exist and85 carry a final sign-off record with an anchor line (D-36). Absent, or partial86 (sections signed but no sign-off record, or a record without its anchor line87 — anchor-written-last makes a killed kickoff look absent, by design): halt88 and prompt `/spec-kickoff`.897. **Run the execution freshness gate** (REQ-F1.9, REQ-F1.10, D-45; the90 `spec-format` anchor rules; fleet-hardening D-9). It stops execution against91 content changed since sign-off and against a **stale local `main`**:92 - **Fetch-before-gate** (D-9, REQ-D1.1). Run `scripts/dispatch-fetch.sh93 --spec specs/<spec> <primary-checkout>`: it fetches `origin` (bounded, **no94 local-`main` advance**) and prints the fetched **`origin/main`** anchor95 (re-pointing `spec-anchor.sh`). Exit **0** → gate vs `origin/main`; **3**96 (`no-remote`, offline) → gate vs local `main`; **4** (`stale-transient`) or97 any other nonzero → do not silently proceed: park to Awaiting input.98 - **Validate the entry** (brief's most recent, from the resolved ref): it99 parses, uses a **sanctioned command form** (any form on `spec-format`'s100 *Sanctioned command forms* list), a **sanctioned writer** (a101 `/spec-kickoff` sign-off or the marked `Class: expression-only` ritual), and102 — meaning-class — a dispositioned `Lens-pass:`.103 - **Compare** the recorded anchor against the one `dispatch-fetch.sh`104 recomputed. **Match** → proceed. **Mismatch** → halt (remedy: a105 `/spec-kickoff` delta re-walkthrough). **No / unparseable / non-sanctioned /106 wrong-writer entry** → halt (repair the record per REQ-F1.10). A107 **pre-change entry** (predating the header-`**Status:**` exclusion, or108 whole-file form) mismatches over unedited content; remedy: the one-time109 classify-then-self-re-anchor. Halts go to110 Awaiting input; no bypass flag.1118. **Read the brief slice and task block(s).** From the brief: the signed-off112 goal restatement, the task graph, and the unit's risk entries. From113 `tasks.md`: each114 block's `Deliverables`, `Done when`, `Dependencies`, and `Citations`. Confirm115 every dependency is completed — on a v1 bundle it sits in `## Completed`; on a116 v2 bundle it derives Completed via the derivation engine117 (`scripts/orchestrate-state.sh`); if one is not, halt naming it.1189. **Derive the full-CI command** (D-19). Pick the most comprehensive guard the119 repo ships, checking in order: a `mise.toml` aggregate task (planwright's own120 is `mise run check`); a `package.json` `ci`/`test` script; a `Makefile`121 `ci`/`test` target; a `lefthook.yml` `pre-commit` stack; a language122 toolchain's check. Prefer the aggregate over a bare test run. If none can be123 derived, ask.12410. **Resolve `dispatch_isolation`** (D-5, REQ-C1.3). Run125 `scripts/resolve-dispatch-isolation.sh` (under the resolved planwright root)126 to read the knob through the four-layer overlay; it prints `per-step` (the127 assigned-decision default) or `per-unit` and applies the REQ-E1.4 by-layer128 malformed policy. A hard-fail (exit 4 — a malformed team-shared value or129 config; exit 5 — a broken install whose core default is unresolvable) is a130 **stop condition**: record to `tasks.md` Awaiting input and halt. A131 warn+degrade (an adopter/machine-local value degraded to the core default,132 exit 0) proceeds. Record the mode; it governs how Implementation and133 Convergence host this unit's steps (see *Step isolation*).13411. **Update Last activity (v1); write no placement or `Status`.** On a135 format-version 2 bundle this step writes nothing — a v2 block carries no136 annotations, and derived execution state never produces commits (version137 keying, here and throughout this skill, reads the declared `Format-version:`138 as the scripts do; unparseable fails closed, never the v1 arm — D-7). On v1:139 the dispatch record (task branch + runtime marker) already makes the unit140 derivable as In progress, so write **no** section placement and **no**141 `Status` line (REQ-B1.1, D-1); a142 block still in `## Forward plan` while its branch is in flight is intentional143 snapshot lag, not corruption (REQ-B1.2). The only edit is the block's144 `- **Last activity:** <today>` annotation, anchor-excluded (`spec-format`145 canonical extraction) and not a `Status` line, so it trips neither146 corruption guard (full race rationale at PR step 3). Commit it when147 `commit_on_state_move` is true (read `config/defaults.yml` overridden by148 `<repo>/.claude/planwright.local.yml`, local wins; absent/malformed falls149 back to the default with a one-line warning).150151## Implementation152153### Step isolation (`dispatch_isolation`, REQ-C1.3, REQ-C1.4, D-5)154155The mode resolved in pre-flight step 10 governs how this unit's **steps** — the156implementation phase (test-first loop, research, security pass, CI), then each157`review_sequence` skill — are **hosted**. It changes hosting, not work or order.158159- **`per-unit`** (strictly preserved): the whole unit runs in **one session** —160 implement, run CI, invoke each `review_sequence` skill inline with `--nested`,161 then push and open the PR. Context carries across steps.162- **`per-step`** (the assigned-decision default): each step runs in its **own163 fresh session**, seeded by `/resume` from durable state alone (brief,164 `tasks.md` snapshot, git log, open PR), so context stays bounded and each165 review's perspective is uncontaminated by prior steps. Each step commits its166 work with the `Planwright-Task:` trailer. Realization is167 the backend's job (D-2): a session-grade backend spawns a session per step; the168 terminal rung (D-3) approximates it with a context clear + `/resume` reseed; a169 backend doing neither degrades to `per-unit` (degrade capability, never170 safety).171172**Launch tier.** A per-step session is a launch: resolve173`scripts/allocation-apply.sh plan --key execute_step --backend <backend> --unit174<spec>:task-<id> --step <step>` and apply per `backend-capability-contract`'s175*Applying a resolved tier*. Exit 3 is withheld: do not launch; only exit 6176degrades. The terminal rung advertises none, inheriting the operator's177session.178179**State-safety holds in both modes (REQ-C1.4):** every `tasks.md` placement move180goes **only** through the sibling reconcile under the per-spec lock, no per-step181session writes dispatch/progress state or opens a PR — push and PR creation182remain this skill's single terminal step (see Invariants).183184### Commit convention (REQ-C1.4, D-2)185186Every commit this skill authors for the unit (test-first action commits, the187observation chore commit, any expression-only amendment commit) carries a188`Planwright-Task: <spec>/<id>` footer trailer: the durable completion anchor the189orchestration-state derivation reads by scanning the whole commit message, so it190survives a squash/rebase merge, branch deletion, and direct-to-`main` commits.191Stamp it through the shared helper, not by hand, so it is grammar-validated and192identical everywhere:193194```sh195printf '%s\n' "$message" \196 | scripts/planwright-commit-trailers.sh <spec>/<id> \197 | git commit -F -198```199200For a **bundle**, pass one ref per task (`… <spec>/<id1> <spec>/<id2> …`); the201helper emits one trailer per task. The trailer is footer-only and additive — no202subject-line change, no Claude/co-author attribution — so the no-attribution203rule is unaffected.204205### Test-first development (REQ-E1.1, `validation-rigor`)206207Read `test-spec.md` for the unit's cited REQs first: each entry describes the208verification path — what to test and which edge cases matter. Then, for every209piece of new behavior or bug fix the unit introduces:2102111. **Write the test**, grounded in the `test-spec.md` entry and the `Done when:`212 conditions. It must be specific enough to fail for the intended reason and213 pass only when the implementation is correct.2142. **Run it and confirm it fails for the right reason** — the failure message215 corresponds to the behavior being implemented, not a syntax, import, or216 unrelated error. A test that passes immediately, or fails for the wrong217 reason and cannot be isolated, is a stop condition.2183. **Implement** to make the test pass, consulting the brief's goal restatement219 and risk register.2204. **Confirm the test passes** — the same test, unchanged. Iterate on the221 implementation, never the test.222223Validate the solution per `validation-rigor`: the targeted test, the wider224project suite (the CI step below), and the altitude check (fix the cause at the225right layer, not the symptom). A unit that is purely configuration,226documentation, or infrastructure with no testable behavior per `test-spec.md`227skips the loop; note in the PR body why no test was added.228229### Research Rigor (REQ-D1.5, `research-rigor`)230231Research fires **before** implementation when a trigger holds — a new232dependency, an unfamiliar domain, a security-touching pattern, a233version-sensitive API, or a "how do mature projects do this" question. Consult234current sources in order (official docs for the pinned version, then the235library's own source and tests, then issues/RFCs), honor recency over model236memory, and run the antipattern check before adopting a pattern. **Record** the237findings, tradeoffs, and sources in the brief's **risk register**, appended to a238named section — never overwriting existing rows, never as an anchor entry.239Declare the research depth's scoping per `proportionality`. A significant risk240the brief did not anticipate is a stop condition: record it and hand off.241242### Write-time security pass (REQ-D1.6, `security-posture`)243244When the diff touches a write-time trigger class — untrusted input, subprocess245or shell construction, path handling, authorization, crypto, or serialization —246run a focused security pass on that risk class before opening the PR, distinct247from the general review lens, with Research Rigor consulted. Apply artifact248data-hygiene to everything committed (brief, risk register, observations log, PR249body): no secrets, credentials, internal hostnames, or sensitive detail. Work in250a hard-disqualifier zone (security-sensitive code, migrations or destructive251ops, CI config, lockfiles, secrets files) follows the `gate-wiring` pause252protocol rather than landing autonomously.253254### Decision-domains drift triggers (REQ-G1.8, `decision-domains`)255256When implementation is about to cross a catalogued decision domain the brief did257not decide, the drift trigger fires: if the brief or spec already decides it,258proceed citing that decision; otherwise research per stake, then recommend (a259low-stake, reversible call, considerations recorded) or **escalate** (a260load-bearing or hard-disqualifier-adjacent call) rather than auto-defaulting. A261decision in an uncatalogued domain writes an **observation** (the catalog grows262through the drain loop). The catalogued domains are the prose seed unioned with263adopter/team/machine-local additions via `scripts/resolve-catalog.sh264decision-domains` (REQ-D1.1), so overlay domains trigger drift too. If265`decision-domains` did not resolve, note the skipped check and use engineering266judgment.267268### Run the full project CI (REQ-E1.2)269270Run the command derived in pre-flight step 9. The full suite must pass before271convergence; capture its output.272273### Adaptive CI-failure handling (REQ-E1.2, D-25)274275On a CI failure, classify it with `scripts/classify-ci-failure.sh` over the276captured output (it prints `transient` or `logic`; unknown patterns default to277`logic`):278279- **`transient`** (network/DNS errors, registry failures, rate limits,280 timeouts): retry up to twice, waiting 30s before the first retry and 90s281 before the second. A retry that goes green proceeds; if both still fail,282 reclassify as logic and escalate.283- **`logic`** (assertion mismatches, type/compile/syntax errors, lint/format284 violations, test-runner failures): escalate immediately, never retried. Record285 the failure with the full CI output to `tasks.md` Awaiting input and halt286 (attended: surface and wait).287288## Convergence (REQ-E1.4, REQ-D1.3, D-39, D-6)289290After CI passes, run the **review sequence**. The sequence is the291`review_sequence` config knob (D-6, REQ-D1.3): an ordered list of nestable292review-skill names, resolved through the four-layer config overlay. The default293is `polish` (today's `/polish --nested` convergence); an overlay can reorder or294extend it.295296**Resolve the sequence.** Run `scripts/resolve-review-sequence.sh` (under the297resolved planwright root). It reads `review_sequence` *through* `config-get`298(REQ-D1.1), validates each name against the nestable-review-skill predicate,299applies the REQ-E1.4 by-layer malformed policy, and prints the validated ordered300names. By exit code:301302- **0** — the printed names are the review sequence, in order. A stderr warning303 may note an overlay was degraded to the core default; surface it but proceed.304- **4** — a repo-tracked overlay set a malformed value, or the repo-tracked305 config is structurally malformed: a hard-fail **stop condition** — record to306 `tasks.md` Awaiting input and halt.307- **5** — broken install (the core default is unresolvable): a **stop308 condition** — halt and hand off.309310**Sync `main` first** (merge-currency-guard REQ-B1.1, REQ-B1.4, D-4): once per311pass, before the first skill runs, run `scripts/converge-sync-main.sh` (under312the resolved planwright root); a non-zero exit halts the unit to Awaiting input313with the reason it printed. The sync changes the head a later ready-flip lands314on, never who flips.315316**Run each named skill in order, with `--nested`.** Every review skill runs317`--nested` — it drains every action disposition per act-then-review and returns318its audit record without pushing or creating a PR (this skill's job, which is319why `--nested` is mandatory). The `dispatch_isolation` mode sets only where each320`--nested` call is **hosted** — `per-unit` in-session composition (REQ-E2.2,321D-13) or a fresh `/resume`-seeded `per-step` session — never the `--nested`322contract.323324After each returns:325326- **Normal exit** (converged, or handed off with queued forks): continue to the327 next skill; once the sequence has run, proceed to PR creation, folding each328 skill's audit record — the four bucket tables (per `finding-categorization`),329 the declined log, the pending-sign-off checklist, and any queued330 Needs-human-judgment forks — into the PR body. One queued fork stops PR331 creation: a meaning-class spec finding is contract drift, and the332 meaning-class refusal below governs it.333- **Safety stop** (wider-suite failure, loop detection, iteration cap): the334 branch may be known-broken. Surface the stop reason and halt; do not run later335 review-sequence skills or open a PR over a broken branch.336- **Hard-disqualifier finding** a review-sequence skill surfaced but could not337 resolve autonomously: a stop condition — hand off for human direction.338339**A convergence finding whose fix edits this spec's anchored content** is an in-flight340amendment, never a direct edit: it takes the ritual below — the stale-anchor341pre-flight first, then the expression-only lane or the meaning-class refusal.342343## In-flight amendments (D-19, REQ-A3.3, REQ-F1.10)344345If implementation or convergence reveals the spec itself needs an edit, the346meta-spec's writer prose (`spec-format`, *Sign-off records and content347anchors*) governs what this skill owes. **Pre-flight first:** before the first348edit, recompute the anchor with the brief's most recent recorded command; a349mismatch, an absent or unparseable entry, and a failed recompute each block the350edit alike — surface the condition instead of editing on top of it. A blocked351edit takes its disposition from its route: a convergence finding queues as an352irreducible fork routed to the anchor repair, folded into the PR body; an edit353this task's own implementation work revealed is a **stop condition** — record354the unit to `tasks.md` Awaiting input and halt. With the pre-flight clean,355classify the edit on the amendment axis:356357- **Expression-only** (a typo, ambiguity, or gap-fill consistent with the358 accepted decisions): fix it in place in **one commit** with a dated359 `## Changelog` entry, and a **marked self-re-anchor entry** to the brief's360 amendment log — `Class: expression-only`, citing the changelog line, anchor by361 `scripts/spec-anchor.sh specs/<spec>` written last. This is the one anchor362 entry an execution skill may write.363- **Meaning-class** (contradicts an accepted decision, alters a REQ's meaning,364 or adds a REQ/D-ID): **contract drift** — do not edit the contract from365 execution. Halt, surface the drift with the conflicting reading, and route the366 human to a `/spec-kickoff` delta re-walkthrough. There is no silent proceed.367368## PR creation (REQ-E1.5, D-21)3693701. **Push the branch:** `git push origin <branch>` (with `-u` on first push).371 New commits only — never force-push, amend, squash, or rebase (REQ-J1.4). On372 push or `gh` auth failure, degrade gracefully (REQ-K1.6, REQ-K1.7): the local373 work is committed; record an Awaiting-input note in `tasks.md` naming the374 pending step and the failure, surface it, and stop. Never retry into an opaque375 failure.3762. **Open or update a draft PR.** If a PR already exists for the branch, update377 its body in place; otherwise `gh pr create --draft` with an explicit378 `--title` and `--body` (headless `gh` prompts or fails without them). The379 title is conventional and passes the PR-title lint380 (`scripts/check-commit-msgs.sh`): `feat(<scope>): <task title>` or the fitting381 type. Assemble the body per the **PR-body assembly** section of the382 `gate-wiring` doctrine — the single normative home for the layout (D-2). This383 skill supplies the summary inputs: the kickoff brief path384 (`specs/<spec>/kickoff-brief.md`), the task IDs, the REQs satisfied (from the385 task `Citations:`), the test additions and what they verify, and386 implementation notes (key decisions). The audit record is the review387 sequence's output: the four tables, declined log,388 pending-sign-off checklist, and any queued forks. At PR review the human389 approves each checklist item by leaving its commit, or rejects it with the390 named revert.391392 The PR is always a draft. Never mark it ready and never merge.3933. **Annotate the unit (v1 bundles only).** On a format-version 2 bundle no394 annotation exists to write — skip this step. Update only the task395 block's `- **Last activity:** <today>` annotation; write **no** `Status`396 line. Section placement is the `tasks-pr-sync` reconcile's sole job397 (REQ-B1.1, D-1); the reconcile preserves annotations untouched and does not398 author the `Status` text. Writing a `PR #<N> draft` Status here would race399 the reconcile: the hook is fail-soft on a busy lock (a clean no-op), so the400 block can still sit in `## Forward plan`, an in-progress `Status` there being401 exactly the section/status contradiction `scripts/check-ledger.sh` flags402 (REQ-E1.1, REQ-E1.2).403404**Hand off.** Report: the unit and spec, the freshness-gate result, tests405written and CI outcome, the convergence summary, the verified anchor, the406push/PR outcome (or degradation note), and what the human decides at PR review —407the pending-sign-off checklist and any queued forks. Apply artifact data-hygiene408to everything surfaced.409410## Stop conditions (mandatory human handoff)411412Halt and hand back when any of these fires, recording the unit to `tasks.md`413Awaiting input with the reason (the pre-flight halt protocol above). Each is414described in full at its point of use:415416- **Spec not Ready or Active:** pre-flight step 4 (Draft/Done/Retired/Superseded;417 suggest `/spec-kickoff` for Draft).418- **Missing or erroring validator:** pre-flight step 5.419- **No or partial kickoff brief:** pre-flight step 6.420- **Freshness-gate halt:** pre-flight step 7, which enumerates the cases.421- **Dependency not completed:** pre-flight step 8.422- **Malformed `dispatch_isolation`:** pre-flight step 10 (exit 4/5).423- **Test cannot fail for the right reason:** test-first step 2.424- **CI logic failure:** a logic-classified failure, or transient retries425 exhausted then reclassified.426- **Research reveals an uncovered risk:** one the brief did not anticipate.427- **Contract drift:** a meaning-class spec change is needed; route to428 `/spec-kickoff`.429- **Ambiguity in the task definition:** `Done when:` or `Deliverables:` admit430 multiple valid interpretations.431- **Hard-disqualifier finding in convergence:** a review-sequence skill could432 not resolve it.433- **`gh` not authenticated or push rejected:** the PR step cannot reach GitHub;434 local work is complete.435436## Invariants437438These hold at every step:439440- **Never** act on a spec whose status is neither Ready nor Active, and441 **never** bypass the execution freshness gate that composes with it — no442 bypass flag for either (REQ-C1.1, superseding REQ-J1.2, D-33; D-2, D-3,443 REQ-F1.9, REQ-C1.3).444- **Never** create a non-draft PR, mark a PR ready, or merge — the draft→ready445 flip and merge are the human's (D-21, REQ-J1.1).446- **Never** create a worktree; this skill runs inside one (D-37, D-44).447- **Never** invoke a `review_sequence` skill (`/polish` by default) without448 `--nested`: this skill owns push and PR creation (D-39, REQ-E1.4, REQ-D1.3).449- **Never** let `per-step` isolation weaken state-safety: every `tasks.md`450 placement move goes through the sibling reconcile under the per-spec lock, and451 no step session opens a PR (REQ-C1.4).452- **Never** skip the test-first loop for a behavior-introducing unit with a453 `test-spec.md` verification path (REQ-E1.1).454- **Never** retry a logic CI failure; transient retries cap at two; unknown455 classifications default to logic (REQ-E1.2).456- **Never** silently proceed past a meaning-class contract drift; route to457 `/spec-kickoff` (REQ-A3.3).458- **Never** write a meaning-class anchor entry; the only one this skill writes459 is the marked `Class: expression-only` self-re-anchor (REQ-F1.10).460- **Never** force-push, amend, squash, or rebase; new commits only (REQ-J1.4).461462## Observations463464When something outside the unit's scope surfaces during implementation or465convergence (complexity growth, an outdated pattern, a newly available466dependency feature, an uncatalogued decision domain), record it as its own467fragment through the shared helper: `scripts/obs-record.sh --slug <topic>468--scope <repo> --text '<observation>'` (resolved under the planwright root; it469writes one file under `specs/_observations/entries/`). Commit the fragment470within the iteration that produced it so the tree returns to clean; on a471non-zero helper exit, surface the failure rather than dropping it. Do not act on472observations during the unit; they are seed material for `/spec-draft`473(REQ-E2.1, REQ-H1.6).474475## Maintenance476477After the run completes (or halts), compare these instructions against the478resolved doctrine docs (REQ-B3.2, D-42) — especially `spec-format` and479`gate-wiring`. If a concept this skill names changed meaning, gained or lost a480step, or moved between docs, record a drift observation via the shared helper481(`scripts/obs-record.sh --slug skill-drift --scope <repo> --text482'skill-drift(execute-task): <what>'`, keeping the `skill-drift(...)` prefix),483commit it as its own chore commit, and tell the user. Do not edit this skill or484the doctrine docs to resolve the drift; `/spec-draft` owns folding drift into485spec amendments.