원클릭으로
task-workflow
Shared implementation workflow for task-based skills, with profile-check sites wrapped in Jinja conditionals.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Shared implementation workflow for task-based skills, with profile-check sites wrapped in Jinja conditionals.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Create, refresh, or show an implementation trail — a durable, wave-structured, evidence-backed task-sequencing artifact stored via ait artifact.
Create, refresh, or show an implementation trail — a durable, wave-structured, evidence-backed task-sequencing artifact stored via ait artifact.
Shadow companion for a followed coding agent — reads its captured terminal output and, in one instruction-driven flow, explains it, helps answer an AskUserQuestion, or critically interrogates a plan. Advisory-only. Spawned by minimonitor; not a task-implementation command.
Draft a manager-facing work report from selected board columns.
Pick and implement a task in remote/non-interactive mode. All decisions from execution profile - no AskUserQuestion calls.
Pick and implement a task on Claude Code Web. Zero interactive prompts. No cross-branch operations — stores task data locally in .aitask-data-updated/.
| name | task-workflow |
| description | Shared implementation workflow for task-based skills, with profile-check sites wrapped in Jinja conditionals. |
| user-invocable | false |
This skill is invoked by other skills (e.g., aitask-pick, aitask-explore, aitask-review) after they have selected a task. The calling skill MUST establish the following context before handing off:
| Variable | Type | Description |
|---|---|---|
task_file | string | Path to selected task file (e.g., aitasks/t16_implement_auth.md or aitasks/t10/t10_2_add_login.md) |
task_id | string | Task identifier (e.g., 16 or 16_2) |
task_name | string | Filename stem for branches/worktrees (e.g., t16_implement_auth or t16_2_add_login) |
is_child | boolean | Whether this is a child task |
parent_id | string/null | Parent task number if child (e.g., 16), null otherwise |
parent_task_file | string/null | Path to parent task file if child (e.g., aitasks/t16_implement_auth.md), null otherwise |
active_profile | object/null | Loaded execution profile from calling skill (or null if no profile) |
active_profile_filename | string/null | Scanner-returned filename for the profile (e.g., fast.yaml or local/fast.yaml), null if no profile |
previous_status | string | Task status before workflow began (for abort revert, e.g., Ready) |
folded_tasks | array/null | List of task IDs folded into this task (e.g., [106, 129_5]), or null/empty if none. Set by aitask-explore when existing tasks are folded into a new task. |
skill_name | string | Name of the calling skill for feedback tracking (e.g., pick, explore, pr-import) |
feedback_collected | boolean | Guard flag — initialized to false. Set to true after the Satisfaction Feedback Procedure runs. Prevents double execution across workflow paths. |
usage_collected | boolean | Guard flag — initialized to false. Set to true before the unconditional usage bump fires in Satisfaction Feedback Step 0. Set-before-call so a mid-procedure failure does not cause a retry double-bump. |
detected_agent_string | string/null | Agent string (e.g., claudecode/opus4_6). Set by either the verify-path append in planning.md Step 6.1 or by Agent Attribution in Step 7. Consumed by Agent Attribution (fast-path) and by Satisfaction Feedback in Step 9b to skip re-detection. Initialized to null. |
After a task is selected and confirmed, perform these checks before proceeding to Step 4.
Check 1 - Done but unarchived task:
status fieldDone:
./.aitask-scripts/aitask_query_files.sh plan-file <taskid>
Parse the output: PLAN_FILE:<path> means found, NOT_FOUND means not found.AskUserQuestion:
Check 2 - Orphaned parent task (empty children_to_implement):
children_to_implement: [] (empty list)./.aitask-scripts/aitask_query_files.sh archived-children <number>
Parse the output: ARCHIVED_CHILD:<path> lines mean archived children exist, NO_ARCHIVED_CHILDREN means none.AskUserQuestion:
Check 3 - Manual-verification task:
issue_type fieldissue_type is manual_verification:
manual-verification.md)Check 4 - In-flight gated task, all gates now pass:
./.aitask-scripts/aitask_gate.sh archive-ready <taskid> and parse:
NO_GATES or BLOCKED:<csv> → skip this check (fall through to normal selection). This is the common case today — no task declares gates yet.ALL_PASS → the task's substantive work landed in an earlier session and every declared gate now passes, but archival was deferred (it was kept active). This is the next-pick backstop for the deferral in Step 9. Use AskUserQuestion:
Check 5 - In-flight task, resume from first unmet checkpoint:
This makes task-workflow re-entrant: a task left Implementing (crash, session loss, multi-day work) resumes from the first unmet recorded checkpoint instead of restarting at planning.
status. If it is not Implementing, skip this check (a fresh task plans from scratch)../.aitask-scripts/aitask_gate.sh resume-point <taskid> and parse the single-word result:
PLAN → skip this check. Nothing durable was recorded (empty/early ledger), so the normal flow runs: Step 4 reclaims the lock and planning re-runs as today. This is the common case for profiles that do not record gates (the ledger stays empty → always PLAN), so they are behaviorally unchanged.IMPLEMENT or POSTIMPL → the task has recorded checkpoints and is being re-entered. Set the context variable resume_point to that value. Show the recorded state and the resume target, e.g.:
./.aitask-scripts/aitask_gate.sh status <taskid>
Display a banner: "Re-entering in-flight task t<id> — <recorded checkpoints> → will resume at <implementation (Step 7) | post-implementation (Step 9)> after the lock is reclaimed." Then proceed to Step 4 normally — ownership MUST be (re)claimed before any work resumes. The actual step-skipping happens after Step 4 (see Re-entry Routing).Note: Check 1, Check 2, and Check 4 should NOT set the task status to "Implementing" — the task is already done (or its work is complete and gated). Skip Step 4 (Assign Task) entirely when archiving via Check 1, Check 2, or Check 4. Check 3 does run Step 4 as normal. Check 5 also runs Step 4 (the in-flight lock must be reclaimed) — it does not skip it; step-skipping happens post-reclaim via Re-entry Routing.
If none of the checks trigger, proceed to Step 4 as normal.
Email resolution (priority order):
Check task metadata: Read the assigned_to field from the task file's frontmatter.
Check userconfig: Read aitasks/metadata/userconfig.yaml and extract the email: field (if file exists).
Mismatch check: If both assigned_to and userconfig email are non-empty and DIFFERENT, use AskUserQuestion:
If assigned_to is non-empty (and matches userconfig, or userconfig is empty): use assigned_to. Display: "Using email from task metadata: <email>". Skip to Claim task ownership.
Profile-driven email resolution (profile 'remote', default_email: userconfig):
Use the userconfig email (from step 2). If userconfig is empty/missing, fall back to reading aitasks/metadata/emails.txt (first email). Display: "Profile 'remote': using email <email> (from userconfig)". If both are empty, prompt the user via AskUserQuestion as described in step 6 below.
Then skip step 6 and proceed to the Userconfig sync check below.
Otherwise, ask for email using AskUserQuestion:
cat aitasks/metadata/emails.txt 2>/dev/null | sort -uAskUserQuestion with free text (use the "Other" option)Userconfig sync check: After email is resolved, if the final email differs from the userconfig email (or userconfig doesn't exist):
AskUserQuestion:
email: <email> to aitasks/metadata/userconfig.yaml (create file if needed with comment header # Local user configuration (gitignored, not shared))Claim task ownership (lock, update status, commit, push):
If email was provided (new or selected):
./.aitask-scripts/aitask_pick_own.sh <task_num> --email "<email>"
If no email (user selected "Skip"):
./.aitask-scripts/aitask_pick_own.sh <task_num>
Parse the script output:
OWNED:<task_id> — Success. Proceed to Step 5.
FORCE_UNLOCKED:<previous_owner> + OWNED:<task_id> — Force-unlock succeeded. Inform user: "Force-unlocked stale lock held by <previous_owner>." Proceed to Step 5.
One of LOCK_RECLAIM:, RECLAIM_CRASH:, or RECLAIM_STATUS: (in addition to OWNED:) — task was already in Implementing and re-locked. When multiple are present, prefer LOCK_RECLAIM > RECLAIM_CRASH > RECLAIM_STATUS. Parse the signal-specific fields and execute the Crash Recovery Procedure (see crash-recovery.md) with signal_type and the parsed fields.
Signal field formats:
LOCK_RECLAIM:<prev_hostname>|<prev_locked_at>|<current_hostname> — multi-PC reclaim (cross-host).RECLAIM_CRASH:<prev_locked_at>|<prev_hostname>|<prev_pid> — same-host crash (PID anchor is dead). Common case after a tmux/host-shell crash.RECLAIM_STATUS:<prev_status>|<prev_assigned_to> — anomaly fallback (lock missing or pre-PID-anchor lock).When the procedure returns:
reclaim → ownership is held here (OWNED: confirms). Continue to the Re-entry Routing gate at the end of Step 4 (it checks resume_point); if no resume applies, proceed to Step 5 normally.decline → return to the calling skill's task selection. Do NOT proceed. (The procedure has already released the lock and reverted the task to Ready.)LOCK_FAILED:<owner>|<locked_at>|<hostname> — Task is locked by another user/PC. Parse the |-separated fields for lock details. Use AskUserQuestion:
--force:
./.aitask-scripts/aitask_pick_own.sh <task_num> --force --email "<email>"
Parse the output again. If FORCE_UNLOCKED + OWNED: proceed. Otherwise: abort.LOCK_ERROR:<message> — Lock system error (fetch failure, race exhaustion, etc.). Display the error and suggest running ./.aitask-scripts/aitask_lock_diag.sh for troubleshooting. Use AskUserQuestion:
aitask_pick_own.sh (same command). Parse output again.LOCK_INFRA_MISSING — Lock infrastructure not initialized. Inform user to run ait setup and abort.
Note: The script handles email storage, lock acquisition, task metadata update (status → Implementing, assigned_to), and git add/commit/push internally. If the script fails entirely (non-zero exit without structured output), display the error and abort.
Materialize the active-gates tuple (ALWAYS runs — never profile-omitted): With ownership held, derive and persist the task's enforced gate set under the current profile. If active_profile_filename is set, run:
./.aitask-scripts/aitask_gate.sh materialize-active <task_num> --profile aitasks/metadata/profiles/<active_profile_filename>
Parse the single stdout line:
MATERIALIZED:<csv> — active set persisted and committed. MATERIALIZED:(empty) means a fully profile-filtered (or ungated) task — that persisted empty set is exactly what makes a declared-but-unrendered gate invisible to every enforcer. Continue.MATERIALIZED_UNCOMMITTED:<csv> — the tuple was written and is enforced locally, but the path-scoped git commit failed (e.g. an index lock). Warn: "active-gates tuple written but not committed — other checkouts won't see it until the task data is committed." and continue; a later ./ait git commit of aitasks/ picks it up.NOOP:unchanged — re-pick under the same profile with unchanged inputs; nothing rewritten (any previously pending commit of the task file was verified/repaired). Continue.NOOP_UNCOMMITTED:pending-persist — the tuple is unchanged and enforced locally, but the task file still carries changes git refused to commit. Warn as for MATERIALIZED_UNCOMMITTED and continue.gates: fallback is only the task's declared intent — it does NOT include this profile's default_gates, so continuing could silently under-enforce the current profile. ABORT the pick: display "active-gates materialization failed (<output>) — fix the profile / compute backend and re-pick t<task_num>.", then execute the Task Abort Procedure (see task-abort.md). Do NOT proceed to Step 5.If active_profile_filename is NOT set (a manual/resume invocation without a profile), skip the call. This is the claim-time-snapshot governance model: with no profile in scope there is nothing to re-derive against, so the previously persisted tuple (when present and intact) remains the enforced snapshot, and a task never materialized follows its raw gates: field. (./.aitask-scripts/aitask_gate.sh active-gates-status <task_num> --profile <file> shows the stored tuple + freshness when a profile is in scope.)
This claim-time materialization replaces the former Step-7 gates: backfill: raw gates: stays the task's declared intent, and the persisted active_gates tuple is the enforced set that planning, the Step-9 orchestrator, and the archival guard all read. Re-running on every (re-)pick re-derives the set under the CURRENT profile, so a profile switch can never leave stale enforcement. (Gate CLI verb shapes — decision vs action vs introspection — are documented once in gate-cli.md.)
Store previous status for potential abort (remember the previous_status from context)
Re-entry Routing gate: After ownership is held (via any success path above — OWNED, FORCE_UNLOCKED + OWNED, or crash-recovery → reclaim), check the resume_point context variable set by Step 3 Check 5. If it is IMPLEMENT or POSTIMPL, follow the Re-entry Routing procedure below instead of proceeding to Step 5 → Step 6. Otherwise (unset, or PLAN), proceed to Step 5 normally. (The routing is gated on resume_point, not on which ownership path was taken — a force-unlock takeover of an in-flight task returns plain OWNED with no reclaim signal, and its resume must not be lost.)
Runs only when resume_point (from Step 3 Check 5) is IMPLEMENT or POSTIMPL and Step 4 left ownership held. It resumes the in-flight task from the first unmet checkpoint instead of restarting at planning. Profile-invariant.
Plan-existence guard: Run ./.aitask-scripts/aitask_query_files.sh plan-file <taskid>. If NOT_FOUND (a checkpoint was recorded but no plan was externalized — e.g. a failed externalization), discard the resume: clear resume_point and fall back to the normal flow (Step 5 → Step 6, re-plan). If PLAN_FILE:<path>, read the plan and continue below.
Environment setup (Step 5) with reuse: If a worktree for <task_name> already exists — git worktree list --porcelain shows a branch refs/heads/aitask/<task_name> line — reuse it (work in that directory); do NOT recreate the branch/worktree. Otherwise run Step 5 as normal. For current-branch profiles (no worktree), Step 5 is a no-op and you work on the current branch.
Route by resume_point:
IMPLEMENT → resume at Step 7's "Follow the approved plan" implementation body. Re-run only the Pre-implementation ownership guard and the Agent Attribution Procedure (both idempotent; attribution re-records the resuming agent), then go straight to implementation. Skip Step 7's post-approval one-time gates:
Implementing single task is necessarily past them; re-running would double-create.plan_approved / risk_evaluated gate re-recordings and the risk-level field write — already done in the original session; re-running only adds redundant commits.POSTIMPL → resume at Step 9 (Post-Implementation), skipping Steps 6–8 (the code is already committed and review_approved was recorded after the Step 8 commit). Step 9 is safe to re-enter: its merge approval is NON-SKIPPABLE (re-asked), a re-merge of an already-merged branch is a git no-op, and archival just moves and commits the task file. For child tasks, the "verify plan completeness before archival" sub-step backstops the Final Implementation Notes.Note: For fully autonomous remote workflows (Claude Code Web), use the
aitask-pickremskill instead — it skips all environment setup and always works on the current branch.
Profile check: If the active profile has create_worktree set:
true: Create worktree. Display: "Profile '<name>': creating worktree"false: Work on current branch. Display: "Profile '<name>': working on current branch"Otherwise, use AskUserQuestion to ask:
If Yes:
Extract <task_name> from the filename
t16_implement_channel_settings from t16_implement_channel_settings.mdt16_2_add_login from t16_2_add_login.mdProfile check: If the active profile has base_branch set:
Otherwise, ask which branch to base the new branch on using AskUserQuestion:
Create worktree directory:
mkdir -p aiwork
Create both the branch and worktree in a single command:
git worktree add -b aitask/<task_name> aiwork/<task_name> <base-branch>
Where <base-branch> is main or the user-specified branch.
Work in the aiwork/<task_name>/ directory for implementation
If No:
Full planning workflow: Read
planning.mdfor the complete Step 6 procedure including:
- 6.0: Check for Existing Plan (profile-aware)
- 6.1: Planning (EnterPlanMode, child tasks, complexity assessment)
- Child Task Documentation Requirements
- Save Plan to External File (naming conventions, metadata headers)
- Checkpoint (post-plan action)
After the checkpoint in
planning.md:
- If child tasks were created and the child checkpoint returned "Stop here" → collect Satisfaction Feedback Procedure (see
satisfaction-feedback.md) withskill_namefrom context variables, then END the workflow (do NOT proceed to Step 7/8/9)- If child tasks were created and the child checkpoint returned "Start first child" → restart with
/aitask-pick <parent>_1(do NOT proceed to Step 7)- Otherwise (normal single-task plan) → proceed to Step 7
Pre-implementation ownership guard:
Before starting implementation, verify that ownership/lock was acquired (Step 4 should have done this, but this guard catches edge cases like plan mode deferral):
status and assigned_to fieldsaitasks/metadata/userconfig.yamlImplementing AND assigned_to matches the current user's email: Ownership appears to have been acquired in Step 4 — but verify the lock is held on this host before assuming so. Run ./.aitask-scripts/aitask_lock.sh --check <task_id> and parse the hostname: line from the output. Compare against hostname (the running shell's hostname).
--check shows no lock at all (single-user / no-remote mode): ownership is confirmed for this host. Proceed normally.crash-recovery.md) with signal_type=LOCK_RECLAIM, parsing prev_hostname from --check output and using the current hostname as current_hostname. If the procedure returns reclaim, run ./.aitask-scripts/aitask_pick_own.sh <task_num> --email "<email>" to refresh the lock to this host before proceeding. If decline, return to the calling skill's task selection. (Same-host crash recovery is moot here: by the time Step 7 fires, Step 4's aitask_pick_own.sh already owned the lock and surfaced any RECLAIM_CRASH: signal.)Implementing, or assigned_to is empty/missing, or assigned_to does not match the current user's email): Ownership was not properly acquired. Display: "Guard: task ownership not confirmed — acquiring ownership now."
./.aitask-scripts/aitask_pick_own.sh <task_num> --email "<email>"
OWNED:<task_id> — Success. Proceed.LOCK_FAILED:<owner>|<locked_at>|<hostname> — Parse the |-separated fields. Use AskUserQuestion with options: "Force unlock and claim" / "Abort task". If force unlock, re-run with --force. If abort, execute the Task Abort Procedure (see task-abort.md).LOCK_ERROR:<message> — Display error. Use AskUserQuestion: "Retry" / "Continue without lock" / "Abort". Handle as in Step 4.LOCK_INFRA_MISSING — Inform user to run ait setup and abort.Record implementing agent: Execute the Agent Attribution Procedure (see agent-attribution.md) to record which code agent and model is implementing this task.
Repository structure awareness: Before starting implementation, read repo-structure.md
Cross-repo child assignment (post-approval creation): If cross_repo_planned is true (set in planning.md §6.1 — the approved plan is a cross-repo paired design), execute the Cross-Repo Child Assignment Procedure (see cross-repo-child-assignment.md) now. It creates the cross-repo parent first, then assigns all children (local + cross-repo) to their parents with their plans, demotes the local parent to a parent-of-children, and presents its own child checkpoint. When it returns, the workflow has ended (via that checkpoint's "Start first child" / "Stop here") — do NOT continue with the normal single-task implementation below or proceed to Step 8. (This is the post-approval creation gate: planning runs in read-only plan mode, so no tasks were created during Step 6.)
Risk fields (post-approval write): If the approved plan contains a ## Risk section (authored by the Risk Evaluation Procedure during planning), write the two decided levels to the task's frontmatter now:
./.aitask-scripts/aitask_update.sh --batch <task_id> \
--risk-code-health <risk_level_code_health> \
--risk-goal-achievement <risk_level_goal_achievement>
Skip silently if the plan has no ## Risk section (e.g. the task is not risk-gated). This is the post-approval write gate: planning runs in read-only plan mode, so the fields are not written during Step 6.
Follow the approved plan, working in the directory specified in the plan metadata.
Update the external plan file as you progress:
IMPORTANT: Do NOT commit changes automatically after implementation. Proceed to Step 8 for user review and approval.
Note: When committing implementation changes (in Step 8), the commit message must follow the <issue_type>: <description> (t<task_id>) format. See Step 8 for details.
⚠️ NON-SKIPPABLE — Auto mode and execution profiles do NOT bypass this review.
The AskUserQuestion below is load-bearing infrastructure, not a routine
confirmation. Auto mode's "minimize interruptions / prefer assumptions for
routine decisions" guidance and execution-profile shortcuts
(skip_task_confirmation, post_plan_action, etc.) target other prompts in
the flow — they do NOT cover this review. The only valid skips are profile
keys explicitly named in this SKILL.md as covering Step 8 review (currently:
none). Skipping this prompt removes the user's last chance to test the change
before it lands in git.
Explicit acceptance required — every iteration. When the user picks "Need more changes", the loop returns to the top of Step 8: after applying the requested changes, the AskUserQuestion review prompt MUST be re-issued. Repeat for every iteration. The ONLY green light to commit is the user explicitly selecting "Commit changes" with no accompanying notes, requests, or open concerns. Tacit consent — silence, lack of objection, "looks fine I guess", a comment that mentions any further change — is NOT acceptance; keep iterating. There is no upper bound on iterations.
After implementation is complete, the user MUST be given the opportunity to review and test changes before any commits are made.
Show change summary:
git status
git diff --stat
Ask for user approval using AskUserQuestion:
If "Commit changes":
plan-externalization.md) as a reactive safety fallback before touching the plan file. It is a no-op (PLAN_EXISTS) if the plan was already externalized in Step 6, and it recovers from ~/.claude/plans/ if Step 6 was skipped. If the procedure reports NOT_FOUND:no_internal_files / no_internal_dir, warn the user: "No plan file exists in aiplans/ and no recent internal plan was found. The implementation will be committed without a plan file update." and skip the consolidation and plan-commit sub-steps below. Other code agents write plans directly to aiplans/ and skip this check.aiplans/git diff --stat against the plan to identify any changes not yet documented## Final Implementation Notes
- **Actual work done:** <summary of what was actually implemented vs what was originally planned>
- **Deviations from plan:** <any changes from the original approach and why>
- **Issues encountered:** <problems found during implementation and how they were resolved>
- **Key decisions:** <technical decisions made during implementation>
- **Upstream defects identified:** Did diagnosis surface a separate, pre-existing bug in a different script/helper/module — whether or not it *caused* the current symptom? Anything you noticed about another piece of code that is broken or wrong belongs here, including defects that are out of scope for the current task or "possibly worth a separate issue". List each defect as a bullet of the form `path/to/file.ext:LINE — short summary` (e.g. `aitask_brainstorm_delete.sh:109-111 — worktree-prune ordering bug leaves stale crew-brainstorm-<N> branch`). Write `None` (verbatim) only if no related defect was identified — this subsection is read by Step 8b. Do not list style/lint cleanups, refactor opportunities, test gaps (those go through `/aitask-qa`), or unrelated TODOs.
**All related defects go here, in this canonical bullet.** Do not record related defects under a separate side bullet (e.g. `- **Trailing-slash follow-up:**`, `- **Possibly worth a separate issue:**`), an "Out of scope" section, or free prose. Step 8b parses this single bullet by name; anything written elsewhere is invisible to the follow-up offer.
*Anti-example (do not do this):* canonical bullet writes `None` and a side bullet `- **Trailing-slash follow-up:**` carries the actual defect. The parser sees `None`, the user never gets the follow-up offer, and the defect is silently buried in the archived plan.
- **Notes for sibling tasks:** <patterns established, gotchas discovered, shared code created, or other information useful for subsequent child tasks> (include this section if this is a child task)
contributor-attribution.md) to determine whether the commit needs an imported-contributor block.code-agent-commit-attribution.md) to resolve a Co-Authored-By trailer from implemented_with. If agent attribution fails, continue with the contributor-only or plain commit message as applicable.git, plan uses ./ait git):
git add <changed_code_files>
git commit -m "$(cat <<'EOF'
<issue_type>: <description> (t<task_id>)
<optional imported contributor block>
<optional code-agent trailer>
EOF
)"
Only include implementation files — never include aitasks/ or aiplans/ paths. Skip this commit if there are no code changes. If neither attribution procedure returns content, the code commit can remain a single-line subject../ait git add aiplans/<plan_file>
./ait git commit -m "ait: Update plan for t<task_id>"
Skip if the plan file was not modified.<issue_type>: <description> (t<task_id>) format, where <issue_type> comes from the task's issue_type frontmatter (one of: bug, chore, documentation, enhancement, feature, performance, refactor, style, test). The (t<task_id>) suffix is used by aitask_issue_update.sh to find commits. Examples: feature: Add channel settings screen (t16), bug: Fix login validation (t16_2).Based on PR:; for issue-imported contributor metadata it may be only the contributor trailer.ait: prefix (e.g., ait: Update plan for t16). Administrative commits (status changes, archival) also use ait: and must NOT include the (t<task_id>) tag.aitasks//aiplans/ files in the same git add or commit. Code uses regular git; task/plan files use ./ait git. This separation is required when task data lives on a separate branch, and is safe in legacy mode where ./ait git passes through to plain git./aitask-qa <task_id> after implementation.If "Need more changes":
aiplans/## Post-Review Changes
### Change Request 1 (YYYY-MM-DD HH:MM)
- **Requested by user:** <summary of what the user asked for>
- **Changes made:** <summary of what was actually implemented>
- **Files affected:** <list of modified files>
If "Abort":
task-abort.md)Entered from Step 8 after the "Commit changes" branch has committed code and plan files. Offers the user a chance to spawn a standalone aitask for an upstream defect surfaced during diagnosis (when the failure was seeded by a separate, pre-existing bug elsewhere — a different script, helper, or module).
Execute the Upstream Defect Follow-up Procedure (see upstream-followup.md) with:
task_file, task_id, is_child, active_profile, parent_id from the current context.task_slug — filename stem with the t<id>_ prefix stripped (e.g. aitasks/t42_add_login.md → add_login).When the procedure returns, proceed to Step 8c.
Entered from Step 8b (or directly from Step 8 if 8b was a no-op). At this point code and plan files have already been committed. Offers the user a chance to queue a standalone manual-verification task that will be picked after this task archives.
Execute the Manual Verification Follow-up Procedure (see manual-verification-followup.md) with:
task_file, task_id, is_child, active_profile, parent_id from the current context.task_slug — filename stem with the t<id>_ prefix stripped (e.g. aitasks/t42_add_login.md → add_login).
When the procedure returns, proceed to Step 9.Execute the post-implementation cleanup steps.
If a separate branch was created:
⚠️ NON-SKIPPABLE — Auto mode and execution profiles do NOT bypass this merge approval.
The AskUserQuestion below is a workflow gate, not a routine confirmation. The following do NOT cover this prompt:
The only valid skips are profile keys explicitly named in this SKILL.md as covering Step 9 merge approval (currently: none) or the user explicitly authorizing the merge in chat before the prompt fires.
IMPORTANT: Use AskUserQuestion to ask: "Proceed with merge of code changes to main branch?" with options "Yes, proceed with merge" / "No, not yet". Do NOT proceed until the user approves.
Check for uncommitted changes:
git status --porcelain
Merge branch into main:
git checkout main
git merge aitask/<task_name>
Handle merge conflicts: Ask user for guidance if needed.
Verify implementation (build / tests / lint):
Do not re-derive which gates this task declares — the gate orchestrator owns that decision and reports it. Dispatch it once, capturing both its output and exit status, then branch on the result:
gates_out="$(./ait gates run <task_id> 2>&1)"; gates_rc=$?
If gates_rc is nonzero — an infrastructure failure (ait/wrapper
error, task resolution failed, Python unavailable, bad registry path, usage
error). ait gates run exits 0 for every normal gate outcome (a fail/error
is a recorded result, not a process error), so a nonzero exit is never an
ordinary gate failure. STOP and diagnose using gates_out; do NOT fall
through to either branch below (the declared-vs-not decision is only meaningful
on a clean exit).
Else if gates_out contains the line No gates declared; nothing to do. —
the task has not opted into the gate system (the common case today). Run the
legacy inline build verification:
aitasks/metadata/project_config.yaml and check the verify_build fieldverify_build is absent, null, or empty (or file doesn't exist): Display "No verify_build configured — skipping build verification." and skip this step.verify_build is a single command string: Run it.verify_build is a list of commands: Run each sequentially (stop on first failure).git diff against the base)Otherwise — the orchestrator ran the task's declared gates and recorded
each run itself. Read its per-gate report lines ( <gate>: <status> …) and
act per status:
pass / skip — satisfied (skip = not applicable, e.g. no command configured); continue.fail — an ordinary gate failure: inspect ./ait gate log <task_id> <gate> and diff against the base. If caused by this task, fix and re-run ./ait gates run <task_id>; repeat until it passes. If pre-existing/unrelated, record ./ait gate fail <task_id> <gate> --reason "…" and log it in the plan's Final Implementation Notes.error ( <gate>: error …) or a malformed-correction line ( ⚠ <gate>: malformed …) — a verifier infrastructure failure (launch failure, timeout, exit 3, or a status that contradicted the exit code), NOT an ordinary gate result. Diagnose the verifier/config (its log, the command, the timeout); do not "fix the code" as if it were a fail, do not record a manual pass, and do not proceed to archival until the verifier itself runs cleanly.blocked: … — an unlocked gate could not run / none remain runnable. blocked: exhausted … or blocked: upstream … not satisfied means the gate is unsatisfied — surface and diagnose; do not treat it as satisfied or proceed. blocked: pending human signal → route to the human sign-off action (never self-signal).pending (human gate) — surface to the user; never self-signal.Clean up branch and worktree:
git worktree remove aiwork/<task_name>
rm -rf aiwork/<task_name>
git branch -d aitask/<task_name>
For child tasks — verify plan completeness before archival:
aiplans/p<parent>/<child_plan>Run the archive script:
All archival operations (metadata updates, file moves, lock releases, folded task cleanup, git staging, and commit) are handled by a single script call:
For parent tasks:
./.aitask-scripts/aitask_archive.sh <task_num>
For child tasks:
./.aitask-scripts/aitask_archive.sh <parent>_<child>
The script automatically handles:
Gate guard — pending declared gates (handle BEFORE parsing the success output):
The archive script refuses to archive a task whose declared gates: are not all
pass: it exits non-zero (code 2) and prints a GATE_PENDING:<csv> line (plus a
GATE_BLOCKED line). If you see that, the archival did not happen — do NOT
treat it as success or run the parse step below. (A task with no declared gates,
or all gates passing, exits 0 and archives straight through — the common case
today.) Instead use AskUserQuestion:
Question: "Task t<task_id> can't archive yet — pending gate(s): . How would you like to proceed?"
Header: "Gates"
Options:
If "Resolve now & archive": For each pending gate the user can satisfy now (run docs/tests, perform the review, etc.), record the pass:
./.aitask-scripts/aitask_gate.sh append <task_id> <gate> pass [k=v ...]
For a procedure-backed gate (kind: procedure — e.g. docs_updated; check
./.aitask-scripts/aitask_gate.sh procedure-gates <task_id>), do not hand-append
a pass — dispatch its skill instead (as in Step 8): begin-procedure <task_id> <gate> → Read-and-follow the gate's aitask-gate-<name> skill in your agent's
skill tree, which records the terminal pass/skip/fail itself.
After each, re-check ./.aitask-scripts/aitask_gate.sh archive-ready <task_id>.
The moment it prints ALL_PASS, re-run the archive script (same command as
above) and continue with the normal success-path parsing below — no re-pick
needed (the archival commit persists the recorded gate runs). If a gate
genuinely cannot be satisfied in this session (e.g. an async reviewer you do
not control), fall through to "Defer".
If "Defer — keep in-flight": Do not archive. The task stays active
(Implementing) and re-enterable — its committed code and recorded gate runs
are the resume state, and the task lock is intentionally left held. Inform the
user: "Archival deferred — t<task_id> stays in-flight. Re-pick it with
/aitask-pick <task_id> once the pending gate(s) pass." Skip the
push-after-archival step and proceed directly to Step 9b (Satisfaction
Feedback) — the implementation work was completed.
Parse the script output and handle interactive follow-ups:
The script outputs structured lines. Parse each line and handle accordingly:
ISSUE:<task_num>:<issue_url> — Execute the Issue Update Procedure (see issue-update.md) for the taskRELATED_ISSUE:<task_num>:<issue_url> — A related/merged issue. Execute the Related Issue Update Procedure (see issue-update.md, "Related Issues" section) using --issue-urlPARENT_ISSUE:<task_num>:<issue_url> — Execute the Issue Update Procedure (see issue-update.md) for the parent taskPARENT_RELATED_ISSUE:<task_num>:<issue_url> — A related/merged issue on the parent. Execute the Related Issue Update Procedure (see issue-update.md, "Related Issues" section) using --issue-urlFOLDED_RELATED_ISSUE:<folded_task_num>:<issue_url> — A related issue on a folded task (file deleted). Handle identically to FOLDED_ISSUE: below (same AskUserQuestion, same --issue-url commands, same task_id note)FOLDED_ISSUE:<folded_task_num>:<issue_url> — The folded task's file has been deleted, so the standard Issue Update Procedure cannot be used (it requires the task file). Instead, handle inline:
AskUserQuestion:
./.aitask-scripts/aitask_issue_update.sh --issue-url "<issue_url>" --close <task_id>
./.aitask-scripts/aitask_issue_update.sh --issue-url "<issue_url>" <task_id>
./.aitask-scripts/aitask_issue_update.sh --issue-url "<issue_url>" --close --no-comment <task_id>
task_id (not folded_task_num) so the comment references the primary task's commits and plan filePR:<task_num>:<pr_url> — Execute the PR Close/Decline Procedure (see pr-close-decline.md) for the taskPARENT_PR:<task_num>:<pr_url> — Execute the PR Close/Decline Procedure (see pr-close-decline.md) for the parent taskFOLDED_PR:<folded_task_num>:<pr_url> — The folded task's file has been deleted, so the standard PR Close/Decline Procedure cannot be used. Instead, handle inline:
AskUserQuestion:
./.aitask-scripts/aitask_pr_close.sh --pr-url "<pr_url>" --close <task_id>
./.aitask-scripts/aitask_pr_close.sh --pr-url "<pr_url>" <task_id>
./.aitask-scripts/aitask_pr_close.sh --pr-url "<pr_url>" --close --no-comment <task_id>
task_id (not folded_task_num) so the comment references the primary task's commits and plan fileFOLDED_WARNING:<task_num>:<status> — Warn the user: "Folded task t has status '' — skipping automatic deletion. Please handle it manually."PARENT_ARCHIVED:<path> — Inform user: "All child tasks complete! Parent task also archived."COMMITTED:<hash> — Archival commit was createdPush after archival:
./ait git push
Execute the Satisfaction Feedback Procedure (see satisfaction-feedback.md) with skill_name and detected_agent_string from the context variables.
The following procedures are in individual files — read on demand when referenced:
task-abort.md) — Lock release, status revert, worktree cleanup. Referenced from Step 6 checkpoint and Step 8.issue-update.md) — Update/close linked issues during archival. Referenced from Step 9.pr-close-decline.md) — Close/decline linked pull requests during archival. Referenced from Step 9.contributor-attribution.md) — Credit PR contributors in commit messages. Referenced from Step 8.code-agent-commit-attribution.md) — Resolve code-agent Co-Authored-By trailer. Referenced from Step 8.plan-externalization.md) — Claude Code only. Copy the approved internal plan file to aiplans/ and parse externalize helper output. Referenced from planning.md (Step 6) and Step 8.model-self-detection.md) — Detect the current code agent and model. Referenced from Agent Attribution and Satisfaction Feedback.agent-attribution.md) — Record implementing code agent and model. Referenced from Step 7.satisfaction-feedback.md) — Collect user feedback and update verified model scores. Referenced from Step 9b and standalone skills.lock-release.md) — Release task locks. Referenced from Task Abort Procedure.crash-recovery.md) — Surveys in-progress work and prompts the user when a reclaim signal is detected (multi-PC, same-host crash via PID anchor, or lock anomaly). Referenced from Step 4 dispatcher and Step 7 ownership guard.manual-verification.md) — Interactive checklist runner for issue_type: manual_verification tasks. Referenced from Step 3 (Check 3).auto-verification.md) — Automated verification for manual_verification tasks. Supports two strategies: autonomous (execute inline, document at end) and pre-built (design plan, optionally approve, then execute). Persists to aiplans/p<id>_manual_verification_auto.md. Referenced from manual-verification.md Step 1.5 (whole checklist) and Step 2 (per-item auto verb).manual-verification-followup.md) — Post-implementation prompt offering to create a standalone manual-verification task, with multi-source candidate discovery. Referenced from Step 8c.upstream-followup.md) — Post-implementation prompt offering to spawn a standalone bug aitask for an upstream defect surfaced during diagnosis. Reads the plan file's "Upstream defects identified" subsection. Referenced from Step 8b.remote-drift-check.md) — Warn before implementation if origin/<base-branch> is ahead of local, with strong emphasis on files the plan touches. Referenced from planning.md Checkpoint.execution-profile-selection.md) — Interactive profile scan and selection. Referenced from Step 0a in calling skills.execution-profile-selection-auto.md) — Non-interactive auto-select for remote/web skills. Referenced from Step 1 in aitask-pickrem/aitask-pickweb.task-creation-batch.md) — Canonical command templates for creating tasks via aitask_create.sh --batch. Referenced from planning.md and multiple skills (explore, review, qa, wrap, pr-import, revert).aiplans/archived/p<parent>/) over archived task files (aitasks/archived/t<parent>/). Plan files contain the full implementation record; task files are just initial proposals. Only use archived task files as fallback when no corresponding plan exists.aitasks/archived/t<parent>/ preserving the directory structureaiplans/archived/p<parent>/ preserving the directory structureupdated_at field in frontmatter to the current date/time using format YYYY-MM-DD HH:MMt{parent}_{child}_description.md where both parent and child identifiers are numbers only. Do not insert tasks "in-between" (e.g., no t10_1b between t10_1 and t10_2). If you discover a missing implementation step, add it as the next available number and adjust dependencies accordinglyissue field, the workflow offers to update/close the linked issue using aitask_issue_update.sh. The SKILL.md workflow is platform-agnostic; the script handles platform specifics (GitHub, GitLab, etc.). It auto-detects commits and includes "Final Implementation Notes" from the archived plan file.folded_tasks frontmatter field (set by aitask-explore or aitask-fold), the listed tasks are deleted during Step 9 archival. Folded tasks have status Folded with a folded_into property pointing to the primary task. They are deleted (not archived) because their full content was incorporated into the primary task's description at creation/fold time.handle_folded_tasks() in both parent and child archival paths. /aitask-fold and manual folding can add folded_tasks to any task type.aitask-data branch, aitasks/ and aiplans/ are symlinks to .aitask-data/. See repo-structure.md for the full architecture and rules.Project-level settings are stored in aitasks/metadata/project_config.yaml (git-tracked, shared across team). This is separate from execution profiles (workflow behavior) and userconfig.yaml (per-user, gitignored).
| Key | Type | Default | Description | Used in |
|---|---|---|---|---|
verify_build | string or list | (none — skip) | Shell command(s) to verify the build after implementation | Step 9; build_verified gate |
test_command | string or list | (none — auto-detect) | Shell command(s) for running project tests | aitask-qa Step 4; tests_pass gate |
lint_command | string or list | (none — skip) | Shell command(s) for linting project code | aitask-qa Step 4; lint gate |
attachments_gc_grace | duration (30d/24h/90m/120s/int seconds) | 30d | Grace window before a fully-orphaned attachment (no active or archived task references it) is reclaimed by ait attach gc. Archiving never decrefs, so an archived task's attachments are kept indefinitely; this knob only governs blobs left unreferenced by ait attach rm or task deletion. | ait attach gc |
If the file does not exist or a field is absent, the corresponding feature is skipped.
Full reference: See
profiles.mdfor the complete profile schema, available keys, and customization guide.
Profiles are YAML files in aitasks/metadata/profiles/ that pre-answer workflow questions. Default profiles: default (all questions asked) and fast (skip confirmations).