work-kit-cli 0.2.4 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -104,7 +104,7 @@ Any stage can route back to a previous stage. Each route is enforced with a max
104
104
  ### Output
105
105
 
106
106
  ```
107
- .claude/work-kit/
107
+ .work-kit-tracker/
108
108
  2026-04-03-avatar-upload.md # distilled summary
109
109
  archive/
110
110
  2026-04-03-avatar-upload.md # full state.md copy
@@ -0,0 +1,103 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import * as fs from "node:fs";
3
+ import * as path from "node:path";
4
+ import { readState, findWorktreeRoot, stateDir } from "../state/store.js";
5
+
6
+ export interface CancelResult {
7
+ action: "cancelled" | "error";
8
+ slug?: string;
9
+ branch?: string;
10
+ worktreeRemoved: boolean;
11
+ branchDeleted: boolean;
12
+ message: string;
13
+ }
14
+
15
+ function resolveMainRepoRoot(worktreeRoot: string): string {
16
+ try {
17
+ const output = execFileSync("git", ["worktree", "list", "--porcelain"], {
18
+ cwd: worktreeRoot,
19
+ encoding: "utf-8",
20
+ timeout: 5000,
21
+ });
22
+ const firstLine = output.split("\n").find(l => l.startsWith("worktree "));
23
+ if (firstLine) return firstLine.slice("worktree ".length).trim();
24
+ } catch {
25
+ // fallback
26
+ }
27
+ return worktreeRoot;
28
+ }
29
+
30
+ export function cancelCommand(worktreeRoot?: string): CancelResult {
31
+ const root = worktreeRoot || findWorktreeRoot();
32
+ if (!root) {
33
+ return {
34
+ action: "error",
35
+ worktreeRemoved: false,
36
+ branchDeleted: false,
37
+ message: "No work-kit state found. Nothing to cancel.",
38
+ };
39
+ }
40
+
41
+ const state = readState(root);
42
+
43
+ if (state.status === "completed") {
44
+ return {
45
+ action: "error",
46
+ slug: state.slug,
47
+ worktreeRemoved: false,
48
+ branchDeleted: false,
49
+ message: `${state.slug} is already completed. Nothing to cancel.`,
50
+ };
51
+ }
52
+
53
+ const slug = state.slug;
54
+ const branch = state.branch;
55
+ const mainRoot = resolveMainRepoRoot(root);
56
+ const isWorktree = path.resolve(root) !== path.resolve(mainRoot);
57
+
58
+ let worktreeRemoved = false;
59
+ let branchDeleted = false;
60
+
61
+ // Remove .work-kit/ state directory
62
+ const stDir = stateDir(root);
63
+ if (fs.existsSync(stDir)) {
64
+ fs.rmSync(stDir, { recursive: true, force: true });
65
+ }
66
+
67
+ // Remove the worktree (if we're in one)
68
+ if (isWorktree) {
69
+ try {
70
+ execFileSync("git", ["worktree", "remove", root, "--force"], {
71
+ cwd: mainRoot,
72
+ encoding: "utf-8",
73
+ timeout: 10000,
74
+ });
75
+ worktreeRemoved = true;
76
+ } catch {
77
+ // Worktree removal failed — may need manual cleanup
78
+ }
79
+ }
80
+
81
+ // Delete the feature branch
82
+ if (branch) {
83
+ try {
84
+ execFileSync("git", ["branch", "-D", branch], {
85
+ cwd: mainRoot,
86
+ encoding: "utf-8",
87
+ timeout: 5000,
88
+ });
89
+ branchDeleted = true;
90
+ } catch {
91
+ // Branch may not exist or may be checked out elsewhere
92
+ }
93
+ }
94
+
95
+ return {
96
+ action: "cancelled",
97
+ slug,
98
+ branch,
99
+ worktreeRemoved,
100
+ branchDeleted,
101
+ message: `Cancelled ${slug}.${worktreeRemoved ? " Worktree removed." : ""}${branchDeleted ? " Branch deleted." : ""}`,
102
+ };
103
+ }
@@ -108,8 +108,16 @@ export function completeCommand(target: string, outcome?: string, worktreeRoot?:
108
108
  return { action: "complete", message: "All phases complete. Work-kit finished." };
109
109
  }
110
110
 
111
- state.currentPhase = null;
112
- state.currentSubStage = null;
111
+ // Mark the first pending sub-stage of the next phase as "waiting"
112
+ // so the observer can distinguish "running" from "waiting for human"
113
+ const nextSubs = Object.entries(state.phases[nextPhase].subStages);
114
+ const firstPending = nextSubs.find(([_, ss]) => ss.status === "pending");
115
+ if (firstPending) {
116
+ firstPending[1].status = "waiting";
117
+ }
118
+
119
+ state.currentPhase = nextPhase;
120
+ state.currentSubStage = firstPending ? firstPending[0] : null;
113
121
  writeState(root, state);
114
122
 
115
123
  return {
@@ -156,7 +164,7 @@ function archiveCompleted(worktreeRoot: string, state: WorkKitState): void {
156
164
  const mainRoot = resolveMainRepoRoot(worktreeRoot);
157
165
  const date = new Date().toISOString().split("T")[0];
158
166
  const slug = state.slug;
159
- const wkDir = path.join(mainRoot, ".claude", "work-kit");
167
+ const wkDir = path.join(mainRoot, ".work-kit-tracker");
160
168
  const archiveDir = path.join(wkDir, "archive");
161
169
 
162
170
  // Ensure directories exist
@@ -91,6 +91,19 @@ ${description}
91
91
  return md;
92
92
  }
93
93
 
94
+ function ensureGitignored(worktreeRoot: string): void {
95
+ const gitignorePath = path.join(worktreeRoot, ".gitignore");
96
+ const entry = ".work-kit/";
97
+
98
+ if (fs.existsSync(gitignorePath)) {
99
+ const content = fs.readFileSync(gitignorePath, "utf-8");
100
+ if (content.split("\n").some((line) => line.trim() === entry)) return;
101
+ fs.appendFileSync(gitignorePath, `\n${entry}\n`);
102
+ } else {
103
+ fs.writeFileSync(gitignorePath, `${entry}\n`);
104
+ }
105
+ }
106
+
94
107
  export function initCommand(options: {
95
108
  mode: "full" | "auto";
96
109
  description: string;
@@ -171,6 +184,9 @@ export function initCommand(options: {
171
184
  },
172
185
  };
173
186
 
187
+ // Ensure .work-kit/ is gitignored (temp working state, not for commits)
188
+ ensureGitignored(worktreeRoot);
189
+
174
190
  // Write state files
175
191
  writeState(worktreeRoot, state);
176
192
  writeStateMd(worktreeRoot, generateStateMd(slug, branch, modeLabel, description, classification, workflow));
@@ -48,7 +48,7 @@ export function nextCommand(worktreeRoot?: string): Action {
48
48
  state.phases[phase].startedAt = new Date().toISOString();
49
49
 
50
50
  const subStages = Object.entries(state.phases[phase].subStages);
51
- const firstActive = subStages.find(([_, ss]) => ss.status === "pending");
51
+ const firstActive = subStages.find(([_, ss]) => ss.status === "pending" || ss.status === "waiting");
52
52
 
53
53
  if (!firstActive) {
54
54
  return { action: "error", message: `No pending sub-stages in ${phase}` };
@@ -30,12 +30,17 @@ export async function observeCommand(opts: { mainRepo?: string }): Promise<void>
30
30
  : findMainRepoRoot(process.cwd());
31
31
 
32
32
  let scrollOffset = 0;
33
+ let tick = 0;
34
+ let tickInterval: ReturnType<typeof setInterval> | null = null;
33
35
  let cleanedUp = false;
34
36
 
35
37
  function cleanup(): void {
36
38
  if (cleanedUp) return;
37
39
  cleanedUp = true;
38
40
 
41
+ // Stop tick interval
42
+ if (tickInterval) { clearInterval(tickInterval); tickInterval = null; }
43
+
39
44
  // Restore terminal
40
45
  exitAlternateScreen();
41
46
  if (process.stdin.isTTY && process.stdin.setRawMode) {
@@ -54,7 +59,7 @@ export async function observeCommand(opts: { mainRepo?: string }): Promise<void>
54
59
  }
55
60
 
56
61
  const data = collectDashboardData(mainRepoRoot, watcher.getWorktrees());
57
- const frame = moveCursorHome() + renderDashboard(data, width, height, scrollOffset);
62
+ const frame = moveCursorHome() + renderDashboard(data, width, height, scrollOffset, tick);
58
63
  process.stdout.write(frame);
59
64
  }
60
65
 
@@ -80,6 +85,12 @@ export async function observeCommand(opts: { mainRepo?: string }): Promise<void>
80
85
  // Initial render
81
86
  render();
82
87
 
88
+ // Tick interval for flashing active stage indicator
89
+ tickInterval = setInterval(() => {
90
+ tick++;
91
+ render();
92
+ }, 500);
93
+
83
94
  // Handle terminal resize
84
95
  process.stdout.on("resize", () => {
85
96
  render();
@@ -30,7 +30,7 @@ export function statusCommand(worktreeRoot?: string): StatusOutput {
30
30
  if (ss.status === "skipped") continue;
31
31
  total++;
32
32
  if (ss.status === "completed") completed++;
33
- else if (ss.status === "in-progress") active++;
33
+ else if (ss.status === "in-progress" || ss.status === "waiting") active++;
34
34
  }
35
35
  phases[phase] = { status: ps.status, completed, total, active };
36
36
  }
@@ -17,7 +17,7 @@ export function nextSubStageInPhase(state: WorkKitState, phase: PhaseName): stri
17
17
 
18
18
  for (const ss of subStages) {
19
19
  const ssState = phaseState.subStages[ss];
20
- if (ssState && (ssState.status === "pending" || ssState.status === "in-progress")) {
20
+ if (ssState && (ssState.status === "pending" || ssState.status === "in-progress" || ssState.status === "waiting")) {
21
21
  return ss;
22
22
  }
23
23
  }
package/cli/src/index.ts CHANGED
@@ -16,6 +16,7 @@ import { completionsCommand } from "./commands/completions.js";
16
16
  import { observeCommand } from "./commands/observe.js";
17
17
  import { uninstallCommand } from "./commands/uninstall.js";
18
18
  import { bootstrapCommand } from "./commands/bootstrap.js";
19
+ import { cancelCommand } from "./commands/cancel.js";
19
20
  import { bold, green, yellow, red } from "./utils/colors.js";
20
21
  import type { Classification, PhaseName } from "./state/schema.js";
21
22
 
@@ -269,4 +270,21 @@ program
269
270
  }
270
271
  });
271
272
 
273
+ // ── cancel ──────────────────────────────────────────────────────────
274
+
275
+ program
276
+ .command("cancel")
277
+ .description("Cancel the active work-kit, remove worktree and branch")
278
+ .option("--worktree-root <path>", "Override worktree root")
279
+ .action((opts) => {
280
+ try {
281
+ const result = cancelCommand(opts.worktreeRoot);
282
+ console.log(JSON.stringify(result, null, 2));
283
+ process.exit(result.action === "error" ? 1 : 0);
284
+ } catch (e: any) {
285
+ console.error(JSON.stringify({ action: "error", message: e.message }));
286
+ process.exit(1);
287
+ }
288
+ });
289
+
272
290
  program.parse();
@@ -16,6 +16,7 @@ export interface WorkItemView {
16
16
  currentPhase: string | null;
17
17
  currentSubStage: string | null;
18
18
  currentPhaseStartedAt?: string;
19
+ currentSubStageStatus?: string;
19
20
  currentSubStageIndex?: number;
20
21
  currentPhaseTotal?: number;
21
22
  startedAt: string;
@@ -92,6 +93,7 @@ export function collectWorkItem(worktreeRoot: string): WorkItemView | null {
92
93
 
93
94
  // Track current phase substage position
94
95
  let currentPhaseStartedAt: string | undefined;
96
+ let currentSubStageStatus: string | undefined;
95
97
  let currentSubStageIndex: number | undefined;
96
98
  let currentPhaseTotal: number | undefined;
97
99
 
@@ -105,9 +107,11 @@ export function collectWorkItem(worktreeRoot: string): WorkItemView | null {
105
107
  continue;
106
108
  }
107
109
 
110
+ // If any sub-stage is "waiting", show the phase as waiting in the view
111
+ const hasWaiting = Object.values(phase.subStages).some(ss => ss.status === "waiting");
108
112
  phaseViews.push({
109
113
  name: phaseName,
110
- status: phase.status,
114
+ status: hasWaiting ? "waiting" : phase.status,
111
115
  startedAt: phase.startedAt,
112
116
  completedAt: phase.completedAt,
113
117
  });
@@ -134,10 +138,12 @@ export function collectWorkItem(worktreeRoot: string): WorkItemView | null {
134
138
  if (phaseName === state.currentPhase) {
135
139
  currentPhaseStartedAt = phase.startedAt;
136
140
  currentPhaseTotal = activeKeys.length;
137
- const idx = state.currentSubStage
138
- ? activeKeys.indexOf(state.currentSubStage)
139
- : -1;
140
- currentSubStageIndex = idx >= 0 ? idx + 1 : undefined;
141
+ if (state.currentSubStage) {
142
+ const idx = activeKeys.indexOf(state.currentSubStage);
143
+ currentSubStageIndex = idx >= 0 ? idx + 1 : undefined;
144
+ const ss = phase.subStages[state.currentSubStage];
145
+ currentSubStageStatus = ss?.status;
146
+ }
141
147
  }
142
148
  }
143
149
  }
@@ -166,6 +172,7 @@ export function collectWorkItem(worktreeRoot: string): WorkItemView | null {
166
172
  currentPhase: state.currentPhase,
167
173
  currentSubStage: state.currentSubStage,
168
174
  currentPhaseStartedAt,
175
+ currentSubStageStatus,
169
176
  currentSubStageIndex,
170
177
  currentPhaseTotal,
171
178
  startedAt: state.started,
@@ -188,7 +195,7 @@ function getAutoKitPhases(state: WorkKitState): PhaseName[] {
188
195
  // ── Collect Completed Items ─────────────────────────────────────────
189
196
 
190
197
  export function collectCompletedItems(mainRepoRoot: string): CompletedItemView[] {
191
- const indexPath = path.join(mainRepoRoot, ".claude", "work-kit", "index.md");
198
+ const indexPath = path.join(mainRepoRoot, ".work-kit-tracker", "index.md");
192
199
  if (!fs.existsSync(indexPath)) return [];
193
200
 
194
201
  let content: string;
@@ -252,11 +259,13 @@ export function collectDashboardData(mainRepoRoot: string, cachedWorktrees?: str
252
259
  });
253
260
 
254
261
  // Merge completed items from worktrees and index file, dedup by slug
262
+ // Also exclude any slug that is currently active (re-initialized features)
263
+ const activeSlugs = new Set(activeItems.map(i => i.slug));
255
264
  const indexItems = collectCompletedItems(mainRepoRoot);
256
265
  const seen = new Set(completedFromWorktrees.map(i => i.slug));
257
266
  const completedItems = [
258
- ...completedFromWorktrees,
259
- ...indexItems.filter(i => !seen.has(i.slug)),
267
+ ...completedFromWorktrees.filter(i => !activeSlugs.has(i.slug)),
268
+ ...indexItems.filter(i => !seen.has(i.slug) && !activeSlugs.has(i.slug)),
260
269
  ];
261
270
 
262
271
  return {
@@ -90,10 +90,11 @@ function renderProgressBar(
90
90
 
91
91
  // ── Phase Status Indicators ─────────────────────────────────────────
92
92
 
93
- function phaseIndicator(status: string): string {
93
+ function phaseIndicator(status: string, tick: number = 0): string {
94
94
  switch (status) {
95
95
  case "completed": return green("✓");
96
- case "in-progress": return cyan("▶");
96
+ case "in-progress": return tick % 2 === 0 ? cyan("▶") : dim("▶");
97
+ case "waiting": return tick % 2 === 0 ? yellow("◉") : dim("◉");
97
98
  case "pending": return dim("·");
98
99
  case "skipped": return dim("⊘");
99
100
  case "failed": return red("✗");
@@ -118,7 +119,7 @@ function formatMode(mode: string, classification?: string): string {
118
119
  return classification ? `${label} · ${classification}` : label;
119
120
  }
120
121
 
121
- function renderWorkItem(item: WorkItemView, innerWidth: number): string[] {
122
+ function renderWorkItem(item: WorkItemView, innerWidth: number, tick: number = 0): string[] {
122
123
  const lines: string[] = [];
123
124
 
124
125
  // Line 1: slug + branch (right-aligned)
@@ -156,16 +157,22 @@ function renderWorkItem(item: WorkItemView, innerWidth: number): string[] {
156
157
  ));
157
158
 
158
159
  // Line 4: phase indicators with sub-stage shown under current phase
159
- const phaseStrs = item.phases.map(p => `${p.name} ${phaseIndicator(p.status)}`);
160
+ const phaseStrs = item.phases.map(p => `${p.name} ${phaseIndicator(p.status, tick)}`);
160
161
  lines.push(" " + phaseStrs.join(" "));
161
162
 
162
163
  // Line 5 (optional): current sub-stage detail under the phase line
163
164
  if (item.currentSubStage && item.currentPhase) {
165
+ const isWaiting = item.currentSubStageStatus === "waiting";
164
166
  let subLabel = `↳ ${item.currentSubStage}`;
165
167
  if (item.currentSubStageIndex != null && item.currentPhaseTotal != null) {
166
168
  subLabel += ` (${item.currentSubStageIndex}/${item.currentPhaseTotal})`;
167
169
  }
168
- lines.push(" " + dim(subLabel));
170
+ if (isWaiting) {
171
+ const badge = tick % 2 === 0 ? bgYellow(" WAITING ") : dim(" WAITING ");
172
+ lines.push(" " + yellow(subLabel) + " " + badge);
173
+ } else {
174
+ lines.push(" " + (tick % 2 === 0 ? cyan(subLabel) : dim(subLabel)));
175
+ }
169
176
  }
170
177
 
171
178
  // Line 5 (optional): loopbacks
@@ -217,7 +224,8 @@ export function renderDashboard(
217
224
  data: DashboardData,
218
225
  width: number,
219
226
  height: number,
220
- scrollOffset: number = 0
227
+ scrollOffset: number = 0,
228
+ tick: number = 0
221
229
  ): string {
222
230
  const maxWidth = Math.min(width, 120);
223
231
  const innerWidth = maxWidth - 4; // account for "║ " and " ║"
@@ -261,7 +269,7 @@ export function renderDashboard(
261
269
 
262
270
  for (let i = 0; i < data.activeItems.length; i++) {
263
271
  const item = data.activeItems[i];
264
- const itemLines = renderWorkItem(item, innerWidth);
272
+ const itemLines = renderWorkItem(item, innerWidth, tick);
265
273
  for (const line of itemLines) {
266
274
  allLines.push(boxLine(line, innerWidth));
267
275
  }
@@ -38,7 +38,7 @@ export function resetToLocation(state: WorkKitState, location: Location): void {
38
38
  let reset = false;
39
39
  for (const [ss, ssState] of Object.entries(targetPhaseState.subStages)) {
40
40
  if (ss === location.subStage) reset = true;
41
- if (reset && ssState.status === "completed") {
41
+ if (reset && (ssState.status === "completed" || ssState.status === "waiting")) {
42
42
  ssState.status = "pending";
43
43
  delete ssState.completedAt;
44
44
  delete ssState.outcome;
@@ -35,7 +35,7 @@ export type Classification = "bug-fix" | "small-change" | "refactor" | "feature"
35
35
  // ── Phase & Sub-stage State ──────────────────────────────────────────
36
36
 
37
37
  export type PhaseStatus = "pending" | "in-progress" | "completed" | "skipped";
38
- export type SubStageStatus = "pending" | "in-progress" | "completed" | "skipped";
38
+ export type SubStageStatus = "pending" | "in-progress" | "completed" | "skipped" | "waiting";
39
39
 
40
40
  export interface SubStageState {
41
41
  status: SubStageStatus;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "work-kit-cli",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "description": "Structured development workflow for Claude Code. Two modes, 6 phases, 27 sub-stages.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -2,7 +2,7 @@
2
2
  name: auto-kit
3
3
  description: "Smart pipeline that analyzes the request and builds a dynamic workflow. Usage: /auto-kit <description> to start, /auto-kit to continue."
4
4
  user-invocable: true
5
- argument-hint: "[description]"
5
+ argument-hint: "[--gated] [description]"
6
6
  allowed-tools: Agent, Bash, Read, Write, Edit, Glob, Grep
7
7
  ---
8
8
 
@@ -97,7 +97,7 @@ The table is a guide, not a rigid rule. Adjust based on the actual request:
97
97
  cd worktrees/<slug>
98
98
  npx work-kit-cli init --mode auto --description "<description>" --classification <classification>
99
99
  ```
