ywc-sequential-executor

star 5

(ywc) Use when executing tasks from the tasks/ directory in strict order through their full lifecycle (branch → implement → commit → PR → CI → merge → cleanup). Triggers: "execute task", "implement tasks 000001-010", "run the next task", "implement all remaining tasks", "start implementing", "sequential-executor", "순차 실행", "タスク順次実行". Do not use for parallel/concurrent execution (use ywc-parallel-executor), code generation without a task directory (use ywc-code-gen), or ad-hoc one-off implementation requests.

yongwoon By yongwoon schedule Updated 6/10/2026

name: ywc-sequential-executor description: >- (ywc) Use when executing tasks from the tasks/ directory in strict order through their full lifecycle (branch → implement → commit → PR → CI → merge → cleanup). Triggers: "execute task", "implement tasks 000001-010", "run the next task", "implement all remaining tasks", "start implementing", "sequential-executor", "순차 실행", "タスク順次実行". Do not use for parallel/concurrent execution (use ywc-parallel-executor), code generation without a task directory (use ywc-code-gen), or ad-hoc one-off implementation requests.

Sequential Executor

Announce at start: "I'm using the ywc-sequential-executor skill to run tasks through their full lifecycle in strict order."

Execute tasks generated by the ywc-task-generator skill through the full development lifecycle: branch creation, implementation, commit, PR, CI verification, merge, and local sync.

Rationalization Defense

When tempted to skip a step, check this table first:

Excuse Reality
"Task A and Task B are independent, run them in parallel" This is the sequential executor. For parallel runs, the user must explicitly switch to ywc-parallel-executor.
"CI is taking long, --skip-ci-wait gets the next task started" Skipping CI hides regressions in subsequent tasks. Skip only if user explicitly approved.
"Previous task partially succeeded, I'll continue and clean up later" Each task must leave the codebase buildable. Stop and report on partial success.
"Merge conflict is small, I'll resolve and continue" Conflicts during sequential execution mean a base branch shifted. Stop, sync, get user direction.
"PR is created, mark task complete" Task is complete only when merged + cleaned up + branch deleted. PR alone is not done.
"Task spec is unclear, I'll infer from neighbors" Stop. Inferring from neighbors compounds error across the sequence. Ask user.
"Local merge with --local-merge is faster, default to it" Default is PR-based. --local-merge only when user explicitly opts in (e.g., personal repo).
"Lint/format failed in Step 4 with --draft, I'll stop and report" Lint/format failures are auto-fixable. Run the project's fix command (e.g., eslint --fix, prettier --write, ruff --fix), commit the result, re-run verification, then continue to Step 5. Only stop if auto-fix fails to resolve residual errors after 2 attempts.
"--draft creates the PR and stops — bot review is for later" Bot review bots (CodeRabbit, Codex Review, Claude Review) post on draft PRs immediately. After finish-branch creates the draft PR, poll for reviews and invoke ywc-handle-pr-reviews as a PR health sweep regardless of BOT_COUNT == 0; the handler also checks CI status and merge-readiness. The PR stays draft — responding now avoids a round-trip after un-drafting.
"normal-pr range: CI passed and no review artifacts yet — proceed to merge" Bot reviewers post 1–5 minutes after CI completes, not immediately. ywc-finish-branch runs a mandatory 60-second initial wait plus a 300-second polling window before concluding no unresolved artifacts exist. A zero count right after CI is not evidence that no bots are active — it means they have not posted yet. The polling window is a required wait gate in range mode, not a pause to skip.
"Last task in --local-merge range: no following task needs this merge, skip finish-branch" Step 5 (Delivery) is unconditional — every task, including the last, must have its feature branch merged into base, the completion-marker committed, and the push executed via ywc-finish-branch. Without it, the implementation code is stranded on an orphaned feature branch, tasks/completed/ is wrong, and the remote base branch is missing the work. The absence of a next task is not a reason to skip delivery.
"Last task in normal-pr range: it's the last one, no need to omit --defer-push" --defer-push must be omitted on the last task in normal-pr range — that omission IS the flush. If --defer-push is set on the last task, all accumulated completion-marker commits stay local and are never pushed. The last task's ywc-finish-branch invocation performs the single batch push; no separate git push runs after the loop.
"I'll add tests after implementation once the shape is clear" For behavior-changing tasks, write or identify the failing test / contract test first. Use ../references/tdd-deep-module-gray-box.md for allowed exceptions; do not backfill tests to match already-written code.
"This task only changes internals, so no contract note is needed" If any exported function, endpoint, DTO, schema contract, component props, CLI flag, event, or worker protocol changes, record the public contract before implementation and report it.
"I reviewed the whole implementation, so gray-box reporting is unnecessary" Gray-box review focuses on public contracts and critical internals. Report Changed Public Contracts, Critical Internals, and TDD Exceptions instead of dumping internal implementation detail.

Violating the letter of these rules is violating the spirit. Sequential execution exists because each task's correctness depends on the previous task's stable state.

Arguments

Parse $ARGUMENTS for the following parameters:

