@kata-sh/cli 0.1.0 → 0.1.2
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/LICENSE +21 -0
- package/README.md +156 -0
- package/dist/app-paths.d.ts +4 -0
- package/dist/app-paths.js +6 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +56 -0
- package/dist/loader.d.ts +2 -0
- package/dist/loader.js +95 -0
- package/dist/resource-loader.d.ts +18 -0
- package/dist/resource-loader.js +50 -0
- package/dist/wizard.d.ts +15 -0
- package/dist/wizard.js +159 -0
- package/package.json +50 -21
- package/pkg/dist/modes/interactive/theme/dark.json +85 -0
- package/pkg/dist/modes/interactive/theme/light.json +84 -0
- package/pkg/dist/modes/interactive/theme/theme-schema.json +335 -0
- package/pkg/dist/modes/interactive/theme/theme.d.ts +78 -0
- package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -0
- package/pkg/dist/modes/interactive/theme/theme.js +949 -0
- package/pkg/dist/modes/interactive/theme/theme.js.map +1 -0
- package/pkg/package.json +8 -0
- package/scripts/postinstall.js +45 -0
- package/src/resources/AGENTS.md +108 -0
- package/src/resources/KATA-WORKFLOW.md +661 -0
- package/src/resources/agents/researcher.md +29 -0
- package/src/resources/agents/scout.md +56 -0
- package/src/resources/agents/worker.md +31 -0
- package/src/resources/extensions/ask-user-questions.ts +200 -0
- package/src/resources/extensions/bg-shell/index.ts +2758 -0
- package/src/resources/extensions/browser-tools/BROWSER-TOOLS-V2-PROPOSAL.md +1277 -0
- package/src/resources/extensions/browser-tools/core.js +1057 -0
- package/src/resources/extensions/browser-tools/index.ts +4916 -0
- package/src/resources/extensions/browser-tools/package.json +20 -0
- package/src/resources/extensions/context7/index.ts +428 -0
- package/src/resources/extensions/context7/package.json +11 -0
- package/src/resources/extensions/get-secrets-from-user.ts +352 -0
- package/src/resources/extensions/github/formatters.ts +207 -0
- package/src/resources/extensions/github/gh-api.ts +537 -0
- package/src/resources/extensions/github/index.ts +778 -0
- package/src/resources/extensions/kata/activity-log.ts +88 -0
- package/src/resources/extensions/kata/auto.ts +2786 -0
- package/src/resources/extensions/kata/commands.ts +355 -0
- package/src/resources/extensions/kata/crash-recovery.ts +85 -0
- package/src/resources/extensions/kata/dashboard-overlay.ts +516 -0
- package/src/resources/extensions/kata/docs/preferences-reference.md +103 -0
- package/src/resources/extensions/kata/doctor.ts +683 -0
- package/src/resources/extensions/kata/files.ts +730 -0
- package/src/resources/extensions/kata/gitignore.ts +165 -0
- package/src/resources/extensions/kata/guided-flow.ts +976 -0
- package/src/resources/extensions/kata/index.ts +556 -0
- package/src/resources/extensions/kata/metrics.ts +397 -0
- package/src/resources/extensions/kata/observability-validator.ts +408 -0
- package/src/resources/extensions/kata/package.json +11 -0
- package/src/resources/extensions/kata/paths.ts +346 -0
- package/src/resources/extensions/kata/preferences.ts +695 -0
- package/src/resources/extensions/kata/prompt-loader.ts +50 -0
- package/src/resources/extensions/kata/prompts/complete-milestone.md +25 -0
- package/src/resources/extensions/kata/prompts/complete-slice.md +27 -0
- package/src/resources/extensions/kata/prompts/discuss.md +151 -0
- package/src/resources/extensions/kata/prompts/doctor-heal.md +29 -0
- package/src/resources/extensions/kata/prompts/execute-task.md +64 -0
- package/src/resources/extensions/kata/prompts/guided-complete-slice.md +1 -0
- package/src/resources/extensions/kata/prompts/guided-discuss-milestone.md +3 -0
- package/src/resources/extensions/kata/prompts/guided-discuss-slice.md +59 -0
- package/src/resources/extensions/kata/prompts/guided-execute-task.md +1 -0
- package/src/resources/extensions/kata/prompts/guided-plan-milestone.md +23 -0
- package/src/resources/extensions/kata/prompts/guided-plan-slice.md +1 -0
- package/src/resources/extensions/kata/prompts/guided-research-slice.md +11 -0
- package/src/resources/extensions/kata/prompts/guided-resume-task.md +1 -0
- package/src/resources/extensions/kata/prompts/plan-milestone.md +47 -0
- package/src/resources/extensions/kata/prompts/plan-slice.md +63 -0
- package/src/resources/extensions/kata/prompts/queue.md +85 -0
- package/src/resources/extensions/kata/prompts/reassess-roadmap.md +48 -0
- package/src/resources/extensions/kata/prompts/replan-slice.md +39 -0
- package/src/resources/extensions/kata/prompts/research-milestone.md +37 -0
- package/src/resources/extensions/kata/prompts/research-slice.md +28 -0
- package/src/resources/extensions/kata/prompts/run-uat.md +109 -0
- package/src/resources/extensions/kata/prompts/system.md +341 -0
- package/src/resources/extensions/kata/session-forensics.ts +550 -0
- package/src/resources/extensions/kata/skill-discovery.ts +137 -0
- package/src/resources/extensions/kata/state.ts +509 -0
- package/src/resources/extensions/kata/templates/context.md +76 -0
- package/src/resources/extensions/kata/templates/decisions.md +8 -0
- package/src/resources/extensions/kata/templates/milestone-summary.md +73 -0
- package/src/resources/extensions/kata/templates/plan.md +133 -0
- package/src/resources/extensions/kata/templates/preferences.md +15 -0
- package/src/resources/extensions/kata/templates/project.md +31 -0
- package/src/resources/extensions/kata/templates/reassessment.md +28 -0
- package/src/resources/extensions/kata/templates/requirements.md +81 -0
- package/src/resources/extensions/kata/templates/research.md +46 -0
- package/src/resources/extensions/kata/templates/roadmap.md +118 -0
- package/src/resources/extensions/kata/templates/slice-context.md +58 -0
- package/src/resources/extensions/kata/templates/slice-summary.md +99 -0
- package/src/resources/extensions/kata/templates/state.md +19 -0
- package/src/resources/extensions/kata/templates/task-plan.md +52 -0
- package/src/resources/extensions/kata/templates/task-summary.md +57 -0
- package/src/resources/extensions/kata/templates/uat.md +54 -0
- package/src/resources/extensions/kata/tests/activity-log-prune.test.ts +327 -0
- package/src/resources/extensions/kata/tests/auto-preflight.test.ts +97 -0
- package/src/resources/extensions/kata/tests/auto-supervisor.test.mjs +53 -0
- package/src/resources/extensions/kata/tests/complete-milestone.test.ts +317 -0
- package/src/resources/extensions/kata/tests/cost-projection.test.ts +160 -0
- package/src/resources/extensions/kata/tests/derive-state-deps.test.ts +477 -0
- package/src/resources/extensions/kata/tests/derive-state.test.ts +1013 -0
- package/src/resources/extensions/kata/tests/doctor.test.ts +718 -0
- package/src/resources/extensions/kata/tests/idle-recovery.test.ts +490 -0
- package/src/resources/extensions/kata/tests/metrics-io.test.ts +254 -0
- package/src/resources/extensions/kata/tests/metrics.test.ts +217 -0
- package/src/resources/extensions/kata/tests/must-have-parser.test.ts +309 -0
- package/src/resources/extensions/kata/tests/parsers.test.ts +1257 -0
- package/src/resources/extensions/kata/tests/plan-milestone.test.ts +185 -0
- package/src/resources/extensions/kata/tests/plan-quality-validator.test.ts +386 -0
- package/src/resources/extensions/kata/tests/reassess-prompt.test.ts +208 -0
- package/src/resources/extensions/kata/tests/replan-slice.test.ts +686 -0
- package/src/resources/extensions/kata/tests/requirements.test.ts +151 -0
- package/src/resources/extensions/kata/tests/resolve-ts-hooks.mjs +17 -0
- package/src/resources/extensions/kata/tests/resolve-ts.mjs +11 -0
- package/src/resources/extensions/kata/tests/run-uat.test.ts +383 -0
- package/src/resources/extensions/kata/tests/unit-runtime.test.ts +388 -0
- package/src/resources/extensions/kata/tests/workspace-index.test.ts +118 -0
- package/src/resources/extensions/kata/tests/worktree.test.ts +222 -0
- package/src/resources/extensions/kata/types.ts +159 -0
- package/src/resources/extensions/kata/unit-runtime.ts +163 -0
- package/src/resources/extensions/kata/workspace-index.ts +203 -0
- package/src/resources/extensions/kata/worktree.ts +182 -0
- package/src/resources/extensions/mac-tools/index.ts +852 -0
- package/src/resources/extensions/mac-tools/swift-cli/Package.swift +22 -0
- package/src/resources/extensions/mac-tools/swift-cli/Sources/main.swift +1318 -0
- package/src/resources/extensions/search-the-web/cache.ts +78 -0
- package/src/resources/extensions/search-the-web/format.ts +258 -0
- package/src/resources/extensions/search-the-web/http.ts +238 -0
- package/src/resources/extensions/search-the-web/index.ts +68 -0
- package/src/resources/extensions/search-the-web/tool-fetch-page.ts +519 -0
- package/src/resources/extensions/search-the-web/tool-llm-context.ts +404 -0
- package/src/resources/extensions/search-the-web/tool-search.ts +503 -0
- package/src/resources/extensions/search-the-web/url-utils.ts +91 -0
- package/src/resources/extensions/shared/confirm-ui.ts +126 -0
- package/src/resources/extensions/shared/interview-ui.ts +822 -0
- package/src/resources/extensions/shared/next-action-ui.ts +235 -0
- package/src/resources/extensions/shared/progress-widget.ts +282 -0
- package/src/resources/extensions/shared/thinking-widget.ts +107 -0
- package/src/resources/extensions/shared/ui.ts +400 -0
- package/src/resources/extensions/shared/wizard-ui.ts +551 -0
- package/src/resources/extensions/slash-commands/audit.ts +92 -0
- package/src/resources/extensions/slash-commands/create-extension.ts +375 -0
- package/src/resources/extensions/slash-commands/create-slash-command.ts +280 -0
- package/src/resources/extensions/slash-commands/index.ts +12 -0
- package/src/resources/extensions/slash-commands/kata-run.ts +34 -0
- package/src/resources/extensions/subagent/agents.ts +126 -0
- package/src/resources/extensions/subagent/index.ts +1293 -0
- package/src/resources/skills/debug-like-expert/SKILL.md +231 -0
- package/src/resources/skills/debug-like-expert/references/debugging-mindset.md +253 -0
- package/src/resources/skills/debug-like-expert/references/hypothesis-testing.md +373 -0
- package/src/resources/skills/debug-like-expert/references/investigation-techniques.md +337 -0
- package/src/resources/skills/debug-like-expert/references/verification-patterns.md +425 -0
- package/src/resources/skills/debug-like-expert/references/when-to-research.md +361 -0
- package/src/resources/skills/frontend-design/SKILL.md +45 -0
- package/src/resources/skills/swiftui/SKILL.md +208 -0
- package/src/resources/skills/swiftui/references/animations.md +921 -0
- package/src/resources/skills/swiftui/references/architecture.md +1561 -0
- package/src/resources/skills/swiftui/references/layout-system.md +1186 -0
- package/src/resources/skills/swiftui/references/navigation.md +1492 -0
- package/src/resources/skills/swiftui/references/networking-async.md +214 -0
- package/src/resources/skills/swiftui/references/performance.md +1706 -0
- package/src/resources/skills/swiftui/references/platform-integration.md +204 -0
- package/src/resources/skills/swiftui/references/state-management.md +1443 -0
- package/src/resources/skills/swiftui/references/swiftdata.md +297 -0
- package/src/resources/skills/swiftui/references/testing-debugging.md +247 -0
- package/src/resources/skills/swiftui/references/uikit-appkit-interop.md +218 -0
- package/src/resources/skills/swiftui/workflows/add-feature.md +191 -0
- package/src/resources/skills/swiftui/workflows/build-new-app.md +311 -0
- package/src/resources/skills/swiftui/workflows/debug-swiftui.md +192 -0
- package/src/resources/skills/swiftui/workflows/optimize-performance.md +197 -0
- package/src/resources/skills/swiftui/workflows/ship-app.md +203 -0
- package/src/resources/skills/swiftui/workflows/write-tests.md +235 -0
- package/dist/commands/task.d.ts +0 -9
- package/dist/commands/task.d.ts.map +0 -1
- package/dist/commands/task.js +0 -129
- package/dist/commands/task.js.map +0 -1
- package/dist/commands/task.test.d.ts +0 -2
- package/dist/commands/task.test.d.ts.map +0 -1
- package/dist/commands/task.test.js +0 -169
- package/dist/commands/task.test.js.map +0 -1
- package/dist/e2e/task-e2e.test.d.ts +0 -2
- package/dist/e2e/task-e2e.test.d.ts.map +0 -1
- package/dist/e2e/task-e2e.test.js +0 -173
- package/dist/e2e/task-e2e.test.js.map +0 -1
- package/dist/index.d.ts +0 -3
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -93
- package/dist/index.js.map +0 -1
- package/dist/slug.d.ts +0 -2
- package/dist/slug.d.ts.map +0 -1
- package/dist/slug.js +0 -12
- package/dist/slug.js.map +0 -1
- package/dist/slug.test.d.ts +0 -2
- package/dist/slug.test.d.ts.map +0 -1
- package/dist/slug.test.js +0 -32
- package/dist/slug.test.js.map +0 -1
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import { parseTaskPlanMustHaves } from '../files.ts';
|
|
2
|
+
|
|
3
|
+
let passed = 0;
|
|
4
|
+
let failed = 0;
|
|
5
|
+
|
|
6
|
+
function assert(condition: boolean, message: string): void {
|
|
7
|
+
if (condition) passed++;
|
|
8
|
+
else {
|
|
9
|
+
failed++;
|
|
10
|
+
console.error(` FAIL: ${message}`);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function assertEq<T>(actual: T, expected: T, message: string): void {
|
|
15
|
+
if (JSON.stringify(actual) === JSON.stringify(expected)) passed++;
|
|
16
|
+
else {
|
|
17
|
+
failed++;
|
|
18
|
+
console.error(` FAIL: ${message} — expected ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
23
|
+
// (a) Standard unchecked format: - [ ] text
|
|
24
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
25
|
+
|
|
26
|
+
console.log('\n=== parseTaskPlanMustHaves: standard unchecked ===');
|
|
27
|
+
{
|
|
28
|
+
const content = `# T01: Test Task
|
|
29
|
+
|
|
30
|
+
## Must-Haves
|
|
31
|
+
|
|
32
|
+
- [ ] First must-have item
|
|
33
|
+
- [ ] Second must-have item
|
|
34
|
+
`;
|
|
35
|
+
const result = parseTaskPlanMustHaves(content);
|
|
36
|
+
assertEq(result.length, 2, 'should return 2 items');
|
|
37
|
+
assertEq(result[0].text, 'First must-have item', 'first item text');
|
|
38
|
+
assertEq(result[0].checked, false, 'first item unchecked');
|
|
39
|
+
assertEq(result[1].text, 'Second must-have item', 'second item text');
|
|
40
|
+
assertEq(result[1].checked, false, 'second item unchecked');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
44
|
+
// (b) Checked variants: - [x] and - [X]
|
|
45
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
46
|
+
|
|
47
|
+
console.log('\n=== parseTaskPlanMustHaves: checked [x] and [X] ===');
|
|
48
|
+
{
|
|
49
|
+
const content = `## Must-Haves
|
|
50
|
+
|
|
51
|
+
- [x] Lowercase checked item
|
|
52
|
+
- [X] Uppercase checked item
|
|
53
|
+
`;
|
|
54
|
+
const result = parseTaskPlanMustHaves(content);
|
|
55
|
+
assertEq(result.length, 2, 'should return 2 items');
|
|
56
|
+
assertEq(result[0].checked, true, 'lowercase x is checked');
|
|
57
|
+
assertEq(result[0].text, 'Lowercase checked item', 'lowercase x text');
|
|
58
|
+
assertEq(result[1].checked, true, 'uppercase X is checked');
|
|
59
|
+
assertEq(result[1].text, 'Uppercase checked item', 'uppercase X text');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
63
|
+
// (c) No-checkbox bullets: - text
|
|
64
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
65
|
+
|
|
66
|
+
console.log('\n=== parseTaskPlanMustHaves: no-checkbox bullets ===');
|
|
67
|
+
{
|
|
68
|
+
const content = `## Must-Haves
|
|
69
|
+
|
|
70
|
+
- Plain bullet item
|
|
71
|
+
- Another plain item
|
|
72
|
+
`;
|
|
73
|
+
const result = parseTaskPlanMustHaves(content);
|
|
74
|
+
assertEq(result.length, 2, 'should return 2 items');
|
|
75
|
+
assertEq(result[0].text, 'Plain bullet item', 'plain bullet text');
|
|
76
|
+
assertEq(result[0].checked, false, 'plain bullet defaults to unchecked');
|
|
77
|
+
assertEq(result[1].text, 'Another plain item', 'second plain bullet text');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
81
|
+
// (d) Indented variants
|
|
82
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
83
|
+
|
|
84
|
+
console.log('\n=== parseTaskPlanMustHaves: indented variants ===');
|
|
85
|
+
{
|
|
86
|
+
const content = `## Must-Haves
|
|
87
|
+
|
|
88
|
+
- [ ] Indented unchecked item
|
|
89
|
+
- [x] Indented checked item
|
|
90
|
+
- Plain indented item
|
|
91
|
+
`;
|
|
92
|
+
const result = parseTaskPlanMustHaves(content);
|
|
93
|
+
assertEq(result.length, 3, 'should return 3 items');
|
|
94
|
+
assertEq(result[0].text, 'Indented unchecked item', 'indented unchecked text');
|
|
95
|
+
assertEq(result[0].checked, false, 'indented unchecked state');
|
|
96
|
+
assertEq(result[1].text, 'Indented checked item', 'indented checked text');
|
|
97
|
+
assertEq(result[1].checked, true, 'indented checked state');
|
|
98
|
+
assertEq(result[2].text, 'Plain indented item', 'indented plain text');
|
|
99
|
+
assertEq(result[2].checked, false, 'indented plain state');
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
103
|
+
// (e) Mixed checkbox states in one section
|
|
104
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
105
|
+
|
|
106
|
+
console.log('\n=== parseTaskPlanMustHaves: mixed states ===');
|
|
107
|
+
{
|
|
108
|
+
const content = `## Must-Haves
|
|
109
|
+
|
|
110
|
+
- [ ] Unchecked one
|
|
111
|
+
- [x] Checked one
|
|
112
|
+
- [X] Also checked
|
|
113
|
+
- Plain bullet
|
|
114
|
+
- [ ] Another unchecked
|
|
115
|
+
`;
|
|
116
|
+
const result = parseTaskPlanMustHaves(content);
|
|
117
|
+
assertEq(result.length, 5, 'should return 5 items');
|
|
118
|
+
assertEq(result[0].checked, false, 'first is unchecked');
|
|
119
|
+
assertEq(result[1].checked, true, 'second is checked');
|
|
120
|
+
assertEq(result[2].checked, true, 'third is checked (uppercase)');
|
|
121
|
+
assertEq(result[3].checked, false, 'fourth (plain) is unchecked');
|
|
122
|
+
assertEq(result[4].checked, false, 'fifth is unchecked');
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
126
|
+
// (f) Missing Must-Haves section → empty array
|
|
127
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
128
|
+
|
|
129
|
+
console.log('\n=== parseTaskPlanMustHaves: missing section ===');
|
|
130
|
+
{
|
|
131
|
+
const content = `# T01: Some Task
|
|
132
|
+
|
|
133
|
+
## Description
|
|
134
|
+
|
|
135
|
+
Some description here.
|
|
136
|
+
|
|
137
|
+
## Verification
|
|
138
|
+
|
|
139
|
+
- Run tests
|
|
140
|
+
`;
|
|
141
|
+
const result = parseTaskPlanMustHaves(content);
|
|
142
|
+
assertEq(result.length, 0, 'returns empty array when section missing');
|
|
143
|
+
assert(Array.isArray(result), 'result is an array');
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
147
|
+
// (g) Empty Must-Haves section → empty array
|
|
148
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
149
|
+
|
|
150
|
+
console.log('\n=== parseTaskPlanMustHaves: empty section ===');
|
|
151
|
+
{
|
|
152
|
+
const content = `## Must-Haves
|
|
153
|
+
|
|
154
|
+
## Verification
|
|
155
|
+
|
|
156
|
+
- Run tests
|
|
157
|
+
`;
|
|
158
|
+
const result = parseTaskPlanMustHaves(content);
|
|
159
|
+
assertEq(result.length, 0, 'returns empty array when section is empty');
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
163
|
+
// (h) Content with YAML frontmatter
|
|
164
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
165
|
+
|
|
166
|
+
console.log('\n=== parseTaskPlanMustHaves: YAML frontmatter ===');
|
|
167
|
+
{
|
|
168
|
+
const content = `---
|
|
169
|
+
estimated_steps: 5
|
|
170
|
+
estimated_files: 3
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
# T01: Task with frontmatter
|
|
174
|
+
|
|
175
|
+
## Must-Haves
|
|
176
|
+
|
|
177
|
+
- [ ] Real must-have after frontmatter
|
|
178
|
+
- [x] Checked must-have after frontmatter
|
|
179
|
+
`;
|
|
180
|
+
const result = parseTaskPlanMustHaves(content);
|
|
181
|
+
assertEq(result.length, 2, 'frontmatter does not pollute results');
|
|
182
|
+
assertEq(result[0].text, 'Real must-have after frontmatter', 'first item text correct');
|
|
183
|
+
assertEq(result[0].checked, false, 'first item unchecked');
|
|
184
|
+
assertEq(result[1].text, 'Checked must-have after frontmatter', 'second item text correct');
|
|
185
|
+
assertEq(result[1].checked, true, 'second item checked');
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Verify frontmatter content is not misinterpreted as must-haves
|
|
189
|
+
console.log('\n=== parseTaskPlanMustHaves: frontmatter-only content ===');
|
|
190
|
+
{
|
|
191
|
+
const content = `---
|
|
192
|
+
estimated_steps: 5
|
|
193
|
+
estimated_files: 3
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
# T01: Task with only frontmatter
|
|
197
|
+
|
|
198
|
+
## Description
|
|
199
|
+
|
|
200
|
+
No must-haves section here.
|
|
201
|
+
`;
|
|
202
|
+
const result = parseTaskPlanMustHaves(content);
|
|
203
|
+
assertEq(result.length, 0, 'frontmatter-only content returns empty array');
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
207
|
+
// (i) Real task plan format (based on S01/T01-PLAN.md structure)
|
|
208
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
209
|
+
|
|
210
|
+
console.log('\n=== parseTaskPlanMustHaves: real task plan format ===');
|
|
211
|
+
{
|
|
212
|
+
const content = `---
|
|
213
|
+
estimated_steps: 5
|
|
214
|
+
estimated_files: 3
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
# T01: Add completing-milestone phase to deriveState with tests
|
|
218
|
+
|
|
219
|
+
**Slice:** S01 — Milestone Completion Unit
|
|
220
|
+
**Milestone:** M002
|
|
221
|
+
|
|
222
|
+
## Description
|
|
223
|
+
|
|
224
|
+
Add the \`completing-milestone\` phase to the Kata state machine.
|
|
225
|
+
|
|
226
|
+
## Steps
|
|
227
|
+
|
|
228
|
+
1. Add \`'completing-milestone'\` to the \`Phase\` union type in \`types.ts\`.
|
|
229
|
+
2. In \`state.ts\`, modify the registry-building loop.
|
|
230
|
+
|
|
231
|
+
## Must-Haves
|
|
232
|
+
|
|
233
|
+
- [ ] \`Phase\` type includes \`'completing-milestone'\`
|
|
234
|
+
- [ ] \`deriveState\` returns \`phase: 'completing-milestone'\` when all slices are \`[x]\` and no \`M00x-SUMMARY.md\` exists
|
|
235
|
+
- [ ] \`deriveState\` returns milestone as \`'complete'\` and advances when summary exists
|
|
236
|
+
- [ ] All 63+ existing \`deriveState\` tests pass without modification
|
|
237
|
+
- [ ] New test fixtures cover single-milestone and multi-milestone completing-milestone scenarios
|
|
238
|
+
|
|
239
|
+
## Verification
|
|
240
|
+
|
|
241
|
+
- Run tests
|
|
242
|
+
- All existing 63 assertions pass
|
|
243
|
+
|
|
244
|
+
## Observability Impact
|
|
245
|
+
|
|
246
|
+
- Signals added/changed: \`completing-milestone\` phase now visible
|
|
247
|
+
- How a future agent inspects this: Run \`deriveState(basePath)\`
|
|
248
|
+
- Failure state exposed: If \`deriveState\` doesn't detect the phase
|
|
249
|
+
|
|
250
|
+
## Inputs
|
|
251
|
+
|
|
252
|
+
- \`agent/extensions/kata/types.ts\` — Phase type definition
|
|
253
|
+
|
|
254
|
+
## Expected Output
|
|
255
|
+
|
|
256
|
+
- \`agent/extensions/kata/types.ts\` — Phase union includes \`'completing-milestone'\`
|
|
257
|
+
`;
|
|
258
|
+
const result = parseTaskPlanMustHaves(content);
|
|
259
|
+
assertEq(result.length, 5, 'real plan has 5 must-haves');
|
|
260
|
+
assert(result[0].text.includes('`Phase` type includes'), 'first must-have text matches');
|
|
261
|
+
assert(result[1].text.includes('`deriveState` returns'), 'second must-have text matches');
|
|
262
|
+
assertEq(result[0].checked, false, 'all real must-haves are unchecked');
|
|
263
|
+
assertEq(result[4].checked, false, 'last real must-have is unchecked');
|
|
264
|
+
assert(result[4].text.includes('multi-milestone'), 'last must-have references multi-milestone');
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
268
|
+
// Edge cases
|
|
269
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
270
|
+
|
|
271
|
+
console.log('\n=== parseTaskPlanMustHaves: empty string ===');
|
|
272
|
+
{
|
|
273
|
+
const result = parseTaskPlanMustHaves('');
|
|
274
|
+
assertEq(result.length, 0, 'empty string returns empty array');
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
console.log('\n=== parseTaskPlanMustHaves: must-haves with inline code and backticks ===');
|
|
278
|
+
{
|
|
279
|
+
const content = `## Must-Haves
|
|
280
|
+
|
|
281
|
+
- [ ] \`functionName\` is exported from \`module.ts\`
|
|
282
|
+
- [x] Returns \`Array<{ text: string }>\` with correct extraction
|
|
283
|
+
`;
|
|
284
|
+
const result = parseTaskPlanMustHaves(content);
|
|
285
|
+
assertEq(result.length, 2, 'handles backtick content');
|
|
286
|
+
assert(result[0].text.includes('`functionName`'), 'preserves backticks in text');
|
|
287
|
+
assertEq(result[0].checked, false, 'backtick item unchecked');
|
|
288
|
+
assertEq(result[1].checked, true, 'backtick item checked');
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
console.log('\n=== parseTaskPlanMustHaves: asterisk bullets ===');
|
|
292
|
+
{
|
|
293
|
+
const content = `## Must-Haves
|
|
294
|
+
|
|
295
|
+
* [ ] Asterisk unchecked
|
|
296
|
+
* [x] Asterisk checked
|
|
297
|
+
* Plain asterisk
|
|
298
|
+
`;
|
|
299
|
+
const result = parseTaskPlanMustHaves(content);
|
|
300
|
+
assertEq(result.length, 3, 'handles asterisk bullets');
|
|
301
|
+
assertEq(result[0].checked, false, 'asterisk unchecked');
|
|
302
|
+
assertEq(result[1].checked, true, 'asterisk checked');
|
|
303
|
+
assertEq(result[2].checked, false, 'plain asterisk unchecked');
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
307
|
+
|
|
308
|
+
console.log(`\n=== Results: ${passed} passed, ${failed} failed ===\n`);
|
|
309
|
+
process.exit(failed > 0 ? 1 : 0);
|