100
- If the user requested gated mode (manual approval between phases), add `--gated`.
100
+ If the user passed `--gated` (e.g., `/auto-kit --gated fix login bug`), add `--gated` to the init command. Strip `--gated` from the description text.
101
101
  2. Show the workflow to the user: `npx work-kit-cli workflow`
102
102
  3. User can adjust: `npx work-kit-cli workflow --add review/security` or `npx work-kit-cli workflow --remove test/e2e`
103
103
  4. **Wait for approval** — user can add/remove steps before proceeding
@@ -0,0 +1,34 @@
1
+ ---
2
+ name: cancel-kit
3
+ description: "Cancel the active work-kit session. Removes state, worktree, and feature branch."
4
+ user-invocable: true
5
+ allowed-tools: Bash, Read
6
+ ---
7
+
8
+ # Cancel Kit
9
+
10
+ Cancels the active work-kit session and cleans up all artifacts.
11
+
12
+ ## What it does
13
+
14
+ 1. Finds the active work-kit session (via `bootstrap`)
15
+ 2. Confirms with the user before proceeding
16
+ 3. Runs `npx work-kit-cli cancel` to:
17
+ - Remove `.work-kit/` state directory
18
+ - Remove the git worktree
19
+ - Delete the feature branch
20
+ 4. Reports what was cleaned up
21
+
22
+ ## Instructions
23
+
24
+ 1. Run `npx work-kit-cli bootstrap` to detect the active session
25
+ 2. If no active session: tell the user there's nothing to cancel
26
+ 3. If active: show the user what will be cancelled:
27
+ - Slug and branch name
28
+ - Current phase and sub-stage
29
+ - Any uncommitted work in the worktree will be lost
30
+ 4. **Ask the user to confirm** — do not proceed without explicit confirmation
31
+ 5. `cd` into the worktree directory
32
+ 6. Run `npx work-kit-cli cancel`
33
+ 7. `cd` back to the main repo root
34
+ 8. Report the result to the user
@@ -2,7 +2,7 @@
2
2
  name: full-kit