Parameter Format Example Description
Task specifier <task-name> or <start>..<end> 000001-010-db-create-users or 000001-010..000002-030 Single task or range (phase+sequence prefix match). Both 001010 (legacy) and 000001-010 (new 6-digit PHASE) formats are accepted; prefix matching works with either.
--pr-lang --pr-lang <lang> --pr-lang ja PR title/description language. Default: auto-detect from CLAUDE.md or AGENTS.md, fallback to project's dominant language
--tasks-dir --tasks-dir <path> --tasks-dir ./docs/tasks Tasks directory path. Default: tasks/
--skip-ci-wait flag Skip CI wait and auto-merge (create PR only)
--draft flag Create PR as draft, skip merge
--local-merge flag Skip PR creation entirely — merge the feature branch into the base branch locally and push. Mutually exclusive with --draft and --skip-ci-wait
--aggregate-pr flag Deliver the whole invocation through one work/<name> branch and one final work -> base PR. Each task still gets its own feature branch and is local-merged into the work branch.
--group-name --group-name <name> --group-name payments Names the aggregate work branch (work/<name>). Valid only with --aggregate-pr; defaults to work/<base-branch>-<timestamp> when omitted.
--base-branch --base-branch <branch> --base-branch develop Base branch override. Default: auto-detect (develop > main > master)
--worktree flag Run the whole invocation inside one run-level worktree. It is not a delivery mode; see references/worktree-run.md.
--dry-run flag Show the execution plan (task order, dependencies, modes) without executing anything
--terse flag Compact Completion Report: task table + Completion Status only — no prose reminders, no mode explanations, no advisor notes
--review flag Auto-run ywc-impl-review after each task, before PR creation or merge
--run-tests-locally flag Before merging in --local-merge mode, detect and run the project's test command. On failure: mark task FAIL and do not merge. Ignored in PR-based modes.

Flag conflicts: --local-merge, --draft, --skip-ci-wait, and --aggregate-pr are mutually exclusive. If the user passes more than one, stop before any branch or implementation work and ask which mode they actually want. The reason is that each mode has a different branch and PR lifecycle — silently picking one would surprise the user. --group-name is valid only with --aggregate-pr; if it is supplied without --aggregate-pr, stop and ask whether the user intended aggregate delivery.

--review can be combined with any delivery mode flag.

--run-tests-locally has no effect without --local-merge (PR CI handles tests in PR-based modes). --worktree is orthogonal to delivery mode flags and may combine with any mode; it changes execution location only.

If no task specifier is given, detect the next executable task from the dependency graph.

Dry Run Mode

When --dry-run is set, perform Pre-flight and Task Resolution as usual, then display:

  • Resolved task list in execution order (with phase+sequence and full name)
  • Dependency status for each task (satisfied / pending)
  • Active mode flags (--draft, --skip-ci-wait, --local-merge, --aggregate-pr, or normal)
  • Base branch that would be used
  • For --worktree: planned run worktree path, integration branch, state path, and start point
  • For --aggregate-pr: the derived work branch (work/<group-name> or work/<base-branch>-<timestamp>) and the final work -> base PR target

Do not create branches, modify files, or run any git commands beyond read-only operations (git branch --show-current, git status). Exit after displaying the plan.

Context

  • Current branch: !git branch --show-current
  • Changed files: !git status --short
  • Tasks directory: !ls tasks/ 2>/dev/null || echo "No tasks/ directory found"

Pre-flight

Resume check first: Before running the checks below, look for .ywc-run-state.json in the project root. If it exists, follow the Resume Detection procedure in Checkpoint and Resume, including the intent-match guard before offering resume. If the user confirms resume, skip Pre-flight and jump to the saved task and step. If the user declines or there is no state file, proceed with the checks below.

Before starting execution, verify these conditions:

  1. Clean working treegit status --porcelain must be empty. If dirty, warn the user and stop.
  2. On base branch — Should be on main/develop/master. If on a feature branch, warn and ask whether to continue.
  3. gh CLI readygh auth status must succeed.
  4. Tasks directory exists — The tasks directory must contain task subdirectories and dependency-graph.md.
  5. Spec-Reference external URL policy — Determine whether this project allows fetching external URLs (Notion, Confluence, Figma, etc.) listed in a task's Spec Reference section. See External URL Policy below. This check runs once per project, not once per task.
  6. Worktree run setup — If --worktree is set, follow references/worktree-run.md for audit/create, $WT state placement, resume discovery, and cleanup.

State Init (non-resume runs only): Initialize .ywc-run-state.json now using the Write tool (see format in Checkpoint and Resume). Also add it to .gitignore if absent:

grep -qxF '.ywc-run-state.json' .gitignore 2>/dev/null || echo '.ywc-run-state.json' >> .gitignore

External URL Policy

Tasks generated by ywc-task-generator may list external URLs in Spec Reference > Primary Sources. Fetching external content mid-task is unpredictable (network, rate limits, SSO walls) and is also a privacy decision the user must make once per project.

Procedure: at Pre-flight, check .codex/settings.local.json for ywDevSequentialExecutor.externalSpecUrls. If present, use it silently. If missing, ask the user once to choose deny (default), allow, or allowlist, then persist the decision under the ywDevSequentialExecutor key (preserving every other key in the file). During Step 1b enforcement, apply the chosen policy: deny skips all http(s):// URLs, allow fetches everything, allowlist fetches only matching host+path prefixes.

For full procedure, jsonc schema, exact prompt wording, and rationale, see references/external-url-policy.md.

Definition of Done

A task is done only when all of the following have happened, in this order. A task that has been "merged but not moved to completed/" is not done — Step 6's auto-detect logic and other tasks' dependency validation read <tasks-dir>/completed/ as the source of truth, so a missing move silently breaks dependency resolution for the next task in any range and for any future invocation of this skill.

  1. Implementation passed all four layers of Step 4 verification (Task Verify commands, task-local tests, full project test suite, lint/typecheck/build).
  2. ywc-finish-branch returned DONE for the task in Step 5. That status enforces conditions 3–5 inline: the merge succeeded with post-merge verification, the task directory was moved to <tasks-dir>/completed/<task-name> with a chore: mark <task-name> as completed commit, and the local feature branch was deleted.
  3. For --local-merge (every task), for --aggregate-pr (every task, to the work branch), and for normal-pr range execution (only the last task), the completion-marker commit has been pushed to the remote delivery branch — ywc-finish-branch pushes immediately when --defer-push is not set; the executor itself pushes once after the final task in a deferred-push range.

A merged-but-not-moved task is not done. Mark Task Complete is part of the task definition, not optional bookkeeping; ywc-finish-branch enforces it and refuses to return DONE if the move did not verify. If finish-branch returns anything other than DONE, the task is incomplete — go back and resolve before transitioning.

