work-kit-cli 0.2.8 → 0.4.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.
- package/README.md +24 -13
- package/cli/src/commands/bootstrap.test.ts +40 -0
- package/cli/src/commands/bootstrap.ts +77 -13
- package/cli/src/commands/cancel.ts +1 -16
- package/cli/src/commands/complete.ts +92 -98
- package/cli/src/commands/completions.ts +2 -2
- package/cli/src/commands/doctor.ts +1 -1
- package/cli/src/commands/extract.ts +217 -0
- package/cli/src/commands/init.test.ts +50 -0
- package/cli/src/commands/init.ts +70 -35
- package/cli/src/commands/learn.test.ts +217 -0
- package/cli/src/commands/learn.ts +104 -0
- package/cli/src/commands/loopback.ts +8 -11
- package/cli/src/commands/next.ts +93 -60
- package/cli/src/commands/observe.ts +16 -21
- package/cli/src/commands/pause-resume.test.ts +142 -0
- package/cli/src/commands/pause.ts +34 -0
- package/cli/src/commands/report.ts +217 -0
- package/cli/src/commands/resume.ts +126 -0
- package/cli/src/commands/setup.ts +280 -0
- package/cli/src/commands/status.ts +8 -6
- package/cli/src/commands/uninstall.ts +8 -3
- package/cli/src/commands/workflow.ts +43 -33
- package/cli/src/config/agent-map.ts +9 -9
- package/cli/src/config/constants.ts +54 -0
- package/cli/src/config/loopback-routes.ts +13 -13
- package/cli/src/config/model-routing.test.ts +190 -0
- package/cli/src/config/model-routing.ts +208 -0
- package/cli/src/config/project-config.test.ts +127 -0
- package/cli/src/config/project-config.ts +106 -0
- package/cli/src/config/{phases.ts → workflow.ts} +40 -23
- package/cli/src/context/prompt-builder.ts +10 -9
- package/cli/src/index.ts +130 -9
- package/cli/src/observer/data.ts +196 -65
- package/cli/src/observer/renderer.ts +127 -107
- package/cli/src/observer/watcher.ts +28 -16
- package/cli/src/state/helpers.test.ts +28 -28
- package/cli/src/state/helpers.ts +37 -25
- package/cli/src/state/schema.ts +135 -45
- package/cli/src/state/store.ts +127 -7
- package/cli/src/state/validators.test.ts +13 -13
- package/cli/src/state/validators.ts +3 -4
- package/cli/src/utils/colors.ts +2 -0
- package/cli/src/utils/fs.ts +13 -0
- package/cli/src/utils/json.ts +20 -0
- package/cli/src/utils/knowledge.ts +471 -0
- package/cli/src/utils/time.ts +27 -0
- package/cli/src/{engine → workflow}/loopbacks.test.ts +2 -2
- package/cli/src/workflow/loopbacks.ts +42 -0
- package/cli/src/workflow/parallel.ts +64 -0
- package/cli/src/workflow/transitions.test.ts +129 -0
- package/cli/src/{engine → workflow}/transitions.ts +18 -22
- package/package.json +2 -2
- package/skills/auto-kit/SKILL.md +44 -27
- package/skills/cancel-kit/SKILL.md +4 -4
- package/skills/full-kit/SKILL.md +45 -28
- package/skills/pause-kit/SKILL.md +25 -0
- package/skills/resume-kit/SKILL.md +64 -0
- package/skills/wk-bootstrap/SKILL.md +11 -5
- package/skills/wk-build/SKILL.md +12 -11
- package/skills/wk-build/{stages → steps}/commit.md +1 -1
- package/skills/wk-build/{stages → steps}/core.md +3 -3
- package/skills/wk-build/{stages → steps}/integration.md +2 -2
- package/skills/wk-build/{stages → steps}/migration.md +1 -1
- package/skills/wk-build/{stages → steps}/red.md +1 -1
- package/skills/wk-build/{stages → steps}/refactor.md +1 -1
- package/skills/wk-build/{stages → steps}/setup.md +1 -1
- package/skills/wk-build/{stages → steps}/ui.md +1 -1
- package/skills/wk-deploy/SKILL.md +7 -6
- package/skills/wk-deploy/{stages → steps}/merge.md +1 -1
- package/skills/wk-deploy/{stages → steps}/monitor.md +1 -1
- package/skills/wk-deploy/{stages → steps}/remediate.md +1 -1
- package/skills/wk-plan/SKILL.md +15 -14
- package/skills/wk-plan/{stages → steps}/architecture.md +1 -1
- package/skills/wk-plan/{stages → steps}/audit.md +2 -2
- package/skills/wk-plan/{stages → steps}/blueprint.md +2 -2
- package/skills/wk-plan/{stages → steps}/clarify.md +1 -1
- package/skills/wk-plan/{stages → steps}/investigate.md +1 -1
- package/skills/wk-plan/{stages → steps}/scope.md +1 -1
- package/skills/wk-plan/{stages → steps}/sketch.md +1 -1
- package/skills/wk-plan/{stages → steps}/ux-flow.md +1 -1
- package/skills/wk-review/SKILL.md +11 -10
- package/skills/wk-review/{stages → steps}/compliance.md +1 -1
- package/skills/wk-review/{stages → steps}/handoff.md +2 -2
- package/skills/wk-review/{stages → steps}/performance.md +1 -1
- package/skills/wk-review/{stages → steps}/security.md +1 -1
- package/skills/wk-review/{stages → steps}/self-review.md +1 -1
- package/skills/wk-test/SKILL.md +9 -8
- package/skills/wk-test/steps/e2e.md +56 -0
- package/skills/wk-test/{stages → steps}/validate.md +1 -1
- package/skills/wk-test/{stages → steps}/verify.md +1 -1
- package/skills/wk-wrap-up/SKILL.md +19 -5
- package/skills/wk-wrap-up/steps/knowledge.md +76 -0
- package/skills/wk-wrap-up/steps/summary.md +86 -0
- package/cli/src/engine/loopbacks.ts +0 -32
- package/cli/src/engine/parallel.ts +0 -60
- package/cli/src/engine/transitions.test.ts +0 -129
- package/skills/wk-test/stages/e2e.md +0 -53
- /package/cli/src/{engine/phases.ts → workflow/gates.ts} +0 -0
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
PhaseName,
|
|
3
|
-
|
|
3
|
+
PHASE_NAMES,
|
|
4
|
+
STEPS_BY_PHASE,
|
|
4
5
|
Classification,
|
|
5
6
|
WorkflowStep,
|
|
6
7
|
} from "../state/schema.js";
|
|
8
|
+
import { SKILL_DIR_PREFIX } from "./constants.js";
|
|
7
9
|
|
|
8
|
-
// ── Phase Order
|
|
10
|
+
// ── Phase Order ─────────────────────────────────────────────────────
|
|
9
11
|
|
|
10
|
-
export const PHASE_ORDER: PhaseName[] = [
|
|
12
|
+
export const PHASE_ORDER: PhaseName[] = [...PHASE_NAMES];
|
|
11
13
|
|
|
12
|
-
// ── Prerequisites
|
|
14
|
+
// ── Prerequisites ───────────────────────────────────────────────────
|
|
13
15
|
|
|
14
16
|
export const PHASE_PREREQUISITES: Record<PhaseName, PhaseName | null> = {
|
|
15
17
|
plan: null,
|
|
@@ -20,15 +22,15 @@ export const PHASE_PREREQUISITES: Record<PhaseName, PhaseName | null> = {
|
|
|
20
22
|
"wrap-up": "review", // or deploy if deploy was included
|
|
21
23
|
};
|
|
22
24
|
|
|
23
|
-
// ── Skill File Paths
|
|
25
|
+
// ── Skill File Paths ────────────────────────────────────────────────
|
|
24
26
|
|
|
25
|
-
export function skillFilePath(phase: PhaseName,
|
|
26
|
-
const dir =
|
|
27
|
-
if (!
|
|
28
|
-
return `.claude/skills/${dir}/
|
|
27
|
+
export function skillFilePath(phase: PhaseName, step?: string): string {
|
|
28
|
+
const dir = `${SKILL_DIR_PREFIX}${phase}`;
|
|
29
|
+
if (!step) return `.claude/skills/${dir}/SKILL.md`;
|
|
30
|
+
return `.claude/skills/${dir}/steps/${step}.md`;
|
|
29
31
|
}
|
|
30
32
|
|
|
31
|
-
// ── Auto-kit Default Workflows
|
|
33
|
+
// ── Auto-kit Default Workflows ──────────────────────────────────────
|
|
32
34
|
|
|
33
35
|
type InclusionRule = "YES" | "skip" | "if UI" | "if DB" | "optional";
|
|
34
36
|
|
|
@@ -42,7 +44,7 @@ const WORKFLOW_MATRIX: Record<Classification, Record<string, InclusionRule>> = {
|
|
|
42
44
|
"review/self-review": "YES", "review/security": "skip", "review/performance": "skip",
|
|
43
45
|
"review/compliance": "skip", "review/handoff": "YES",
|
|
44
46
|
"deploy/merge": "YES", "deploy/monitor": "optional", "deploy/remediate": "optional",
|
|
45
|
-
"wrap-up/wrap-up": "
|
|
47
|
+
"wrap-up/summary": "YES", "wrap-up/knowledge": "skip",
|
|
46
48
|
},
|
|
47
49
|
"small-change": {
|
|
48
50
|
"plan/clarify": "YES", "plan/investigate": "skip", "plan/sketch": "skip", "plan/scope": "skip",
|
|
@@ -53,7 +55,7 @@ const WORKFLOW_MATRIX: Record<Classification, Record<string, InclusionRule>> = {
|
|
|
53
55
|
"review/self-review": "YES", "review/security": "skip", "review/performance": "skip",
|
|
54
56
|
"review/compliance": "skip", "review/handoff": "YES",
|
|
55
57
|
"deploy/merge": "YES", "deploy/monitor": "optional", "deploy/remediate": "optional",
|
|
56
|
-
"wrap-up/wrap-up": "
|
|
58
|
+
"wrap-up/summary": "YES", "wrap-up/knowledge": "skip",
|
|
57
59
|
},
|
|
58
60
|
refactor: {
|
|
59
61
|
"plan/clarify": "YES", "plan/investigate": "YES", "plan/sketch": "skip", "plan/scope": "skip",
|
|
@@ -64,7 +66,7 @@ const WORKFLOW_MATRIX: Record<Classification, Record<string, InclusionRule>> = {
|
|
|
64
66
|
"review/self-review": "YES", "review/security": "skip", "review/performance": "YES",
|
|
65
67
|
"review/compliance": "skip", "review/handoff": "YES",
|
|
66
68
|
"deploy/merge": "YES", "deploy/monitor": "optional", "deploy/remediate": "optional",
|
|
67
|
-
"wrap-up/wrap-up": "YES",
|
|
69
|
+
"wrap-up/summary": "YES", "wrap-up/knowledge": "YES",
|
|
68
70
|
},
|
|
69
71
|
feature: {
|
|
70
72
|
"plan/clarify": "YES", "plan/investigate": "YES", "plan/sketch": "YES", "plan/scope": "YES",
|
|
@@ -75,7 +77,7 @@ const WORKFLOW_MATRIX: Record<Classification, Record<string, InclusionRule>> = {
|
|
|
75
77
|
"review/self-review": "YES", "review/security": "YES", "review/performance": "skip",
|
|
76
78
|
"review/compliance": "YES", "review/handoff": "YES",
|
|
77
79
|
"deploy/merge": "YES", "deploy/monitor": "optional", "deploy/remediate": "optional",
|
|
78
|
-
"wrap-up/wrap-up": "YES",
|
|
80
|
+
"wrap-up/summary": "YES", "wrap-up/knowledge": "YES",
|
|
79
81
|
},
|
|
80
82
|
"large-feature": {
|
|
81
83
|
"plan/clarify": "YES", "plan/investigate": "YES", "plan/sketch": "YES", "plan/scope": "YES",
|
|
@@ -86,20 +88,35 @@ const WORKFLOW_MATRIX: Record<Classification, Record<string, InclusionRule>> = {
|
|
|
86
88
|
"review/self-review": "YES", "review/security": "YES", "review/performance": "YES",
|
|
87
89
|
"review/compliance": "YES", "review/handoff": "YES",
|
|
88
90
|
"deploy/merge": "YES", "deploy/monitor": "optional", "deploy/remediate": "optional",
|
|
89
|
-
"wrap-up/wrap-up": "YES",
|
|
91
|
+
"wrap-up/summary": "YES", "wrap-up/knowledge": "YES",
|
|
90
92
|
},
|
|
91
93
|
};
|
|
92
94
|
|
|
93
|
-
export function buildDefaultWorkflow(
|
|
95
|
+
export function buildDefaultWorkflow(
|
|
96
|
+
classification: Classification,
|
|
97
|
+
overrides?: { include?: string[]; exclude?: string[] }
|
|
98
|
+
): WorkflowStep[] {
|
|
94
99
|
const matrix = WORKFLOW_MATRIX[classification];
|
|
95
100
|
const steps: WorkflowStep[] = [];
|
|
96
101
|
|
|
102
|
+
const forceInclude = new Set(overrides?.include ?? []);
|
|
103
|
+
const forceExclude = new Set(overrides?.exclude ?? []);
|
|
104
|
+
|
|
97
105
|
for (const [key, rule] of Object.entries(matrix)) {
|
|
98
|
-
const [phase,
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
if (
|
|
102
|
-
|
|
106
|
+
const [phase, step] = key.split("/") as [PhaseName, string];
|
|
107
|
+
let included = rule === "YES" || rule === "if UI" || rule === "if DB";
|
|
108
|
+
if (forceInclude.has(key)) included = true;
|
|
109
|
+
if (forceExclude.has(key)) included = false;
|
|
110
|
+
// "skip" excluded by default, but project config may force-include
|
|
111
|
+
if (rule === "skip" && !forceInclude.has(key)) continue;
|
|
112
|
+
steps.push({ phase, step, included });
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Add any force-included steps not in the matrix
|
|
116
|
+
for (const ref of forceInclude) {
|
|
117
|
+
const [phase, step] = ref.split("/") as [PhaseName, string];
|
|
118
|
+
if (!steps.some(s => s.phase === phase && s.step === step)) {
|
|
119
|
+
steps.push({ phase, step, included: true });
|
|
103
120
|
}
|
|
104
121
|
}
|
|
105
122
|
|
|
@@ -109,8 +126,8 @@ export function buildDefaultWorkflow(classification: Classification): WorkflowSt
|
|
|
109
126
|
export function buildFullWorkflow(): WorkflowStep[] {
|
|
110
127
|
const steps: WorkflowStep[] = [];
|
|
111
128
|
for (const phase of PHASE_ORDER) {
|
|
112
|
-
for (const
|
|
113
|
-
steps.push({ phase,
|
|
129
|
+
for (const step of STEPS_BY_PHASE[phase]) {
|
|
130
|
+
steps.push({ phase, step, included: true });
|
|
114
131
|
}
|
|
115
132
|
}
|
|
116
133
|
return steps;
|
|
@@ -2,27 +2,28 @@ import { WorkKitState, PhaseName } from "../state/schema.js";
|
|
|
2
2
|
import { getContextFor } from "../config/agent-map.js";
|
|
3
3
|
import { extractSection, extractTopSection } from "./extractor.js";
|
|
4
4
|
import { readStateMd } from "../state/store.js";
|
|
5
|
-
import { skillFilePath } from "../config/
|
|
5
|
+
import { skillFilePath } from "../config/workflow.js";
|
|
6
6
|
import { redactIgnoredBlocks } from "./redactor.js";
|
|
7
|
+
import { CLI_BINARY } from "../config/constants.js";
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
|
-
* Build a complete agent prompt for a given phase/
|
|
10
|
+
* Build a complete agent prompt for a given phase/step.
|
|
10
11
|
* Accepts optional pre-read stateMd to avoid repeated file reads in parallel scenarios.
|
|
11
12
|
*/
|
|
12
13
|
export function buildAgentPrompt(
|
|
13
14
|
worktreeRoot: string,
|
|
14
15
|
state: WorkKitState,
|
|
15
16
|
phase: PhaseName,
|
|
16
|
-
|
|
17
|
+
step: string,
|
|
17
18
|
stateMd?: string | null
|
|
18
19
|
): string {
|
|
19
|
-
const ctx = getContextFor(phase,
|
|
20
|
+
const ctx = getContextFor(phase, step);
|
|
20
21
|
const md = stateMd ?? readStateMd(worktreeRoot);
|
|
21
|
-
const skill = skillFilePath(phase,
|
|
22
|
+
const skill = skillFilePath(phase, step);
|
|
22
23
|
|
|
23
24
|
const parts: string[] = [];
|
|
24
25
|
|
|
25
|
-
parts.push(`# Agent: ${phase}/${
|
|
26
|
+
parts.push(`# Agent: ${phase}/${step}`);
|
|
26
27
|
parts.push(`**Worktree:** ${worktreeRoot}`);
|
|
27
28
|
parts.push(`**Slug:** ${state.slug}`);
|
|
28
29
|
parts.push(`**Branch:** ${state.branch}`);
|
|
@@ -59,12 +60,12 @@ export function buildAgentPrompt(
|
|
|
59
60
|
}
|
|
60
61
|
|
|
61
62
|
parts.push(`## Output`);
|
|
62
|
-
parts.push(`Write your outputs to \`.work-kit/state.md\` under a section for this
|
|
63
|
+
parts.push(`Write your outputs to \`.work-kit/state.md\` under a section for this step.`);
|
|
63
64
|
|
|
64
|
-
if (
|
|
65
|
+
if (step === "wrap-up") {
|
|
65
66
|
parts.push(`Follow the wrap-up skill file instructions for archiving and cleanup.`);
|
|
66
67
|
} else {
|
|
67
|
-
parts.push(`When done, report your outcome so the orchestrator can run:
|
|
68
|
+
parts.push(`When done, report your outcome so the orchestrator can run: \`${CLI_BINARY} complete ${phase}/${step} --outcome <outcome>\``);
|
|
68
69
|
}
|
|
69
70
|
|
|
70
71
|
return redactIgnoredBlocks(parts.join("\n"));
|
package/cli/src/index.ts
CHANGED
|
@@ -17,8 +17,14 @@ import { observeCommand } from "./commands/observe.js";
|
|
|
17
17
|
import { uninstallCommand } from "./commands/uninstall.js";
|
|
18
18
|
import { bootstrapCommand } from "./commands/bootstrap.js";
|
|
19
19
|
import { cancelCommand } from "./commands/cancel.js";
|
|
20
|
+
import { pauseCommand } from "./commands/pause.js";
|
|
21
|
+
import { resumeCommand } from "./commands/resume.js";
|
|
22
|
+
import { reportCommand } from "./commands/report.js";
|
|
23
|
+
import { learnCommand } from "./commands/learn.js";
|
|
24
|
+
import { extractCommand } from "./commands/extract.js";
|
|
20
25
|
import { bold, green, yellow, red } from "./utils/colors.js";
|
|
21
|
-
import type { Classification, PhaseName } from "./state/schema.js";
|
|
26
|
+
import type { Classification, ModelPolicy, PhaseName } from "./state/schema.js";
|
|
27
|
+
import { isModelPolicy } from "./state/schema.js";
|
|
22
28
|
|
|
23
29
|
import { createRequire } from "node:module";
|
|
24
30
|
|
|
@@ -37,18 +43,27 @@ program
|
|
|
37
43
|
program
|
|
38
44
|
.command("init")
|
|
39
45
|
.description("Create worktree and initialize state")
|
|
40
|
-
.
|
|
46
|
+
.option("--mode <mode>", "Workflow mode: full or auto (default: from project config or 'full')")
|
|
41
47
|
.requiredOption("--description <text>", "Description of the work")
|
|
42
48
|
.option("--classification <type>", "Work classification (auto mode): bug-fix, small-change, refactor, feature, large-feature")
|
|
43
49
|
.option("--gated", "Wait for user approval between phases (default: auto-proceed)")
|
|
50
|
+
.option("--model-policy <policy>", "Session model policy: auto, opus, sonnet, haiku, inherit (default: auto)")
|
|
44
51
|
.option("--worktree-root <path>", "Override worktree root directory")
|
|
45
52
|
.action((opts) => {
|
|
46
53
|
try {
|
|
54
|
+
if (opts.modelPolicy !== undefined && !isModelPolicy(opts.modelPolicy)) {
|
|
55
|
+
console.error(JSON.stringify({
|
|
56
|
+
action: "error",
|
|
57
|
+
message: `Invalid --model-policy "${opts.modelPolicy}". Use one of: auto, opus, sonnet, haiku, inherit.`,
|
|
58
|
+
}));
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
47
61
|
const result = initCommand({
|
|
48
|
-
mode: opts.mode as "full" | "auto",
|
|
62
|
+
mode: opts.mode as "full" | "auto" | undefined,
|
|
49
63
|
description: opts.description,
|
|
50
64
|
classification: opts.classification as Classification | undefined,
|
|
51
|
-
gated: opts.gated
|
|
65
|
+
gated: opts.gated,
|
|
66
|
+
modelPolicy: opts.modelPolicy as ModelPolicy | undefined,
|
|
52
67
|
worktreeRoot: opts.worktreeRoot,
|
|
53
68
|
});
|
|
54
69
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -78,7 +93,7 @@ program
|
|
|
78
93
|
|
|
79
94
|
program
|
|
80
95
|
.command("complete <target>")
|
|
81
|
-
.description("Mark a phase/
|
|
96
|
+
.description("Mark a phase/step as complete (e.g., plan/clarify)")
|
|
82
97
|
.option("--outcome <value>", "Outcome of the step (e.g., done, revise, broken, changes_requested)")
|
|
83
98
|
.option("--worktree-root <path>", "Override worktree root")
|
|
84
99
|
.action((target, opts) => {
|
|
@@ -144,8 +159,8 @@ program
|
|
|
144
159
|
program
|
|
145
160
|
.command("loopback")
|
|
146
161
|
.description("Register a loop-back transition")
|
|
147
|
-
.requiredOption("--from <source>", "Source phase/
|
|
148
|
-
.requiredOption("--to <target>", "Target phase/
|
|
162
|
+
.requiredOption("--from <source>", "Source phase/step (e.g., review/handoff)")
|
|
163
|
+
.requiredOption("--to <target>", "Target phase/step (e.g., build/core)")
|
|
149
164
|
.requiredOption("--reason <text>", "Reason for loop-back")
|
|
150
165
|
.option("--worktree-root <path>", "Override worktree root")
|
|
151
166
|
.action((opts) => {
|
|
@@ -241,8 +256,9 @@ program
|
|
|
241
256
|
.command("observe")
|
|
242
257
|
.description("Real-time dashboard of all active work items")
|
|
243
258
|
.option("--repo <path>", "Main repository root")
|
|
259
|
+
.option("--all", "Observe every work-kit project found under ~/.claude/projects/")
|
|
244
260
|
.action(async (opts) => {
|
|
245
|
-
await observeCommand({ mainRepo: opts.repo });
|
|
261
|
+
await observeCommand({ mainRepo: opts.repo, all: opts.all });
|
|
246
262
|
});
|
|
247
263
|
|
|
248
264
|
// ── uninstall ────────────────────────────────────────────────────────
|
|
@@ -260,9 +276,10 @@ program
|
|
|
260
276
|
.command("bootstrap")
|
|
261
277
|
.description("Detect work-kit state and output session orientation")
|
|
262
278
|
.option("--json", "Output as JSON", true)
|
|
279
|
+
.option("--auto-resume", "If paused or stale, auto-flip to in-progress")
|
|
263
280
|
.action((opts) => {
|
|
264
281
|
try {
|
|
265
|
-
const result = bootstrapCommand();
|
|
282
|
+
const result = bootstrapCommand(undefined, { autoResume: opts.autoResume });
|
|
266
283
|
console.log(JSON.stringify(result, null, 2));
|
|
267
284
|
} catch (e: any) {
|
|
268
285
|
console.error(JSON.stringify({ action: "error", message: e.message }));
|
|
@@ -270,6 +287,59 @@ program
|
|
|
270
287
|
}
|
|
271
288
|
});
|
|
272
289
|
|
|
290
|
+
// ── pause ───────────────────────────────────────────────────────────
|
|
291
|
+
|
|
292
|
+
program
|
|
293
|
+
.command("pause")
|
|
294
|
+
.description("Pause the active work-kit session")
|
|
295
|
+
.option("--reason <text>", "Optional reason for pausing")
|
|
296
|
+
.option("--worktree-root <path>", "Override worktree root")
|
|
297
|
+
.action((opts) => {
|
|
298
|
+
try {
|
|
299
|
+
const result = pauseCommand(opts.reason, opts.worktreeRoot);
|
|
300
|
+
console.log(JSON.stringify(result, null, 2));
|
|
301
|
+
process.exit(result.action === "error" ? 1 : 0);
|
|
302
|
+
} catch (e: any) {
|
|
303
|
+
console.error(JSON.stringify({ action: "error", message: e.message }));
|
|
304
|
+
process.exit(1);
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
// ── resume ──────────────────────────────────────────────────────────
|
|
309
|
+
|
|
310
|
+
program
|
|
311
|
+
.command("resume")
|
|
312
|
+
.description("Resume a paused work-kit session (lists paused sessions when no slug is given)")
|
|
313
|
+
.option("--worktree-root <path>", "Override worktree root (resume session at exact path)")
|
|
314
|
+
.option("--slug <slug>", "Resume the paused session with this slug")
|
|
315
|
+
.action((opts) => {
|
|
316
|
+
try {
|
|
317
|
+
const result = resumeCommand({ worktreeRoot: opts.worktreeRoot, slug: opts.slug });
|
|
318
|
+
console.log(JSON.stringify(result, null, 2));
|
|
319
|
+
process.exit(result.action === "error" ? 1 : 0);
|
|
320
|
+
} catch (e: any) {
|
|
321
|
+
console.error(JSON.stringify({ action: "error", message: e.message }));
|
|
322
|
+
process.exit(1);
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
// ── report ──────────────────────────────────────────────────────────
|
|
327
|
+
|
|
328
|
+
program
|
|
329
|
+
.command("report")
|
|
330
|
+
.description("Show stats across completed work-kits")
|
|
331
|
+
.option("--json", "Output as JSON")
|
|
332
|
+
.option("--repo <path>", "Main repository root")
|
|
333
|
+
.option("--worktree-root <path>", "Override worktree root")
|
|
334
|
+
.action((opts) => {
|
|
335
|
+
try {
|
|
336
|
+
reportCommand({ json: opts.json, repo: opts.repo, worktreeRoot: opts.worktreeRoot });
|
|
337
|
+
} catch (e: any) {
|
|
338
|
+
console.error(JSON.stringify({ action: "error", message: e.message }));
|
|
339
|
+
process.exit(1);
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
|
|
273
343
|
// ── cancel ──────────────────────────────────────────────────────────
|
|
274
344
|
|
|
275
345
|
program
|
|
@@ -287,4 +357,55 @@ program
|
|
|
287
357
|
}
|
|
288
358
|
});
|
|
289
359
|
|
|
360
|
+
// ── learn ───────────────────────────────────────────────────────────
|
|
361
|
+
|
|
362
|
+
program
|
|
363
|
+
.command("learn")
|
|
364
|
+
.description("Append a knowledge entry (lesson/convention/risk/workflow) to .work-kit-knowledge/")
|
|
365
|
+
.requiredOption("--type <type>", "Entry type: lesson, convention, risk, workflow")
|
|
366
|
+
.requiredOption("--text <text>", "Free-form text. Secrets are auto-redacted at write time.")
|
|
367
|
+
.option("--scope <glob>", "Optional path glob (stored, not yet used for filtering)")
|
|
368
|
+
.option("--phase <phase>", "Override session phase auto-fill")
|
|
369
|
+
.option("--step <step>", "Override session step auto-fill")
|
|
370
|
+
.option("--source <source>", "Override entry source label", "explicit-cli")
|
|
371
|
+
.option("--worktree-root <path>", "Override worktree root")
|
|
372
|
+
.action((opts) => {
|
|
373
|
+
try {
|
|
374
|
+
const result = learnCommand({
|
|
375
|
+
type: opts.type,
|
|
376
|
+
text: opts.text,
|
|
377
|
+
scope: opts.scope,
|
|
378
|
+
phase: opts.phase,
|
|
379
|
+
step: opts.step,
|
|
380
|
+
source: opts.source,
|
|
381
|
+
worktreeRoot: opts.worktreeRoot,
|
|
382
|
+
});
|
|
383
|
+
console.log(JSON.stringify(result, null, 2));
|
|
384
|
+
if (result.action === "error") process.exit(1);
|
|
385
|
+
if (result.redacted) {
|
|
386
|
+
console.error(yellow(`! Redacted ${result.redactedKinds?.length ?? 0} secret(s) before writing.`));
|
|
387
|
+
}
|
|
388
|
+
} catch (e: any) {
|
|
389
|
+
console.error(JSON.stringify({ action: "error", message: e.message }));
|
|
390
|
+
process.exit(1);
|
|
391
|
+
}
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
// ── extract ─────────────────────────────────────────────────────────
|
|
395
|
+
|
|
396
|
+
program
|
|
397
|
+
.command("extract")
|
|
398
|
+
.description("Parse current session's state.md + tracker.json and append entries to knowledge files")
|
|
399
|
+
.option("--worktree-root <path>", "Override worktree root")
|
|
400
|
+
.action((opts) => {
|
|
401
|
+
try {
|
|
402
|
+
const result = extractCommand({ worktreeRoot: opts.worktreeRoot });
|
|
403
|
+
console.log(JSON.stringify(result, null, 2));
|
|
404
|
+
if (result.action === "error") process.exit(1);
|
|
405
|
+
} catch (e: any) {
|
|
406
|
+
console.error(JSON.stringify({ action: "error", message: e.message }));
|
|
407
|
+
process.exit(1);
|
|
408
|
+
}
|
|
409
|
+
});
|
|
410
|
+
|
|
290
411
|
program.parse();
|