3
3
  description: "Full pipeline for feature development. Runs all phases and sub-stages in order. Usage: /full-kit <description> to start, /full-kit to continue."
4
4
  user-invocable: true
5
- argument-hint: "[description]"
5
+ argument-hint: "[--gated] [description]"
6
6
  allowed-tools: Agent, Bash, Read, Write, Edit, Glob, Grep
7
7
  ---
8
8
 
@@ -39,7 +39,7 @@ Do not proceed until `doctor` reports all checks passed.
39
39
  cd worktrees/<slug>
40
40
  npx work-kit-cli init --mode full --description "<description>"
41
41
  ```
42
- If the user requested gated mode (manual approval between phases), add `--gated`.
42
+ If the user passed `--gated` (e.g., `/full-kit --gated add user avatar`), add `--gated` to the init command. Strip `--gated` from the description text.
43
43
  2. Parse the JSON response and follow the action
44
44
  3. Continue with the execution loop below
45
45
 
@@ -13,14 +13,18 @@ description: "Deploy sub-stage: Get the PR merged safely."
13
13
  ```bash
14
14
  git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@' || echo "main"
15
15
  ```
16
- 2. Sync the feature branch with the default branch:
16
+ 2. Remove `.work-kit/` from git tracking before merging (state is transient — the archive in `.work-kit-tracker/` is the permanent record):
17
+ ```bash
18
+ git rm -r --cached .work-kit/ 2>/dev/null && git commit -m "work-kit: remove transient state before merge" || true
19
+ ```
20
+ 3. Sync the feature branch with the default branch:
17
21
  ```bash