--draft and --skip-ci-wait are the only documented per-task exceptions: in those modes finish-branch ends at PR creation, the task stays in <tasks-dir>/<task-name>, and the user is expected to re-run the executor (or merge the PRs manually) to finalize them.

--aggregate-pr group-level done: every task must satisfy the per-task Definition of Done against the work branch, and the group is not complete until the final single work -> base PR is created from work/<name>, marked ready, CI-verified, cleared of bot review, passed through the merge-readiness gate, merged with gh pr merge --delete-branch, and the local base branch is synced. A run whose work PR is created but unmerged is DONE_WITH_CONCERNS at best, never DONE. Completion marker commits already live on the work branch; do not re-Mark-Complete after the final PR merges.

Pre-authorizing Tool Permissions (required for range execution)

The Non-Stop Execution Principle below governs LLM-level pausing, but it cannot override Codex's tool approval layer — every unprompted git/gh/mv command can independently block on user confirmation. In range mode this is the single most common reason execution stops mid-range: each git checkout, git push, git mv, and gh pr in every task triggers an individual prompt.

Required for range execution: Without pre-authorization, every git/gh/mv command in every task will pause for user approval — directly breaking the Non-Stop Execution Principle. Complete this setup before starting any range; it is not optional.

The fix is a one-time Codex command-approval setup that pre-authorizes a small set of read-only and task-scoped command prefixes. The same permissions are used by both ywc-sequential-executor and ywc-parallel-executor.

For the full pattern list, narrow fallback for strict policies, privacy notes, and diagnosis steps when pre-authorization is not enough, see ../references/local-merge-permissions.md.

Plan Critical Review (Pattern C, range mode)

When a range of 3+ tasks is about to start and the plan was either generated in a prior session or modified since, run a one-shot upfront advisor (Pattern C from ../references/advisor-pattern.md) over the dependency graph + first/last task summaries. The verdict is proceed or reconsider with refinements; on the latter, surface the refinements to the user and stop — do not auto-apply. The full invocation conditions, payload shape, output format, and budget accounting (consumes 1 of the 3 advisor calls) live in references/plan-critical-review.md. Skip the review for single-task, ≤2 task ranges, auto-detect mode, or when ywc-task-generator ran in the same session.

Checkpoint and Resume

The executor writes .ywc-run-state.json in the project root after each major step. If a range run is interrupted, you can resume from the last checkpoint — completed tasks are skipped and the in-progress task restarts at its last saved step. With --worktree, state lives at $WT/.ywc-run-state.json; root state remains the legacy default. Resume Detection checks root state first, then preserved run worktrees.

Resume detection runs before Pre-flight. For the resume procedure (executor/age/git validation, intent-match guard, resume offer prompt), the on-disk state schema, the per-step Checkpoint event table, and manual inspection commands, see references/checkpoint-resume.md. The per-step **Checkpoint** markers below in Steps 2/4/5 reference the event table in that document — update last_checkpoint to the current UTC time on every write. The legacy current_step: 8 value is preserved for resume compatibility with state files written by older skill versions; new runs reach the same logical state via Step 5 (Delivery). Long-range compaction: carry a one-line task status digest per completed task (for example, 000027-020 DONE local-merge <merge-sha>), and treat .ywc-run-state.json plus task artifacts (README.md, task.md, tasks/completed/<task>/) as the durable source of truth after compaction.

Task Resolution

Single Task

Match the specifier against task directory names in the tasks directory. Accept both exact match and prefix match (e.g., 000001-010 matches 000001-010-db-create-users-table; legacy 001010 format is still accepted during the transition period).

Range Execution

For <start>..<end> format, collect all tasks whose phase+sequence falls within the range (inclusive). Sort by phase then sequence. Execute sequentially, repeating the full cycle for each task.

Auto-detect Next Task

If no specifier is given:

  1. Read dependency-graph.md
  2. Check which tasks are in tasks/completed/
  3. Find the first task whose all dependencies are satisfied (all Depends On tasks are in completed/)
  4. If multiple tasks are ready (same phase, no mutual dependency), pick the lowest sequence number

Execution Cycle

For each task, execute these steps in order. If executing a range, repeat the entire cycle (Step 1 → Step 5) for each task before moving to the next. Each task gets its own feature branch — range mode does not reuse a single branch across multiple tasks.

Per-Task Branch Lifecycle (range mode overview)

Each task in a range gets its own feature branch — never reuse a branch across tasks. Starting point depends on mode: normal / --local-merge branch from a fresh base branch; --aggregate-pr branch from the dedicated work/<name> branch; --draft / --skip-ci-wait chain-branch from the previous feature branch (prior tasks are not merged, so their code would be missing otherwise). For per-mode diagrams, the decision table, and the "non-stop transitions ≠ non-stop coding on one branch" rationale (the single most common range-mode failure), see references/branch-lifecycle.md. For the aggregate work branch lifecycle, see references/aggregate-pr.md. When --worktree is active, the same lifecycle runs inside $WT; git commands, file edits, verification, finish-branch, and transition gates must be $WT scoped per references/worktree-run.md.

Non-Stop Execution Principle

Action required before any range task begins: Read ../references/non-stop-execution.md now. It defines the exhaustive allowed-stop list, the force-continue rule, tool permission prompt handling, and the Tool Error Recovery policy (how to recover from Edit/Bash failures without entering extended thinking). Do not defer this read to mid-execution.

When executing a range, do not pause, ask for confirmation, or report intermediate results between tasks. The shared rule, full stop list, force-continue rule, zero-output rule, and the "non-stop transitions ≠ non-stop coding on one branch" reasoning live in ../references/non-stop-execution.md.

