work-kit-cli 0.2.7 → 0.3.0

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.
Files changed (86) hide show
  1. package/README.md +13 -13
  2. package/cli/src/commands/bootstrap.ts +39 -13
  3. package/cli/src/commands/cancel.ts +1 -16
  4. package/cli/src/commands/complete.ts +92 -98
  5. package/cli/src/commands/completions.ts +2 -2
  6. package/cli/src/commands/doctor.ts +1 -1
  7. package/cli/src/commands/init.ts +40 -32
  8. package/cli/src/commands/loopback.ts +8 -11
  9. package/cli/src/commands/next.ts +64 -51
  10. package/cli/src/commands/pause-resume.test.ts +142 -0
  11. package/cli/src/commands/pause.ts +34 -0
  12. package/cli/src/commands/report.ts +217 -0
  13. package/cli/src/commands/resume.ts +38 -0
  14. package/cli/src/commands/setup.ts +136 -0
  15. package/cli/src/commands/status.ts +6 -6
  16. package/cli/src/commands/uninstall.ts +8 -3
  17. package/cli/src/commands/workflow.ts +27 -27
  18. package/cli/src/config/agent-map.ts +9 -9
  19. package/cli/src/config/constants.ts +44 -0
  20. package/cli/src/config/loopback-routes.ts +13 -13
  21. package/cli/src/config/project-config.test.ts +127 -0
  22. package/cli/src/config/project-config.ts +106 -0
  23. package/cli/src/config/{phases.ts → workflow.ts} +40 -23
  24. package/cli/src/context/prompt-builder.ts +10 -9
  25. package/cli/src/index.ts +63 -7
  26. package/cli/src/observer/data.ts +64 -56
  27. package/cli/src/observer/renderer.ts +162 -75
  28. package/cli/src/state/helpers.test.ts +28 -28
  29. package/cli/src/state/helpers.ts +37 -25
  30. package/cli/src/state/schema.ts +88 -45
  31. package/cli/src/state/store.ts +92 -7
  32. package/cli/src/state/validators.test.ts +13 -13
  33. package/cli/src/state/validators.ts +3 -4
  34. package/cli/src/utils/colors.ts +2 -0
  35. package/cli/src/utils/json.ts +20 -0
  36. package/cli/src/utils/time.ts +27 -0
  37. package/cli/src/{engine → workflow}/loopbacks.test.ts +2 -2
  38. package/cli/src/workflow/loopbacks.ts +42 -0
  39. package/cli/src/workflow/parallel.ts +64 -0
  40. package/cli/src/workflow/transitions.test.ts +129 -0
  41. package/cli/src/{engine → workflow}/transitions.ts +18 -22
  42. package/package.json +2 -2
  43. package/skills/auto-kit/SKILL.md +22 -22
  44. package/skills/cancel-kit/SKILL.md +4 -4
  45. package/skills/full-kit/SKILL.md +23 -23
  46. package/skills/pause-kit/SKILL.md +25 -0
  47. package/skills/resume-kit/SKILL.md +28 -0
  48. package/skills/wk-bootstrap/SKILL.md +5 -5
  49. package/skills/wk-build/SKILL.md +10 -10
  50. package/skills/wk-build/{stages → steps}/commit.md +1 -1
  51. package/skills/wk-build/{stages → steps}/core.md +3 -3
  52. package/skills/wk-build/{stages → steps}/integration.md +2 -2
  53. package/skills/wk-build/{stages → steps}/migration.md +1 -1
  54. package/skills/wk-build/{stages → steps}/red.md +1 -1
  55. package/skills/wk-build/{stages → steps}/refactor.md +1 -1
  56. package/skills/wk-build/{stages → steps}/setup.md +1 -1
  57. package/skills/wk-build/{stages → steps}/ui.md +1 -1
  58. package/skills/wk-deploy/SKILL.md +6 -6
  59. package/skills/wk-deploy/{stages → steps}/merge.md +1 -1
  60. package/skills/wk-deploy/{stages → steps}/monitor.md +1 -1
  61. package/skills/wk-deploy/{stages → steps}/remediate.md +1 -1
  62. package/skills/wk-plan/SKILL.md +13 -13
  63. package/skills/wk-plan/{stages → steps}/architecture.md +1 -1
  64. package/skills/wk-plan/{stages → steps}/audit.md +2 -2
  65. package/skills/wk-plan/{stages → steps}/blueprint.md +2 -2
  66. package/skills/wk-plan/{stages → steps}/clarify.md +1 -1
  67. package/skills/wk-plan/{stages → steps}/investigate.md +1 -1
  68. package/skills/wk-plan/{stages → steps}/scope.md +1 -1
  69. package/skills/wk-plan/{stages → steps}/sketch.md +1 -1
  70. package/skills/wk-plan/{stages → steps}/ux-flow.md +1 -1
  71. package/skills/wk-review/SKILL.md +10 -10
  72. package/skills/wk-review/{stages → steps}/compliance.md +1 -1
  73. package/skills/wk-review/{stages → steps}/handoff.md +2 -2
  74. package/skills/wk-review/{stages → steps}/performance.md +1 -1
  75. package/skills/wk-review/{stages → steps}/security.md +1 -1
  76. package/skills/wk-review/{stages → steps}/self-review.md +1 -1
  77. package/skills/wk-test/SKILL.md +8 -8
  78. package/skills/wk-test/{stages → steps}/e2e.md +1 -1
  79. package/skills/wk-test/{stages → steps}/validate.md +1 -1
  80. package/skills/wk-test/{stages → steps}/verify.md +1 -1
  81. package/skills/wk-wrap-up/SKILL.md +6 -5
  82. package/skills/wk-wrap-up/steps/summary.md +86 -0
  83. package/cli/src/engine/loopbacks.ts +0 -32
  84. package/cli/src/engine/parallel.ts +0 -60
  85. package/cli/src/engine/transitions.test.ts +0 -129
  86. /package/cli/src/{engine/phases.ts → workflow/gates.ts} +0 -0