18
22
  git fetch origin
19
23
  git rebase origin/<default-branch>
20
24
  ```
21
25
  If rebase conflicts occur, resolve them. If they're non-trivial, report to the user and abort.
22
- 3. If a PR exists, check CI status — all checks must pass. If CI fails, diagnose and fix (loop back to Build if needed).
23
- 4. Merge automatically using the project's preferred method (check CONTRIBUTING.md or README; default to squash):
26
+ 4. If a PR exists, check CI status — all checks must pass. If CI fails, diagnose and fix (loop back to Build if needed).
27
+ 5. Merge automatically using the project's preferred method (check CONTRIBUTING.md or README; default to squash):
24
28
  - If a PR exists: merge via `gh pr merge --squash --delete-branch`
25
29
  - If no PR: merge locally:
26
30
  ```bash
@@ -12,16 +12,16 @@ allowed-tools: Bash, Read, Write, Edit, Glob, Grep
12
12
 
13
13
  ## Instructions
14
14
 
15
- > **Note:** Archiving state.md and appending to `.claude/work-kit/index.md` are handled automatically by the CLI when you run `work-kit complete` on the last sub-stage. You do NOT need to do these manually.
15
+ > **Note:** Archiving state.md and appending to `.work-kit-tracker/index.md` are handled automatically by the CLI when you run `work-kit complete` on the last sub-stage. You do NOT need to do these manually.
16
16
 