The unit for this skill is task. Sequential-specific Allowed Stop Reasons: dependency unsatisfied (Step 1), task.md stop condition triggered (Step 3), verification fails after 2 fix attempts (Step 4), ywc-finish-branch returned BLOCKED and the four-step triage (context → reasoning → scope → plan) is exhausted (Step 5) — covers CI failures, merge conflicts, and push rejections that previously stopped this skill directly, flag conflict detected (Pre-flight). The "Zero output between transitions" rule applies to the gap between Step 5 of one task and Step 1 of the next. Everything else — Force Continue Rule, what not to stop for, tool-permission-prompts-are-not-stop-conditions, the --local-merge rationale, and the branch-lifecycle warning — is in the reference and applies verbatim.

Advisor Escalation Policy

This skill follows Pattern A from ../references/advisor-pattern.md: a single inherited-model executor with bounded advisor escalation. Budget: up to 3 advisor calls per invocation (single-task or range alike); exceeding requires explicit justification in the Completion Report. Context payload rule: forward only the decision point (≤100 lines), never the full task README, spec, repo state, or prior Execution Cycle turns; advisor returns a ≤200-word verdict.

The escalation conditions remaining in this skill's scope — Spec Reference conflict (Step 1b), verification first failure with unclear cause (Step 4), Stop Condition borderline (Step 3) — are defined in references/advisor-escalation.md. Merge conflict and CI first-failure escalations (originally conditions 3 and 4 in that reference) move to ywc-finish-branch's scope at Step 5; finish-branch consumes its own advisor_budget: 1 for those escalations independently of this skill's budget of 3.

Step 1: Dependency Validation and Spec Loading

Read the task's README.md in full. This step has two purposes: verify dependencies are met, and load the Spec Reference into context so implementation in Step 3 is grounded in the actual specification rather than guesswork.

1a. Dependency Validation

  • All tasks listed in Depends On exist in tasks/completed/
  • Range + draft/skip-ci-wait mode exception: If a dependency was not merged but a PR was created for it during this same range execution, treat it as satisfied. This allows range+draft mode to proceed through dependent tasks even though PRs are not yet merged.
  • Local-merge mode: No exception needed. Because --local-merge actually merges into the base branch, earlier dependencies in a range will be genuinely completed by the time later tasks are checked.
  • If any dependency is not completed (and not covered by the exception above), stop and report which dependencies are missing

1b. Spec Reference Loading