@@ -0,0 +1,20 @@
1
+ import * as fs from "node:fs";
2
+
3
+ /**
4
+ * Read and parse a JSON file. Returns null when the file is missing,
5
+ * unreadable, or contains invalid JSON. Use only when null is a meaningful
6
+ * "no config" answer; use direct fs/JSON for hard-required files.
7
+ */
8
+ export function readJsonFile<T>(filePath: string): T | null {
9
+ let raw: string;
10
+ try {
11
+ raw = fs.readFileSync(filePath, "utf-8");
12
+ } catch {
13
+ return null;
14
+ }
15
+ try {
16
+ return JSON.parse(raw) as T;
17
+ } catch {
18
+ return null;
19
+ }
20
+ }
@@ -0,0 +1,27 @@
1
+ /** Difference in ms between two ISO timestamps; 0 on missing/invalid input. */
2
+ export function durationMs(start?: string, end?: string): number {
3
+ if (!start || !end) return 0;
4
+ const a = new Date(start).getTime();
5
+ const b = new Date(end).getTime();
6
+ if (isNaN(a) || isNaN(b)) return 0;
7
+ return Math.max(0, b - a);
8
+ }
9
+
10
+ /** Human-readable duration: "12s", "5m", "2h30m", or "—" for non-positive. */
11
+ export function formatDurationMs(ms: number): string {
12
+ if (ms <= 0) return "—";
13
+ const sec = Math.round(ms / 1000);
14
+ if (sec < 60) return `${sec}s`;
15
+ const min = Math.round(sec / 60);
16
+ if (min < 60) return `${min}m`;
17
+ const hr = Math.floor(min / 60);
18
+ const rem = min % 60;
19
+ return rem > 0 ? `${hr}h${rem}m` : `${hr}h`;
20
+ }
21
+
22
+ /** Elapsed since `start` formatted with `formatDurationMs`. Returns "" on bad input. */
23
+ export function formatDurationSince(start: string): string {
24
+ const startMs = new Date(start).getTime();
25
+ if (isNaN(startMs)) return "";
26
+ return formatDurationMs(Date.now() - startMs);
27
+ }
@@ -6,7 +6,7 @@ describe("checkLoopback", () => {
6
6
  it("plan/audit with 'revise' loops back to plan/blueprint", () => {
7
7
  const result = checkLoopback("plan", "audit", "revise");
8
8
  assert.notEqual(result, null);
9
- assert.deepStrictEqual(result!.to, { phase: "plan", subStage: "blueprint" });
9
+ assert.deepStrictEqual(result!.to, { phase: "plan", step: "blueprint" });
10
10
  assert.ok(result!.reason.length > 0);
11
11
  });
12
12
 
@@ -18,7 +18,7 @@ describe("checkLoopback", () => {
18
18
  it("review/handoff with 'changes_requested' loops back to build/core", () => {
19
19
  const result = checkLoopback("review", "handoff", "changes_requested");
20
20
  assert.notEqual(result, null);
21
- assert.deepStrictEqual(result!.to, { phase: "build", subStage: "core" });
21
+ assert.deepStrictEqual(result!.to, { phase: "build", step: "core" });
22
22
  });
23
23
 
24
24
  it("build/core with 'done' returns null", () => {
@@ -0,0 +1,42 @@
1
+ import { PhaseName, Location, LoopbackRecord, StepOutcome } from "../state/schema.js";
2
+ import { LOOPBACK_ROUTES } from "../config/loopback-routes.js";
3
+
4
+ interface LoopbackResult {
5
+ to: Location;
6
+ reason: string;
7
+ }
8
+
9
+ /**
10
+ * Count how many times a specific loopback route has been taken.
11
+ */
12
+ export function countLoopbacksForRoute(loopbacks: LoopbackRecord[], from: Location, to: Location): number {
13
+ return loopbacks.filter(
14
+ (lb) => lb.from.phase === from.phase && lb.from.step === from.step
15
+ && lb.to.phase === to.phase && lb.to.step === to.step
16
+ ).length;
17
+ }
18
+
19
+ /**
20
+ * Check if completing a step with a given outcome should trigger a loop-back.
21
+ */
22
+ export function checkLoopback(
23
+ phase: PhaseName,
24
+ step: string,
25
+ outcome?: StepOutcome
26
+ ): LoopbackResult | null {
27
+ if (!outcome) return null;
28
+
29
+ const route = LOOPBACK_ROUTES.find(
30
+ (r) =>
31
+ r.from.phase === phase &&
32
+ r.from.step === step &&
33
+ r.triggerOutcome === outcome
34
+ );
35
+
36
+ if (!route) return null;
37
+
38
+ return {
39
+ to: route.to,
40
+ reason: route.reason,
41
+ };
42
+ }
@@ -0,0 +1,64 @@
1
+ import type { PhaseName, WorkKitState } from "../state/schema.js";
2
+ import { loadProjectConfig } from "../config/project-config.js";
3
+
4
+ /**
5
+ * Defines which steps run in parallel and which runs sequentially after.
6
+ */
7
+ export interface ParallelGroup {
8
+ parallel: string[]; // steps that run concurrently
9
+ thenSequential?: string; // step that runs after all parallel complete
10
+ }
11
+
12
+ /**
13
+ * Default parallel groups per phase. Most projects should not need to override
14
+ * these — the defaults reflect the canonical work-kit pipeline.
15
+ */
16
+ export const DEFAULT_PARALLEL_GROUPS: Record<string, ParallelGroup> = {
17
+ test: {
18
+ parallel: ["verify", "e2e"],
19
+ thenSequential: "validate",
20
+ },
21
+ review: {
22
+ parallel: ["self-review", "security", "performance", "compliance"],
23
+ thenSequential: "handoff",
24
+ },
25
+ };
26
+
27
+ /**
28
+ * Resolve parallel groups for a project, merging defaults with optional
29
+ * project config overrides at `<mainRepoRoot>/.work-kit-config.json`.
30
+ */
31
+ export function resolveParallelGroups(mainRepoRoot?: string): Record<string, ParallelGroup> {
32
+ if (!mainRepoRoot) return DEFAULT_PARALLEL_GROUPS;
33
+ const config = loadProjectConfig(mainRepoRoot);
34
+ if (!config.parallel || Object.keys(config.parallel).length === 0) {
35
+ return DEFAULT_PARALLEL_GROUPS;
36
+ }
37
+ return { ...DEFAULT_PARALLEL_GROUPS, ...config.parallel };
38
+ }
39
+
40
+ /**
41
+ * Check if a step triggers a parallel group.
42
+ * Triggers on the first non-skipped, non-completed parallel member.
43
+ */
44
+ export function getParallelGroup(phase: PhaseName, step: string, state?: WorkKitState): ParallelGroup | null {
45
+ const groups = resolveParallelGroups(state?.metadata?.mainRepoRoot);
46
+ const group = groups[phase];
47
+ if (!group) return null;
48
+
49
+ if (!group.parallel.includes(step)) return null;
50
+
51
+ if (state) {
52
+ const phaseState = state.phases[phase];
53
+ const firstActive = group.parallel.find((s) => {
54
+ const sState = phaseState?.steps[s];
55
+ return sState && sState.status !== "skipped" && sState.status !== "completed";
56
+ });
57
+ if (firstActive !== step) return null;
58
+ } else {
59
+ if (group.parallel[0] !== step) return null;
60
+ }
61
+
62
+ return group;
63
+ }
64
+
@@ -0,0 +1,129 @@
1
+ import { describe, it } from "node:test";
2
+ import * as assert from "node:assert/strict";
3
+ import { nextStepInPhase, isPhaseComplete, determineNextStep } from "./transitions.js";
4
+ import type { WorkKitState, PhaseName, PhaseState, StepState } from "../state/schema.js";
5
+ import { PHASE_NAMES, STEPS_BY_PHASE } from "../state/schema.js";
6
+
7
+ function makeState(): WorkKitState {
8
+ const phases = {} as Record<PhaseName, PhaseState>;
9
+ for (const phase of PHASE_NAMES) {
10
+ const steps: Record<string, StepState> = {};
11
+ for (const s of STEPS_BY_PHASE[phase]) {
12
+ steps[s] = { status: "pending" };
13
+ }
14
+ phases[phase] = { status: "pending", steps };
15
+ }
16
+ return {
17
+ version: 2,
18
+ slug: "test",
19
+ branch: "feature/test",
20
+ started: "2026-01-01",
21
+ mode: "full-kit",
22
+ status: "in-progress",
23
+ currentPhase: "plan",
24
+ currentStep: "clarify",
25
+ phases,
26
+ loopbacks: [],
27
+ metadata: { worktreeRoot: "/tmp/test", mainRepoRoot: "/tmp/test" },
28
+ };
29
+ }
30
+
31
+ describe("nextStepInPhase", () => {
32
+ it("returns first pending step", () => {
33
+ const state = makeState();
34
+ const result = nextStepInPhase(state, "plan");
35
+ assert.equal(result, "clarify");
36
+ });
37
+
38
+ it("returns null when all complete or skipped", () => {
39
+ const state = makeState();
40
+ for (const s of Object.values(state.phases.plan.steps)) {
41
+ s.status = "completed";
42
+ }
43
+ const result = nextStepInPhase(state, "plan");
44
+ assert.equal(result, null);
45
+ });
46
+
47
+ it("skips completed steps and returns next pending", () => {
48
+ const state = makeState();
49
+ state.phases.plan.steps.clarify.status = "completed";
50
+ state.phases.plan.steps.investigate.status = "completed";
51
+ const result = nextStepInPhase(state, "plan");
52
+ assert.equal(result, "sketch");
53
+ });
54
+ });
55
+
56
+ describe("isPhaseComplete", () => {
57
+ it("returns true when all complete or skipped", () => {
58
+ const state = makeState();
59
+ for (const s of Object.values(state.phases.plan.steps)) {
60
+ s.status = "completed";
61
+ }
62
+ assert.equal(isPhaseComplete(state, "plan"), true);
63
+ });
64
+
65
+ it("returns true with mix of completed and skipped", () => {
66
+ const state = makeState();
67
+ let first = true;
68
+ for (const s of Object.values(state.phases.plan.steps)) {
69
+ s.status = first ? "skipped" : "completed";
70
+ first = false;
71
+ }
72
+ assert.equal(isPhaseComplete(state, "plan"), true);
73
+ });
74
+
75
+ it("returns false when some steps are pending", () => {
76
+ const state = makeState();
77
+ assert.equal(isPhaseComplete(state, "plan"), false);
78
+ });
79
+ });
80
+
81
+ describe("determineNextStep", () => {
82
+ it("returns complete when state is completed", () => {
83
+ const state = makeState();
84
+ state.status = "completed";
85
+ const result = determineNextStep(state);
86
+ assert.equal(result.type, "complete");
87
+ });
88
+
89
+ it("returns phase-boundary when no current phase", () => {
90
+ const state = makeState();
91
+ state.currentPhase = null;
92
+ const result = determineNextStep(state);
93
+ assert.equal(result.type, "phase-boundary");
94
+ assert.equal(result.phase, "plan");
95
+ });
96
+
97
+ it("returns step for current phase with pending work", () => {
98
+ const state = makeState();
99
+ state.currentPhase = "plan";
100
+ state.phases.plan.status = "in-progress";
101
+ const result = determineNextStep(state);
102
+ assert.equal(result.type, "step");
103
+ assert.equal(result.phase, "plan");
104
+ assert.equal(result.step, "clarify");
105
+ });
106
+
107
+ it("auto-proceeds to next phase by default when current phase is complete", () => {
108
+ const state = makeState();
109
+ state.currentPhase = "plan";
110
+ for (const s of Object.values(state.phases.plan.steps)) {
111
+ s.status = "completed";
112
+ }
113
+ const result = determineNextStep(state);
114
+ assert.equal(result.type, "phase-boundary");
115
+ assert.equal(result.phase, "build");
116
+ });
117
+
118
+ it("returns wait-for-user when gated and current phase is complete", () => {
119
+ const state = makeState();
120
+ state.gated = true;
121
+ state.currentPhase = "plan";
122
+ for (const s of Object.values(state.phases.plan.steps)) {
123
+ s.status = "completed";
124
+ }
125
+ const result = determineNextStep(state);
126
+ assert.equal(result.type, "wait-for-user");
127
+ assert.equal(result.phase, "build");
128
+ });
129
+ });
@@ -1,36 +1,36 @@
1
- import { WorkKitState, PhaseName, SUBSTAGES_BY_PHASE } from "../state/schema.js";
2
- import { PHASE_ORDER } from "../config/phases.js";
1
+ import { WorkKitState, PhaseName, STEPS_BY_PHASE } from "../state/schema.js";
2
+ import { PHASE_ORDER } from "../config/workflow.js";
3
3
 
4
4
  export interface NextStep {
5
- type: "sub-stage" | "phase-boundary" | "complete" | "wait-for-user";
5
+ type: "step" | "phase-boundary" | "complete" | "wait-for-user";
6
6
  phase?: PhaseName;
7
- subStage?: string;
7
+ step?: string;
8
8
  message?: string;
9
9
  }
10
10
 
11
11
  /**
12
- * Find the next pending sub-stage within a phase.
12
+ * Find the next pending step within a phase.
13
13
  */
14
- export function nextSubStageInPhase(state: WorkKitState, phase: PhaseName): string | null {
14
+ export function nextStepInPhase(state: WorkKitState, phase: PhaseName): string | null {
15
15
  const phaseState = state.phases[phase];
16
- const subStages = SUBSTAGES_BY_PHASE[phase];
16
+ const steps = STEPS_BY_PHASE[phase];
17
17
 
18
- for (const ss of subStages) {
19
- const ssState = phaseState.subStages[ss];
20
- if (ssState && (ssState.status === "pending" || ssState.status === "in-progress" || ssState.status === "waiting")) {
21
- return ss;
18
+ for (const step of steps) {
19
+ const stepState = phaseState.steps[step];
20
+ if (stepState && (stepState.status === "pending" || stepState.status === "in-progress" || stepState.status === "waiting")) {
21
+ return step;
22
22
  }
23
23
  }
24
24
  return null;
25
25
  }
26
26
 
27
27
  /**
28
- * Check if all non-skipped sub-stages in a phase are completed.
28
+ * Check if all non-skipped steps in a phase are completed.
29
29
  */
30
30
  export function isPhaseComplete(state: WorkKitState, phase: PhaseName): boolean {
31
31
  const phaseState = state.phases[phase];
32
- return Object.values(phaseState.subStages).every(
33
- (ss) => ss.status === "completed" || ss.status === "skipped"
32
+ return Object.values(phaseState.steps).every(
33
+ (s) => s.status === "completed" || s.status === "skipped"
34
34
  );
35
35
  }
36
36
 
@@ -58,7 +58,6 @@ export function determineNextStep(state: WorkKitState): NextStep {
58
58
  const currentPhase = state.currentPhase;
59
59
 
60
60
  if (!currentPhase) {
61
- // Find the next phase
62
61
  const next = nextPhase(state);
63
62
  if (!next) {
64
63
  return { type: "complete", message: "All phases complete" };
@@ -68,7 +67,6 @@ export function determineNextStep(state: WorkKitState): NextStep {
68
67
 
69
68
  // Check if current phase is complete
70
69
  if (isPhaseComplete(state, currentPhase)) {
71
- // Find next phase
72
70
  const phaseIndex = PHASE_ORDER.indexOf(currentPhase);
73
71
  const remainingPhases = PHASE_ORDER.slice(phaseIndex + 1);
74
72
 
@@ -76,14 +74,12 @@ export function determineNextStep(state: WorkKitState): NextStep {
76
74
  const ps = state.phases[phase];
77
75
  if (ps.status !== "skipped") {
78
76
  if (state.gated) {
79
- // Gated mode — wait for user confirmation before crossing
80
77
  return {
81
78
  type: "wait-for-user",
82
79
  phase,
83
80
  message: `${currentPhase} phase complete. Ready to start ${phase}. Proceed?`,
84
81
  };
85
82
  }
86
- // Default — auto-proceed to next phase
87
83
  return { type: "phase-boundary", phase, message: `${currentPhase} complete → starting ${phase}` };
88
84
  }
89
85
  }
@@ -91,10 +87,10 @@ export function determineNextStep(state: WorkKitState): NextStep {
91
87
  return { type: "complete", message: "All phases complete" };
92
88
  }
93
89
 
94
- // Find next sub-stage within current phase
95
- const nextSS = nextSubStageInPhase(state, currentPhase);
96
- if (nextSS) {
97
- return { type: "sub-stage", phase: currentPhase, subStage: nextSS };
90
+ // Find next step within current phase
91
+ const next = nextStepInPhase(state, currentPhase);
92
+ if (next) {
93
+ return { type: "step", phase: currentPhase, step: next };
98
94
  }
99
95
 
100
96
  return { type: "complete", message: `${currentPhase} phase complete` };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "work-kit-cli",
3
- "version": "0.2.7",
4
- "description": "Structured development workflow for Claude Code. Two modes, 6 phases, 27 sub-stages.",
3
+ "version": "0.3.0",
4
+ "description": "Structured development workflow for Claude Code. Two modes, 6 phases, 27 steps.",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "work-kit": "cli/bin/work-kit.mjs",
@@ -6,7 +6,7 @@ argument-hint: "[--gated] [description]"
6
6
  allowed-tools: Agent, Bash, Read, Write, Edit, Glob, Grep
7
7
  ---
8
8
 
9
- You are the **Work Orchestrator (Auto Mode)**. You analyze the request first, then build a tailored workflow with only the phases and sub-stages that are actually needed.
9
+ You are the **Work Orchestrator (Auto Mode)**. You analyze the request first, then build a tailored workflow with only the phases and steps that are actually needed.
10
10
 
11
11
  Best for: bug fixes, small changes, refactors, or well-understood tasks.
12
12
 
@@ -14,7 +14,7 @@ Best for: bug fixes, small changes, refactors, or well-understood tasks.
14
14
 
15
15
  Before starting, verify the CLI is installed:
16
16
  ```bash
17
- npx work-kit-cli doctor
17
+ work-kit doctor
18
18
  ```
19
19
 
20
20
  If `work-kit` is not found, ask the user to install it:
@@ -22,7 +22,7 @@ If `work-kit` is not found, ask the user to install it:
22
22
 
23
23
  Do not proceed until `doctor` reports all checks passed.
24
24
 
25
- ## All Available Sub-stages
25
+ ## All Available Steps
26
26
 
27
27
  These are the building blocks you pick from:
28
28
 
@@ -47,13 +47,13 @@ Before creating the worktree, perform a quick analysis:
47
47
  - **feature** — new capability (small to medium scope)
48
48
  - **large-feature** — new capability (large scope, multiple systems)
49
49
  3. **Scan the codebase** — quick look at affected areas (not a full investigation)
50
- 4. **Build the workflow** — select only the sub-stages needed
50
+ 4. **Build the workflow** — select only the steps needed
51
51
 
52
52
  ### Step 2: Build Dynamic Workflow
53
53
 
54
- Based on the classification, select sub-stages. Use this table as a starting point, then adjust based on the specific request:
54
+ Based on the classification, select steps. Use this table as a starting point, then adjust based on the specific request:
55
55
 
56
- | Sub-stage | bug-fix | small-change | refactor | feature | large-feature |
56
+ | Step | bug-fix | small-change | refactor | feature | large-feature |
57
57
  |------------------------|---------|--------------|----------|---------|---------------|
58
58
  | **Plan: Clarify** | YES | YES | YES | YES | YES |
59
59
  | **Plan: Investigate** | YES | skip | YES | YES | YES |
@@ -95,34 +95,34 @@ The table is a guide, not a rigid rule. Adjust based on the actual request:
95
95
  ```bash
96
96
  git worktree add worktrees/<slug> -b feature/<slug>
97
97
  cd worktrees/<slug>
98
- npx work-kit-cli init --mode auto --description "<description>" --classification <classification>
98
+ work-kit init --mode auto --description "<description>" --classification <classification>
99
99
  ```
100
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
- 2. Show the workflow to the user: `npx work-kit-cli workflow`
102
- 3. User can adjust: `npx work-kit-cli workflow --add review/security` or `npx work-kit-cli workflow --remove test/e2e`
101
+ 2. Show the workflow to the user: `work-kit workflow`
102
+ 3. User can adjust: `work-kit workflow --add review/security` or `work-kit workflow --remove test/e2e`
103
103
  4. **Wait for approval** — user can add/remove steps before proceeding
104
104
  5. Once approved, start the execution loop
105
105
 
106
106
  ## Continuing Work (`/auto-kit` with no args)
107
107
 
108
- 1. Run `npx work-kit-cli bootstrap` to detect session state
108
+ 1. Run `work-kit bootstrap` to detect session state
109
109
  2. Parse the JSON response:
110
110
  - If `active: false` — no session found, ask the user for a description and start new work
111
111
  - If `recovery` is set — report the recovery suggestion to the user before continuing
112
- - If `active: true` — report current state (slug, phase, sub-stage) to the user
112
+ - If `active: true` — report current state (slug, phase, step) to the user
113
113
  3. `cd` into the worktree directory
114
- 4. Run `npx work-kit-cli next` to get the next action
114
+ 4. Run `work-kit next` to get the next action
115
115
  5. Follow the execution loop below
116
116
 
117
117
  ## Step Validation
118
118
 
119
119
  All validation is handled by the CLI. The `next` command enforces order, phase boundaries, and prerequisites automatically.
120
120
 
121
- To add/remove steps mid-work: `npx work-kit-cli workflow --add <phase/sub-stage>` or `--remove <phase/sub-stage>`. Completed steps cannot be removed.
121
+ To add/remove steps mid-work: `work-kit workflow --add <phase/step>` or `--remove <phase/step>`. Completed steps cannot be removed.
122
122
 
123
123
  ## Agent Architecture
124
124
 
125
- Same as full-kit: each phase runs as a **fresh agent** to keep context focused. The difference is that each agent only runs the sub-stages in the `## Workflow` checklist.
125
+ Same as full-kit: each phase runs as a **fresh agent** to keep context focused. The difference is that each agent only runs the steps in the `## Workflow` checklist.
126
126
 
127
127
  ```
128
128
  Orchestrator (main agent — you)
@@ -177,23 +177,23 @@ Orchestrator (main agent — you)
177
177
 
178
178
  Each phase writes a `### <Phase>: Final` section — a self-contained summary. The next agent reads **only** the Final sections it needs.
179
179
 
180
- If a phase has fewer sub-stages in the workflow, the Final section still covers the same output — just with less detail where sub-stages were skipped.
180
+ If a phase has fewer steps in the workflow, the Final section still covers the same output — just with less detail where steps were skipped.
181
181
 
182
182
  ## Execution Loop
183
183
 
184
184
  The CLI manages all state transitions, prerequisites, and loopbacks. Follow this loop:
185
185
 
186
- 1. Run `npx work-kit-cli next` to get the next action
186
+ 1. Run `work-kit next` to get the next action
187
187
  2. Parse the JSON response
188
188
  3. Follow the action type:
189
- - **`spawn_agent`**: Use the Agent tool with the provided `agentPrompt`. Pass `skillFile` path for reference. After the agent completes: `npx work-kit-cli complete <phase>/<sub-stage> --outcome <outcome>`
190
- - **`spawn_parallel_agents`**: Spawn all agents in the `agents` array in parallel using the Agent tool. Wait for all to complete. Then spawn `thenSequential` if provided. After all complete: `npx work-kit-cli complete <onComplete target>`
191
- - **`wait_for_user`**: Report the message to the user and stop. Wait for them to say "proceed" before running `npx work-kit-cli next` again.
192
- - **`loopback`**: Report the loopback to the user, then run `npx work-kit-cli next` to continue from the target.
189
+ - **`spawn_agent`**: Use the Agent tool with the provided `agentPrompt`. Pass `skillFile` path for reference. After the agent completes: `work-kit complete <phase>/<step> --outcome <outcome>`
190
+ - **`spawn_parallel_agents`**: Spawn all agents in the `agents` array in parallel using the Agent tool. Wait for all to complete. Then spawn `thenSequential` if provided. After all complete: `work-kit complete <onComplete target>`
191
+ - **`wait_for_user`**: Report the message to the user and stop. Wait for them to say "proceed" before running `work-kit next` again.
192
+ - **`loopback`**: Report the loopback to the user, then run `work-kit next` to continue from the target.
193
193
  - **`complete`**: Done — run wrap-up if not already done.
194
194
  - **`error`**: Report the error and suggestion to the user. Stop.
195
- 4. After each agent completes: `npx work-kit-cli complete <phase>/<sub-stage> --outcome <outcome>`
196
- 5. Then `npx work-kit-cli next` again to continue
195
+ 4. After each agent completes: `work-kit complete <phase>/<step> --outcome <outcome>`
196
+ 5. Then `work-kit next` again to continue
197
197
 
198
198
  ## Loop-Back Rules
199
199
 
@@ -13,7 +13,7 @@ Cancels the active work-kit session and cleans up all artifacts.
13
13
 
14
14
  1. Finds the active work-kit session (via `bootstrap`)
15
15
  2. Confirms with the user before proceeding
16
- 3. Runs `npx work-kit-cli cancel` to:
16
+ 3. Runs `work-kit cancel` to:
17
17
  - Remove `.work-kit/` state directory
18
18
  - Remove the git worktree
19
19
  - Delete the feature branch
@@ -21,14 +21,14 @@ Cancels the active work-kit session and cleans up all artifacts.
21
21
 
22
22
  ## Instructions
23
23
 
24
- 1. Run `npx work-kit-cli bootstrap` to detect the active session
24
+ 1. Run `work-kit bootstrap` to detect the active session
25
25
  2. If no active session: tell the user there's nothing to cancel
26
26
  3. If active: show the user what will be cancelled:
27
27
  - Slug and branch name
28
- - Current phase and sub-stage
28
+ - Current phase and step
29
29
  - Any uncommitted work in the worktree will be lost
30
30
  4. **Ask the user to confirm** — do not proceed without explicit confirmation
31
31
  5. `cd` into the worktree directory
32
- 6. Run `npx work-kit-cli cancel`
32
+ 6. Run `work-kit cancel`
33
33
  7. `cd` back to the main repo root
34
34
  8. Report the result to the user