17
17
  1. **Read the full `.work-kit/state.md`** — every phase output from Plan through the last completed phase
18
18
  2. **Synthesize the work-kit log entry** — not a copy-paste of state, but a distilled record that a future developer (or agent) would find useful
19
- 3. **Write the summary file** to `.claude/work-kit/<date>-<slug>.md` on the **main branch** (not the worktree)
19
+ 3. **Write the summary file** to `.work-kit-tracker/<date>-<slug>.md` on the **main branch** (not the worktree)
20
20
  4. **Ask the user** if they want the worktree and branch removed
21
21
 
22
22
  ## Work-Kit Log Entry Format
23
23
 
24
- Write to `.claude/work-kit/<YYYY-MM-DD>-<slug>.md`:
24
+ Write to `.work-kit-tracker/<YYYY-MM-DD>-<slug>.md`:
25
25
 
26
26
  ```markdown
27
27
  ---
@@ -88,7 +88,7 @@ After writing the summary:
88
88
  1. Switch to main branch: `cd` back to the main repo root
89
89
  2. Stage and commit all work-kit log files:
90
90
  ```bash
91
- git add .claude/work-kit/
91
+ git add .work-kit-tracker/
92
92
  git commit -m "work-kit: <slug>"
93
93
  ```
94
94
  3. Remove the worktree and delete the feature branch (merge already happened, cleanup is safe):