Locate the ## Spec Reference section in README.md. Three sub-fields drive Step 3 implementation:

  • Primary Sources — the source-of-truth documents.
    • For each project-relative path, read the file (or the specific section/anchor if given). If the path is missing, attempt a fuzzy recovery before stopping: search for files with a similar basename (case-insensitive, ignoring directory) using find or Glob. If exactly one candidate is found, use it and log a warning noting the path mismatch. If zero or multiple candidates are found, stop and report — the spec is the contract, and silently proceeding would guarantee divergence.
    • For each external URL (http:// / https://), apply the External URL Policy determined in Pre-flight. Urls skipped by policy are logged, not errors.
    • If the field is N/A — no external spec, skip loading and proceed. This is a legitimate state for housekeeping / refactor / config tasks.
  • Summary — a 2–5 sentence orientation. Read it even when Primary Sources are fully available; it captures the intent behind the linked content and is the fastest way to re-anchor if you get lost mid-implementation.
  • Out of Scope (from spec) — a guardrail. Keep this list visible throughout Step 3. If during implementation you feel tempted to add "just one more thing" that matches an Out of Scope item, do not — that item belongs to a different task (or was intentionally deferred) and adding it here violates the task's review boundary. Note the temptation in the PR description instead so reviewers can confirm the deferral is still correct.

If the Spec Reference section is entirely absent from README.md (i.e. the task was generated before this section existed), do not stop — instead, warn once in the execution log and fall back to implementing from task.md alone. This preserves backward compatibility with older task sets.

Step 2: Branch Creation

Every task gets its own feature branch. This applies to both single-task and range execution. Never run multiple tasks on the same branch — each task's changes must be isolated so they can be reviewed, merged, and rolled back independently.

Normal / local-merge mode (including range execution):

git checkout <base-branch>
git pull origin <base-branch>
git checkout -b feature/<task-name>

This applies to every task in a range, not just the first one. After each task completes its cycle (verify → finish-branch delivery), the next task starts fresh from the updated base branch. ywc-finish-branch (Step 5) leaves the working tree on <base-branch> for normal-pr and local-merge modes, so this command sequence runs cleanly without manual setup.

Aggregate PR mode (--aggregate-pr): Before the first task, create and push the work branch once from the real base branch. The work branch is the per-task delivery target for the entire range; the real base branch is not mutated until the final work -> base PR merges.

# With --group-name <name>:
WORK_BRANCH="work/<group-name>"
# Without --group-name:
WORK_BRANCH="work/<base-branch>-$(date +%Y%m%d-%H%M%S)"

git checkout <base-branch>
git pull origin <base-branch>
git checkout -b "$WORK_BRANCH"
git push -u origin "$WORK_BRANCH"

For each task, branch from the current work branch:

git checkout "$WORK_BRANCH"
git pull origin "$WORK_BRANCH"
git checkout -b feature/<task-name>

After Step 5 local-merges the task into $WORK_BRANCH, the next task branches from that updated work branch and sees all prior task changes. See references/aggregate-pr.md for the complete work branch lifecycle and final delivery gate.

Range + draft/skip-ci-wait mode (chain branching): When executing a range with --draft or --skip-ci-wait, earlier tasks are not merged into the base branch, so their code changes are absent from it. To ensure dependent tasks can build on prior work, create each subsequent branch from the previous task's feature branch instead of the base branch:

# First task in range — branch from base as usual
git checkout <base-branch>
git pull origin <base-branch>
git checkout -b feature/<task-name>

# Subsequent tasks — branch from the previous feature branch
git checkout feature/<previous-task-name>
git checkout -b feature/<task-name>

This solves the code-availability problem that Step 1's dependency-validation exception alone cannot address: the exception lets the dependency check pass, but without chain branching the implementation code from the previous task would be missing.

Branch name format: feature/<task-name> (e.g., feature/000001-010-db-create-users-table)

Checkpoint: Update .ywc-run-state.json — set current_task to <task-name>, current_step to 2, branch to feature/<task-name>, and last_checkpoint to current UTC time.

Step 3: Implementation

Read the task's task.md and implement according to the checklist. The Spec Reference section loaded in Step 1b is the authoritative source of intent — when task.md and the spec disagree, the spec wins and the discrepancy should be noted in the PR description. If docs/ubiquitous-language.md exists in the project root, read it now and apply canonical term names throughout implementation — identifiers matching a "Synonyms to Avoid" entry are a naming violation.

Question-First gate (run before any code change): After reading task.md and the Spec Reference, enumerate genuinely ambiguous decisions whose wrong answer would force a rewrite (interface shape, data model, naming that conflicts with existing code, library choice when more than one is installed). If the list is non-empty, stop and return NEEDS_CONTEXT with the questions enumerated — do not infer from neighboring tasks. Inferring silently compounds error across the sequence and is the most expensive failure mode. For the canonical procedure, what counts as genuine ambiguity, and the question format, see ../references/question-first-gate.md.

Simplicity + Surgical Changes (enforce throughout implementation): Implement the minimum code that satisfies the task spec — no speculative features, no unsolicited abstractions, no "flexibility" that wasn't asked for. When editing existing code: touch only files within the declared Ownership; do not improve adjacent code, comments, or formatting unless they are the direct subject of this task. If you notice unrelated issues, mention them in the PR description — do not fix them. Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, simplify before committing.

Schema-aware implementation (when the task touches DB): If the task adds, modifies, or removes tables, columns, indexes, or relations, read the shared ../references/schema/core.md and the one stack file matching the project (prisma.md / sql-ddl.md / drizzle.md / typeorm.md) before writing the migration. The eight mechanical invariants there (bilateral relations, cascade ↔ API status, NOT NULL backfill, FK index, composite uniqueness, multi-tenant scope, enum domain, timestamptz) fail deterministically at generate time or first write when omitted, and a migration task is the single point where they must all be right.

  1. Check Prerequisites — Verify all prerequisite items are satisfied
  2. Respect Edit Scope — Only modify files within the declared Ownership from README.md
  3. Follow Implementation Steps — Execute each step in order, checking off as completed. Keep the Spec Reference's Out of Scope (from spec) list in mind at every step — if an implementation step tempts you toward an Out of Scope item, stop and re-read the step; the item likely belongs to a different task.
  4. Contract + TDD baseline — Before behavior-changing implementation, apply ../references/tdd-deep-module-gray-box.md: record Changed Public Contracts and Critical Internals, then write or identify the failing regression/unit/integration/contract test before implementation. Allowed exceptions are docs-only, config-only, mechanical/metadata work, no practical local harness, or explicit user override; report each as TDD Exception: <reason>. Keep tests focused on public behavior and stable contracts, not private helper shape.
  5. Write tests and test cases (required) — Every behavior-changing task must ship with tests unless an allowed TDD exception is recorded. If task.md lists specific test requirements, follow them. Otherwise, author tests appropriate to the change:
    • Unit tests for new functions, classes, or modules (happy path + edge cases + error paths)
    • Integration tests when the task touches boundaries (DB, HTTP, IPC, external services)
    • Regression tests when the task fixes a bug — the test should fail on the old code and pass on the new code
    • Place tests in the project's existing test directory using its existing framework and naming convention (discover via ls/find before creating new structures)
    • TDD baseline is required for behavior changes: write or identify the failing test first, then the implementation that makes it pass. This gives you a concrete definition of done and prevents "test written to match the code"
    • Do not skip, comment out, or weaken assertions to make tests pass — fix the implementation instead
  6. Honor Stop Conditions — If any stop condition is triggered, halt and report to the user
  7. Commit incrementally — Create commits at logical boundaries (per implementation step or per logical unit). Tests and the code they cover should land in the same commit (or a test-first commit immediately preceding the implementation commit). Follow the project's commit convention from AGENTS.md, CODEX.md, CLAUDE.md, or recent git log.

Commit guidelines:

  • Each commit should be a coherent, reviewable unit
  • Follow the project's commit message convention
  • Add a co-author trailer only when the repository's commit convention or the user explicitly requires one. Do not fabricate a provider-specific trailer.
  • Stage specific files by name (never git add -A or git add .)

Completeness Gate (required before first commit): Before creating the first commit for this task, run a stub-pattern check on all modified files:

git diff --name-only HEAD 2>/dev/null | xargs grep -lnE \
  "TO""DO:.*imple""ment|FIX""ME|raise Not""ImplementedError|throw new Error\(.*[Nn]ot [Ii]mple""mented" \
  2>/dev/null || echo "OK: no stub patterns found"

If any stub patterns appear in implementation files, complete the implementation before committing. Stubs committed here become Step 4 verification failures; catching them before the first commit saves the entire retry cycle.

Exception: to-do comments in test files (for example, an edge-case reminder) are permitted. Stub markers in implementation files are not.

Step 4: Task Verification

Run verification in three layers, from narrowest to broadest. Each layer must pass before moving on.

  1. Task Verify commands — Run each command listed in the task.md Task Verify section. These are the task-author's definition of "this specific change works."

  2. Task-local test run — Explicitly run the tests you authored or touched in Step 3, even if they overlap with (1). This catches the case where a task's Verify section is stale or missing the new tests.

  3. Full project test suite (required, every task) — After (1) and (2) pass, run the entire project test suite, not just the files the task touched. The purpose is to catch regressions in code outside the task's declared Ownership — a task can technically stay within its edit scope and still break something downstream via shared state, shared types, schema changes, or runtime wiring. Discover the command from (in order): package.json scripts, Makefile, pyproject.toml/tox.ini, Cargo.toml, go test ./..., CI workflow files, or CLAUDE.md. Typical examples: npm test, pnpm test, pytest, go test ./..., cargo test, bundle exec rspec. Long test suites may be run in the background.

  4. General verification — Run the remaining checks specified by the task or project: lint, typecheck, build. These are cheap regression catchers and should always run. For lint/format failures, run the project's auto-fix command first (e.g., eslint --fix, prettier --write, ruff --fix, gofmt -w) before counting it as a fix attempt. Commit the auto-fixed changes and re-run the layer. If auto-fix resolves the issue, continue to Step 5 normally.

If any layer fails: fix the code, never the test — no skip/xit/.only, no commented-out or relaxed assertions. Re-run the failing layer plus any earlier layer the fix could invalidate. For a failure in a test unrelated to the current task, investigate whether the task actually caused it (shared state, fixtures, ordering) before dismissing as flaky. Layer 4 lint/format exception: running the project's auto-fix command is step zero and does not count toward the 2-attempt limit — the limit starts only if auto-fix leaves residual errors. After 2 fix attempts (post-auto-fix for Layer 4, or 2 direct attempts for other layers), stop and report layer + failing test name(s) + error output + attempts made. Never proceed to Step 5 with a failing full suite — local catch saves a CI round trip and keeps main healthy.

Checkpoint: Update .ywc-run-state.json — set current_step to 4, last_checkpoint to current UTC time.

--run-tests-locally gate (applies only when --run-tests-locally is set AND --local-merge is active): After all four verification layers pass, detect the project's test command from CLAUDE.md or package.json (scripts field). Run it before proceeding to Step 5 (merge). On failure: mark the task FAIL and do not merge — surface the test output to the user and stop. If no test command can be detected: emit a warning and proceed to Step 5 without blocking.

Step 4.5: Implementation Review (optional)

If --review is set, invoke ywc-impl-review on the current feature branch after all verification layers in Step 4 pass. The review runs before PR creation (Step 5) or local merge (Step 6a), so any issues it surfaces can be fixed while still on the feature branch.

This is optional — it adds time and tokens but catches design issues, naming problems, and patterns that automated tests miss. It pairs especially well with --local-merge, where no remote CI runs and this review becomes the last quality gate before code reaches the base branch.

The review applies the ywc-impl-review recurring real-world defects catalog — the classes (data-layer access-boundary / ownership isolation, data-integrity / NULL handling, error-swallow, external-call resilience, validation / fail-fast, HTTP status, test fidelity) that PR-review bots such as CodeRabbit flag most. In PR-based modes (normal-pr, --draft, --skip-ci-wait), catching these before the PR opens directly reduces the bot-review round-trips handled later by ywc-handle-pr-reviews.

Handling the review's status return: ywc-impl-review emits one of DONE, DONE_WITH_CONCERNS, BLOCKED, NEEDS_CONTEXT. The orchestrator's response is defined by ../references/subagent-status-actions.md — in particular, BLOCKED triggers the four-step triage (context → reasoning → scope → plan) before surfacing to the user, and DONE_WITH_CONCERNS requires reading the concerns to decide whether they are correctness-level (fix and re-review) or observation-level (carry forward to the Completion Report).

Step 5: Delivery (delegated to ywc-finish-branch)

After Step 4 verification (and optional Step 4.5 review) passes, the rest of the task — PR creation, CI wait, bot polling, merge (PR or local), post-merge verification, Mark Task Complete, and local branch cleanup — is delivered by ywc-finish-branch. This skill does not duplicate that logic.

Mode mapping (this skill's flag → finish-branch --mode):

This skill's flag finish-branch --mode
--local-merge local-merge
--draft draft
--skip-ci-wait skip-ci-wait
--aggregate-pr local-merge targeting $WORK_BRANCH
(none — default) normal-pr

⚠️ DO NOT SKIP THIS STEP FOR THE LAST TASK. The single most common failure in --local-merge range mode is jumping from Step 4 directly to the Completion Report for the last task. There is no exception. Even when there are no remaining tasks in the range, ywc-finish-branch must be invoked — it performs the git merge, push, completion-marker commit, and branch deletion. Skipping it leaves the implementation code on an orphaned feature branch with nothing pushed to the remote base branch.

Invocation (unconditional — every task in a range, including the last task, runs through this exact delegation; the optional --defer-push flag controls only whether the Mark-Complete commit is pushed at the end of finish-branch Step 7, and never affects PR creation, CI wait, bot polling, merge, post-merge verification, or Mark Complete itself):

$ywc-finish-branch \
  --mode <mapped-mode> \
  --branch feature/<task-name> \
  --base-branch <base-branch-or-$WORK_BRANCH> \
  --task-name <task-name> \
  --tasks-dir <tasks-dir> \
  --pr-lang <pr-lang> \
  --bot-action sequential \
  [--defer-push only when mapped-mode is `normal-pr` AND this is not the last task in a multi-task range]

--bot-action sequential is required: this skill executes one task at a time, so bot review fixes must trigger a CI re-gate before merging (finish-branch's parallel mode skips the re-gate).

For --aggregate-pr, invoke finish-branch as a per-task local merge into the work branch:

$ywc-finish-branch \
  --mode local-merge \
  --branch feature/<task-name> \
  --base-branch "$WORK_BRANCH" \
  --task-name <task-name> \
  --tasks-dir <tasks-dir> \
  --pr-lang <pr-lang> \
  --bot-action sequential

This preserves the normal per-task verification, merge, post-merge verification, Mark Complete, and feature-branch cleanup contract while changing only the delivery target from the real base branch to work/<name>.

Range push deferral (push behavior only — does not affect PR creation, CI wait, bot polling, merge, or Mark Complete): in normal-pr range mode, Mark-Complete commits accumulate locally as --defer-push is set on every task except the last; finish-branch's own Step 7 push on the last task (which deliberately omits --defer-push) flushes all accumulated commits in a single push. No separate post-loop git push command is required — the last task's finish-branch invocation IS the flush. For --local-merge, --aggregate-pr, and single-task invocations, omit --defer-push — push happens immediately every time. In --aggregate-pr, that push goes to $WORK_BRANCH, not the real base branch.

Handling finish-branch's status return: ywc-finish-branch ends with one of DONE, DONE_WITH_CONCERNS, BLOCKED, NEEDS_CONTEXT. The orchestrator's response is defined by ../references/subagent-status-actions.md. In particular, BLOCKED triggers the four-step triage (context → reasoning → scope → plan) before surfacing to the user, and DONE_WITH_CONCERNS requires reading the concerns to decide whether they are correctness-level (fix and re-dispatch) or observation-level (carry forward to the Completion Report).

Status Routing — Apply to ywc-finish-branch and optional ywc-impl-review returns:

Returned status Caller action
DONE Proceed to Step 6, or to the Completion Report if this was the last task.
DONE_WITH_CONCERNS Observation concerns go to the Completion Report; correctness concerns require a fix and re-dispatch before proceeding.
BLOCKED Run the four-step triage; if unresolved, halt the range and surface the failing task plus blocker excerpt.
NEEDS_CONTEXT Provide missing context and re-dispatch; do not infer from prior tasks.
Status absent or unparseable Treat as BLOCKED, halt the range, and surface the raw payload.

BLOCKED returns preserve the task branch and any in-progress merge state. The task directory stays in <tasks-dir>/<task-name> rather than moving to completed/; after the blocker is resolved, Resume Detection should restart from the failed task's delivery step.

Mode-skip semantics: for --mode draft and --mode skip-ci-wait, finish-branch's responsibility ends at PR creation (not at merge or Mark Complete). The task remains in <tasks-dir>/<task-name> (not moved to completed/) and no completion marker is committed; the user is expected to re-run the executor (or merge the PRs manually) to finalize. This does not apply to --aggregate-pr: per-task delivery is a real local-merge into $WORK_BRANCH, and the final group PR lifecycle below is mandatory.

--draft PR health sweep: After finish-branch returns with the draft PR URL, run the bot review polling loop from ../references/pr-bot-polling.md, then invoke ywc-handle-pr-reviews for this PR regardless of BOT_COUNT == 0. The handler checks review artifacts, CI status, and merge-readiness; a zero bot-comment count is not terminal success. The PR stays as draft after review response — do not un-draft or merge.

Checkpoint: Update .ywc-run-state.json after finish-branch returns — set current_step to 8 (final pre-completion checkpoint, preserved for resume compatibility with older state files); set branch to null for normal-pr, local-merge, and --aggregate-pr (finish-branch deleted the feature branch) or keep feature/<task-name> for draft / skip-ci-wait (branch stays alive). Append <task-name> to completed only when finish-branch returned DONE and the task was finalized through normal-pr, local-merge, or --aggregate-pr. For draft / skip-ci-wait, do not append; the task is intentionally incomplete.

Step 6: Next Task (Range Mode Only)

Precondition (enforced, not optional): You may only enter Step 6 if ywc-finish-branch (Step 5) has already returned DONE for the current task. If you have not yet invoked ywc-finish-branch for the current task, go back to Step 5 now — do not proceed here. Step 6 is a transition step, not a shortcut past Step 5.

If executing a range:

  1. Check if there are remaining tasks in the range. If no remaining tasks, and Step 5 has returned DONE for the current task, proceed to the Completion Report.
  2. Pre-transition state check (normal-pr, local-merge, and --aggregate-pr modes): Run the bundled verification script, passing the branch the next task will branch from — <base-branch> in normal-pr/local-merge, or $WORK_BRANCH in --aggregate-pr. The script is mode-agnostic and checks the same 4 conditions against whichever integration branch it receives:
    bash <path-to-skill>/scripts/verify-transition.sh \
      <base-branch-or-$WORK_BRANCH> <completed-task-name> [<tasks-dir>]
    
    Exit 0 = PASS — all 4 conditions satisfied, safe to proceed. Exit 1 = FAIL — details printed to stdout with fix hints. Remediations per condition: wrong branch → git checkout <base-branch>; feature branch still alive → re-invoke ywc-finish-branch (it returned non-DONE); dirty tracked files → stop and report, do not auto-stash (only ?? untracked files are safe to git clean -fd); missing completed/<task> directory → finish-branch's Step 7 post-move verification did not run — treat as a Step 5 failure and re-invoke or surface to the user. Never transition forward without PASS. This gate exists because the most common range-mode failure is carrying state from one task into the next, and a missed Mark-Complete silently corrupts the dependency contract for every subsequent task.
  3. Transition to the next task immediately and silently — emit no text output, do not ask for confirmation, do not summarize. The next output after Step 5 of this task is the first tool call (reading README.md) of Step 1 of the next task — not any text. Suppress any transition-message impulse and issue the tool call instead.
  4. Go back to Step 1 and repeat the full cycle (Step 1 → Step 5) for the next task. Step 2 runs again for every task — each task gets its own fresh feature branch.

The working tree state at this point differs by mode (normal-pr / local-merge are on <base-branch> with merged changes pulled; --aggregate-pr is on $WORK_BRANCH with merged changes pulled; draft / skip-ci-wait stay positioned for chain branching from the previous feature branch). For per-mode transition details, see references/branch-lifecycle.md. The key point: Step 2 is not skipped for subsequent tasks — every task in a range goes through the complete Step 1 → Step 5 cycle, including branch creation.

Completion Report

--aggregate-pr final group delivery (execute before the report below): After the last task has been local-merged into $WORK_BRANCH and marked complete, run the full work -> base PR lifecycle from references/aggregate-pr.md. It owns PR creation, ready, CI, bot review, merge-readiness, merge, and base sync. Completion-marker commits already live on $WORK_BRANCH; do not re-Mark-Complete after the final PR merges.

After all tasks are executed, display:

  • Total tasks executed: N
  • Each task: name, PR URL, PR status (draft / open / merged) — or local-merge with the merge commit SHA when --local-merge is used
  • Contract report per task: Changed Public Contracts, contract/behavior tests that first failed and then passed, Critical Internals reviewed, and TDD Exceptions (or N/A)
  • Any tasks that were skipped or failed (with reason)
  • Current branch and sync status
  • If in worktree mode: run worktree path, integration branch, state cleanup, and preserved branch/recovery command when applicable
  • If in draft/skip-ci-wait mode: remind user that PRs need manual review and merge
  • If in local-merge mode: remind user that no PR was created and no CI ran remotely — only the local verification from Step 4 gates the merge
  • If in aggregate-pr mode: list the final aggregate PR URL and status; it must be marked ready, CI-verified, bot-cleared, merge-readiness checked, merged, and locally synced before the run can report DONE

When --terse is set, omit all prose reminders and mode-specific explanations. Emit only:

  1. The task table (name | status | PR URL or merge SHA)
  2. The Completion Status line

Reporting Symbols: Use the shared vocabulary in symbols.md for the per-task status column and inline step traces. The symbol is a scan aid, not a replacement for the status text — keep both. For multi-step traces inside a single task report, use the flow operator » (e.g. branch ✅ » impl ✅ » verify ✅ » PR ✅ » merge ✅). Do not use symbols inside commit messages, PR titles, or generated source code — they belong to the report layer only.

Completion Status: End every report with one of these four declarations on its own line. This is the final line of the report — nothing follows it.

Status When to use
DONE All tasks completed, all PRs merged (or merged locally), including the final aggregate PR when --aggregate-pr is used, no open issues
DONE_WITH_CONCERNS Run completed but with caveats — failed tasks, skipped steps, advisor budget exceeded, or non-critical warnings
BLOCKED Run stopped and cannot continue — merge conflict, authentication failure, or a decision requiring human input
NEEDS_CONTEXT Task list or arguments are ambiguous; the run cannot start without clarification

Operational Self-Improvement: Before deleting the checkpoint file, append any genuinely new project-specific operational findings to .ywc-learnings.jsonl (one JSON object per line, format {"ts":"<ISO-8601>","skill":"ywc-sequential-executor","project":"<basename>","learning":"<one sentence>"}). Add the file to .gitignore if absent. Record only project-specific facts (package manager quirks, CI timing, build-step ordering, branch-protection rules) — skip generic programming facts and anything already in CLAUDE.md. If nothing new in this run, skip the write entirely; empty entries are noise.

State cleanup (mandatory, unconditional, every mode): After displaying the report, delete the checkpoint file. This step runs for every successful run regardless of mode (normal-pr / local-merge / draft / skip-ci-wait / --aggregate-pr), regardless of how many tasks ran (single-task or range), and regardless of whether mid-flight checkpoint updates were actually written. Skipping it leaves a stale .ywc-run-state.json whose current_task / current_step / completed fields no longer reflect reality, and the next invocation's Resume Detection will pick it up and offer to resume — silently re-executing or short-circuiting tasks that already finished. The most common failure mode is single-task normal-pr runs where intermediate checkpoint writes did not fire (because the path is short) and the LLM perceives the cleanup as superfluous; treat it as part of the run, not an optional post-script.

rm -f .ywc-run-state.json
test ! -f .ywc-run-state.json && echo "OK: state cleaned" || echo "WARNING: state file still present"

If the verification line prints WARNING, the run is DONE_WITH_CONCERNS, not DONE — surface the leftover file path in the Completion Report.

Output Format

The final output is the Completion Report. In normal verbosity it includes the full task table and mode-specific caveats; under --terse, emit only the table and status line:

| Task | Status | PR URL or merge SHA |
|---|---|---|
| 000001-010-example | merged | <sha-or-url> |

Completion Status: DONE | DONE_WITH_CONCERNS | BLOCKED | NEEDS_CONTEXT

Validation

Before emitting the Completion Report, verify:

  • The current task reached ywc-finish-branch unless the run stopped before implementation
  • verify-transition.sh passed before moving between range tasks
  • Completed tasks are under <tasks-dir>/completed/
  • In --worktree mode, $WT state cleanup/preservation and integration branch handling match worktree-run.md
  • In --aggregate-pr mode, the final work -> base PR was marked ready, CI-verified, bot-cleared, merge-readiness checked, merged, and local base was synced
  • .ywc-run-state.json was removed or reported as a concern
  • The final line is exactly one Completion Status declaration

Error Handling

Merge conflict during pull → stop and ask the user to resolve manually. PR-vs-base conflict at delivery → ywc-finish-branch's Merge-Readiness Gate (Step 4 final, per ../references/pr-conflict-resolution.md) handles it: a merely-behind branch is auto-updated and CI re-verified; a real textual conflict returns BLOCKED for human resolution. CI timeout (>30 min) → report status and ask whether to continue waiting. CI failure → ywc-finish-branch Step 4 diagnoses the failing checks, categorizes the failure (lint/format, type, test, build), and applies up to 2 fix attempts automatically; returns BLOCKED only when fixes are exhausted — do not stop at the first CI failure. gh CLI not authenticated → provide setup instructions and stop. Task not found → list available tasks and ask the user to specify. Dirty working tree → show changed files and ask the user to commit or stash.

Notes

This skill works with tasks generated by ywc-task-generator. PR creation is delegated to the create-pr skill (security check + CI pre-push validation handled there). Parallel execution (multiple independent tasks at once) belongs to ywc-parallel-executor — this skill is sequential by default for safety. Never force-push or amend published commits without explicit user approval. On any step failure, explain what went wrong and suggest a fix rather than silently retrying.

Install via CLI
npx skills add https://github.com/yongwoon/ywc-agent-toolkit --skill ywc-sequential-executor
Repository Details
star Stars 5
call_split Forks 1
navigation Branch main
article Path SKILL.md
More from Creator