x-internal-verify-phase-gates
Validates phase transitions for orchestrators under Rule 25. Four modes: --mode pre (assert predecessor phases completed before entering phase N), --mode post (assert all child tasks of phase N are completed AND all expected artifacts exist on disk), --mode wave (post-Batch-B verification of parallel wave completeness: N child TaskUpdate completed + N artifacts exist), --mode final (terminal gate composing with x-internal-verify-epic-integrity). Reads execution-state.json.taskTracking.phaseGateResults and TaskList task state; writes back the gate result. Emits a single-line JSON envelope {passed, mode, skill, phase, expectedTasks, completedTasks, missingTasks, expectedArtifacts, missingArtifacts, wallclockMs, timestamp}. Exit 0 on passed, 12 on failure, 13 on malformed args, 14 on task-resolution timeout. First skill in the x-internal-* convention authored by EPIC-0055; eighth overall (after status-update, report-write, args-normalize, story-load-context, story-build-plan, story-verify, story-resume, epic-build-plan, epic-integrity-gate, epic-branch-ensure, story-report) and the eighth under internal/plan/.
- License 许可
- MIT
- 最近更新
- 2026-10-27
- Stars
- ★ 0
- Forks
- 1
01 前言 Front Matter
- name
- x-internal-verify-phase-gates
- model
- haiku
- category
- internal-plan
- visibility
- internal
- description
- Validates phase transitions for orchestrators under Rule 25. Four modes: --mode pre (assert predecessor phases completed before entering phase N), --mode post (assert all child tasks of phase N are completed AND all expected artifacts exist on disk), --mode wave (post-Batch-B verification of parallel wave completeness: N child TaskUpdate completed + N artifacts exist), --mode final (terminal gate composing with x-internal-verify-epic-integrity). Reads execution-state.json.taskTracking.phaseGateResults and TaskList task state; writes back the gate result. Emits a single-line JSON envelope {passed, mode, skill, phase, expectedTasks, completedTasks, missingTasks, expectedArtifacts, missingArtifacts, wallclockMs, timestamp}. Exit 0 on passed, 12 on failure, 13 on malformed args, 14 on task-resolution timeout. First skill in the x-internal-* convention authored by EPIC-0055; eighth overall (after status-update, report-write, args-normalize, story-load-context, story-build-plan, story-verify, story-resume, epic-build-plan, epic-integrity-gate, epic-branch-ensure, story-report) and the eighth under internal/plan/.
- allowed-tools
- Read, Bash
- argument-hint
- --mode pre|post|wave|final [--skill <name>] [--phase <Phase N>] [--parent-task-id <id>] [--expected-tasks id1,id2] [--expected-artifacts path1,path2] [--timeout-s <N>] [--emit-tracker true|false] [--state-file ai/epics/epic-XXXX/execution-state.json]
- context-budget
- medium
- user-invocable
- false
- requires-capabilities
- []
02 资源文件 1
- 参考文档references/full-protocol.md8.0 KB
03 SKILL.md 正文
Global Output Policy
- Language: English ONLY.
- Tone: Technical, Direct, and Concise.
- Efficiency: Remove all conversational fillers and greetings to save tokens.
🔒 INTERNAL SKILL Esta skill é invocada apenas por outras skills (orquestradores). NÃO é destinada a invocação direta pelo usuário. Callers principais:
x-implement-epic,x-implement-story,x-implement-task,x-release,x-orchestrate-epic,x-review-codebase,x-review-pr,x-manage-pr-merge-train(após retrofits em stories 0055-0003 a 0055-0010). Oitava skill no subdirinternal/plan/(apósx-internal-load-story-context,x-internal-build-story-plan,x-internal-verify-story,x-internal-resume-story,x-internal-build-epic-plan,x-internal-verify-epic-integrity,x-internal-write-story-report). Primeira skill introduzida por EPIC-0055.
Skill: x-internal-verify-phase-gates
Purpose
Validates phase transitions in orchestrators governed by Rule 25. A phase gate is a synchronous, fail-fast check that runs around each numbered ## Phase N section: a PRE gate ensures the predecessor phases are cleanly completed; a POST gate ensures every child task of the current phase is completed AND every artifact the phase was supposed to produce exists on disk. Rule 25 moves enforcement from "Stop hook notices afterwards" (Rule 24 defense-in-depth) to sync gate before the phase is marked completed — missing tasks or artifacts abort the lifecycle with exit 12.
Responsibilities (single):
- Parse arguments against the 4-mode matrix (
pre/post/wave/final). - For PRE mode: scan predecessor phases'
phaseGateResultsinexecution-state.jsonandTaskListfor any non-completedsibling task. - For POST / WAVE / FINAL mode: intersect
--expected-tasksagainstTaskListlooking forcompletedstatus on each, ANDstat-check every path in--expected-artifacts. - Atomically append a
phaseGateResults[]entry toexecution-state.json.taskTrackingviax-internal-update-status(delegated). - Emit a single-line JSON envelope on stdout.
- Translate every failure class to the exit-code catalogue.
Non-responsibilities (explicit):
- Does NOT mutate task state (no
TaskUpdate(status: ...)). The caller owns task state transitions. - Does NOT run the PostToolUse hook. The hook (
verify-phase-gates.sh, story-0055-0002) readsphaseGateResults[]this skill writes. - Does NOT emit
TaskCreateunless--mode wave --emit-tracker trueis set (Rule 25 Invariant 6 exception — one tracker task to surface wave wall-clock). - Does NOT run tests, build, or any project-level validation.
x-internal-verify-story/x-internal-verify-epic-integrityown those — this gate composes with them via--mode final.
Convention Anchors (x-internal-* — EPIC-0055)
| Aspect | Value | Rationale |
|---|---|---|
| Path | internal/plan/x-internal-verify-phase-gates/ |
Read-and-compute carve-out, co-located with other story/epic gate skills. |
Frontmatter visibility |
internal |
Generator filters from /help menu. |
Frontmatter user-invocable |
false |
Declarative complement. |
Frontmatter model |
haiku |
Zero-reasoning lookup (RULE-023 utility tier). |
| Body marker | > 🔒 **INTERNAL SKILL** |
Rule 22 §Body marker. |
| Allowed tools | Read, Bash |
Read for artifact stat; Bash for jq + state-file I/O via x-internal-update-status. |
Triggers
Bare-slash form intentionally omitted — never invoked by a user. All invocations follow Rule 13 Pattern 1 (INLINE-SKILL):
Skill(skill: "x-internal-verify-phase-gates",
args: "--mode pre --skill x-implement-story --phase Phase-1 --state-file ai/epics/epic-XXXX/execution-state.json")
Skill(skill: "x-internal-verify-phase-gates",
args: "--mode post --skill x-implement-story --phase Phase-1 --expected-tasks 101,102,103,104,105,106 --expected-artifacts ai/epics/epic-XXXX/plans/arch-story-0060-0001.md,ai/epics/epic-XXXX/plans/plan-story-0060-0001.md --state-file ai/epics/epic-XXXX/execution-state.json")
Skill(skill: "x-internal-verify-phase-gates",
args: "--mode wave --skill x-review-codebase --phase Phase-2 --expected-tasks 201,202,203,204,205,206,207,208,209 --state-file ai/epics/epic-XXXX/execution-state.json")
Parameters
| Flag | Required | Default | Description |
|---|---|---|---|
--mode <tier> |
M | — | One of pre, post, wave, final. Case-insensitive; normalized to lowercase. |
--skill <name> |
M | — | Calling orchestrator name (recorded in the envelope and state file). |
--phase <Phase N> |
M | — | Exact phase label (matches ## Phase N — Name header). |
--parent-task-id <id> |
O | — | Integer ID of the parent TaskCreate that owns the phase. Used to discover children via TaskList. |
--expected-tasks <ids> |
O | — | Comma-separated integer task IDs the gate must see as completed. Required for post, wave, final. |
--expected-artifacts <paths> |
O | — | Comma-separated relative paths that MUST exist on disk. Required for post and final. Optional for wave. |
--timeout-s <N> |
O | 10 |
Integer seconds to retry-poll if any --expected-tasks is still in_progress. Exceeded → exit 14. |
--emit-tracker <bool> |
O | false |
Only legal with --mode wave. Emits a single tracker TaskCreate with subject = <skill> › <phase> › wave-tracker for CLI visibility. |
--state-file <path> |
O | auto | Path to execution-state.json. Auto-derived from $CWD/ai/epics/epic-XXXX/execution-state.json when epic is unambiguous. |
Response Contract
On success (exit 0) and on failure (exit 12) the skill writes a single-line JSON object to stdout:
| Field | Type | Always Present | Description |
|---|---|---|---|
passed |
Boolean |
yes | true when all checks passed. |
mode |
String |
yes | Echo of --mode. |
skill |
String |
yes | Echo of --skill. |
phase |
String |
yes | Echo of --phase. |
expectedTasks |
Array<Integer> |
yes | Echo of --expected-tasks ([] if absent). |
completedTasks |
Array<Integer> |
yes | Subset of expectedTasks confirmed completed in TaskList. |
missingTasks |
Array<Integer> |
yes | expectedTasks \ completedTasks. Empty when passed=true. |
expectedArtifacts |
Array<String> |
yes | Echo of --expected-artifacts. |
missingArtifacts |
Array<String> |
yes | Subset of expectedArtifacts that do NOT exist on disk. Empty when passed=true. |
wallclockMs |
Integer |
yes | Gate execution time in milliseconds (monotonic clock). |
timestamp |
String (ISO-8601) |
yes | Gate completion timestamp in UTC. |
The envelope shape is authoritative. phaseGateResults[] in execution-state.json receives a slim projection: {phase, mode, passed, missingArtifacts, missingTasks, timestamp}.
Exit Codes
| Code | Name | Condition |
|---|---|---|
| 0 | OK |
passed=true |
| 12 | PHASE_GATE_FAILED |
passed=false — at least one missing task or missing artifact |
| 13 | PHASE_GATE_MALFORMED |
Unknown flag, missing required flag, --emit-tracker true without --mode wave, --expected-tasks on --mode pre, etc. |
| 14 | PHASE_GATE_TIMEOUT |
An expected task is still in_progress after --timeout-s seconds of polling |
| 64 | EX_USAGE |
--mode value not in {pre, post, wave, final} or --phase fails Rule-25 subject regex |
No partial-success state: the first non-recoverable error aborts the run and yields a non-zero exit.
Workflow
Step 1 — Arg parse + validation
Parse arguments with the shared Rule-14 while (($#)) loop. Normalize --mode to lowercase. Validate:
--mode ∈ {pre, post, wave, final}— else exit 64.--phasematches Rule-25 subject regex — else exit 64.- For
--mode post|wave|final:--expected-tasksMUST be present. - For
--mode post|final:--expected-artifactsMUST be present. - For
--mode pre:--expected-tasks/--expected-artifactsMUST be absent (checks come from state file only) — else exit 13. --emit-tracker truerequires--mode wave— else exit 13.
Step 2 — Resolve --state-file
When --state-file absent, search upward from $PWD for ai/epics/epic-*/execution-state.json. Exactly one match → proceed. Zero or multiple → exit 13 with STATE_FILE_AMBIGUOUS.
Step 3 — Short-circuit on taskTracking.enabled=false
Read taskTracking.enabled from the state file. Default is true when the field is absent (Rule 19 fallback). Only when the value is explicitly false, emit:
{"passed":true,"mode":"<mode>","skill":"<skill>","phase":"<phase>","expectedTasks":[],"completedTasks":[],"missingTasks":[],"expectedArtifacts":[],"missingArtifacts":[],"wallclockMs":<N>,"timestamp":"<t>","note":"taskTracking disabled (legacy mode)"}
and exit 0. This is the Rule-19 backward-compat path — legacy epics treat gates as no-ops.
Step 4 — Mode-specific validation
4a. --mode pre
Read execution-state.json.taskTracking.phaseGateResults[]. Let N = int(phase.replace("Phase-","")). For every k ∈ [0, N-1], at least one entry with phase="Phase-k" AND mode="post" AND passed=true MUST be present. Missing entries → missingTasks=[<Phase-k-placeholder>], passed=false, exit 12.
No artifact checks in PRE mode.
4b. --mode post
- Tasks: For each
id ∈ --expected-tasks, retrieve its status. UseTaskListvia Bash (e.g., reading from~/.claude/state/tasks/<session>/tasks.jsonwhen available, falling back toexecution-state.json.taskTracking.taskIndex[]).completed→ add tocompletedTasks; else add tomissingTasks. If any task isin_progress, poll every 500ms up to--timeout-s; persistent → exit 14. - Artifacts: For each
path ∈ --expected-artifacts,[[ -e "$path" ]]— present → drop; absent → append tomissingArtifacts. passed = missingTasks.isEmpty() && missingArtifacts.isEmpty().
4c. --mode wave
Same as POST, but:
- Semantics: ALL wave members must be
completedsimultaneously (no ordering assumption). --expected-artifactsis optional — waves that only produce task commits (no files) are valid.- When
--emit-tracker true, emit exactly oneTaskCreate(subject: "<skill> › <phase> › wave-tracker")upfront andTaskUpdate(status: "completed")at the end, regardless of result.
4d. --mode final
Superset of POST. Additionally scans the Rule-24 mandatory artifact set (when --skill = x-implement-story): verify-envelope, review-story, techlead-review, story-completion-report. Acts as the synchronous Rule-24 gate the Stop-hook normally enforces asynchronously.
Step 5 — Write phaseGateResults[] entry
Atomically append to execution-state.json.taskTracking.phaseGateResults[] via:
Skill(skill: "x-internal-update-status",
args: "--file <state-file> --type phase-gate --phase <phase> --mode <mode> --passed <true|false> --missing-artifacts <comma-list> --missing-tasks <comma-list>")
The status-update skill owns the flock-protected read-modify-write.
Step 6 — Emit envelope
Single-line JSON via jq -nc with all fields. Exit 0 on success, 12 on failure.
Idempotency Contract
The skill is idempotent by design:
- Re-invoking the same gate (same
--mode,--skill,--phase) is a replay: it re-reads task state + artifact state, writes a freshphaseGateResults[]entry, and returns the current result. Previous entries remain for audit history. - Concurrent invocations serialize on
x-internal-update-status's flock (file-level).
Performance Contract
| Mode | Budget |
|---|---|
pre |
< 50ms (single file read + jq projection) |
post |
< 100ms + artifact stat × N (usually < 150ms total) |
wave |
same as post |
final |
< 200ms (adds Rule-24 scan) |
Target global overhead across an epic with ~30 gates: < 5 seconds, i.e., well below the EPIC-0055 DoD threshold of "< 2% wall-clock overhead".
Examples
Example 1 — Happy path, PRE mode
Skill(skill: "x-internal-verify-phase-gates",
args: "--mode pre --skill x-implement-story --phase Phase-2 --state-file ai/epics/epic-XXXX/execution-state.json")
Output:
{"passed":true,"mode":"pre","skill":"x-implement-story","phase":"Phase-2","expectedTasks":[],"completedTasks":[],"missingTasks":[],"expectedArtifacts":[],"missingArtifacts":[],"wallclockMs":12,"timestamp":"2026-04-24T10:30:00Z"}
Exit: 0.
Example 2 — POST mode all green
Skill(skill: "x-internal-verify-phase-gates",
args: "--mode post --skill x-implement-story --phase Phase-1 --expected-tasks 101,102,103,104,105,106 --expected-artifacts ai/epics/epic-XXXX/plans/arch-story-0060-0001.md,ai/epics/epic-XXXX/plans/plan-story-0060-0001.md")
Output:
{"passed":true,"mode":"post","skill":"x-implement-story","phase":"Phase-1","expectedTasks":[101,102,103,104,105,106],"completedTasks":[101,102,103,104,105,106],"missingTasks":[],"expectedArtifacts":["ai/epics/epic-XXXX/plans/arch-story-0060-0001.md","ai/epics/epic-XXXX/plans/plan-story-0060-0001.md"],"missingArtifacts":[],"wallclockMs":47,"timestamp":"2026-04-24T10:35:00Z"}
Exit: 0.
Example 3 — POST mode, missing artifacts
Skill(skill: "x-internal-verify-phase-gates",
args: "--mode post --skill x-implement-story --phase Phase-1 --expected-tasks 101,102 --expected-artifacts ai/epics/epic-XXXX/plans/arch-story-0060-0001.md,ai/epics/epic-XXXX/plans/missing.md")
Output:
{"passed":false,"mode":"post","skill":"x-implement-story","phase":"Phase-1","expectedTasks":[101,102],"completedTasks":[101,102],"missingTasks":[],"expectedArtifacts":["ai/epics/epic-XXXX/plans/arch-story-0060-0001.md","ai/epics/epic-XXXX/plans/missing.md"],"missingArtifacts":["ai/epics/epic-XXXX/plans/missing.md"],"wallclockMs":38,"timestamp":"2026-04-24T10:40:00Z"}
Exit: 12.
Example 4 — WAVE mode, one member still running
With --timeout-s 2 and task 203 in in_progress:
Skill(skill: "x-internal-verify-phase-gates",
args: "--mode wave --skill x-review-codebase --phase Phase-2 --expected-tasks 201,202,203,204,205,206,207,208,209 --timeout-s 2")
Stderr:
PHASE_GATE_TIMEOUT — task 203 still in_progress after 2s
Exit: 14.
Example 5 — Malformed: wave without expected-tasks
Skill(skill: "x-internal-verify-phase-gates",
args: "--mode wave --skill x-review-codebase --phase Phase-2")
Stderr:
PHASE_GATE_MALFORMED — --mode wave requires --expected-tasks
Exit: 13.
Example 6 — Legacy short-circuit
When execution-state.json.taskTracking.enabled = false:
Skill(skill: "x-internal-verify-phase-gates",
args: "--mode post --skill x-implement-story --phase Phase-1 --expected-tasks 101 --expected-artifacts foo.md")
Output:
{"passed":true,"mode":"post","skill":"x-implement-story","phase":"Phase-1","expectedTasks":[],"completedTasks":[],"missingTasks":[],"expectedArtifacts":[],"missingArtifacts":[],"wallclockMs":3,"timestamp":"2026-04-24T10:45:00Z","note":"taskTracking disabled (legacy mode)"}
Exit: 0.
Error Handling
| Scenario | Action |
|---|---|
--mode value invalid |
PHASE_GATE_MALFORMED; exit 13 |
--phase fails regex |
Exit 64 |
| Required flag missing per mode | PHASE_GATE_MALFORMED; exit 13 |
State file absent AND no --state-file override |
STATE_FILE_AMBIGUOUS; exit 13 |
taskTracking.enabled=false |
Short-circuit; passed=true; exit 0 |
Expected task in_progress beyond timeout |
PHASE_GATE_TIMEOUT; exit 14 |
| At least one expected task missing / non-completed | PHASE_GATE_FAILED; exit 12 |
| At least one expected artifact absent | PHASE_GATE_FAILED; exit 12 |
x-internal-update-status delegation fails |
Propagate stderr; exit 13 with STATE_UPDATE_FAILED |
Generator Filter Contract
The ia-dev-env generator excludes skills with visibility: internal from:
.claude/README.mdinventory table./helpmenu.- User-facing autocomplete.
Still copied to .claude/skills/ (flat layout) so other skills can invoke via Skill(...).
Telemetry
Internal skills DO NOT emit phase.start / phase.end markers — the calling orchestrator owns telemetry wrapping. Passive hooks capture tool.call events for the underlying Bash/Read invocations.
Integration Notes
| Skill | Relationship | Context |
|---|---|---|
x-internal-update-status |
delegate | Atomic flock-protected write of phaseGateResults[] entry. |
x-implement-epic, x-implement-story, x-implement-task, x-release, x-orchestrate-epic, x-review-codebase, x-review-pr, x-manage-pr-merge-train |
callers | Retrofit in stories 0055-0003 → 0055-0010. |
x-internal-verify-epic-integrity |
composition | --mode final of x-implement-epic Phase 4 composes with integrity gate (gate runs first; integrity-gate is subsequent). |
x-internal-verify-story |
composition | --mode final of x-implement-story Phase 3 composes with story-verify (verify runs first; gate confirms its outputs). |
.claude/hooks/verify-phase-gates.sh |
consumer (Stop hook) | Reads phaseGateResults[] this skill writes; emits WARNING + exit 2 on gate failure at end of LLM turn. |
.claude/hooks/enforce-phase-sequence.sh |
consumer (PreToolUse hook) | Reads phaseGateResults[] to block Skill(...) of an orchestrator whose predecessor phase has no passed=true entry. |
Rule References
- Rule 25 — the specification this skill enforces.
- Rule 22 — Skill Visibility convention (
x-internal-*, visibility: internal). - Rule 23 — Model Selection (haiku tier for utility skills).
- Rule 13 — Skill Invocation Protocol (INLINE-SKILL pattern).
- Rule 19 — Backward Compatibility (legacy short-circuit behavior).
- Rule 24 — Execution Integrity (composition via
--mode final).
Full Protocol
Per-mode state-file schema, full flock + x-internal-update-status interaction pseudocode, polling algorithm for in_progress tasks, and the phaseGateResults[] append-only invariant live in references/full-protocol.md.
04 同仓库更多 Skills
x-parallel-eval
Detects and classifies file-collision risks between work units (tasks, stories, or epic phases) before parallel execution. Reads ## File Footprint blocks produced by x-task-plan / x-story-plan, applies the parallelism-heuristics knowledge pack (hard / regen / soft categories + hotspot overrides), and emits a collision matrix + serialization recommendation in Markdown (default) or JSON.
parallelism-heuristics
Canonical catalog of file-collision heuristics for parallel task, story, and epic execution. Defines the File Footprint block format, the three Conflict Categories (hard / regen / soft), a hotspot list of high-contention paths, and the degrade-with-warning policy. Consumed by x-task-plan, x-story-plan, x-epic-map, x-parallel-eval, and x-dev-*-implement.
x-watch-pr-ci
Polls a PR's CI checks and Copilot review status, blocking until checks complete or timeout. Returns one of 8 stable exit codes (SUCCESS=0, CI_PENDING_PROCEED=10, CI_FAILED=20, TIMEOUT=30, PR_ALREADY_MERGED=40, NO_CI_CONFIGURED=50, PR_CLOSED=60, PR_NOT_FOUND=70). Writes a versioned state-file for session resume.
x-validate-docs
Documentation freshness gate: validates 6 dimensions (readme, api-specs, grpc-proto, adr, skill-docs, system-architecture) against code changes in a PR. Stack-aware — only validates targets declared/auto-detected from ProjectConfig.documentation.targets. Returns exit non-zero on staleness; produces structured report.
x-update-system-architecture
Incrementally updates docs/architecture/system.md after an epic completes. Appends new entries to the Decision Log (§11) using x-internal-write-report --append (dedup by ## ID: marker) and surgically inserts component/integration changes into sections 1-10 via Edit. Idempotent: re-running with the same epic produces a byte-identical system.md.
x-update-architecture
Incrementally updates the service architecture document with changes from architecture plans. Adds new components, integrations, flows, and ADR references without rewriting existing content. Use after implementation to keep architecture documentation current.