@aipper/aiws 0.0.47 → 0.0.49

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 (112) hide show
  1. package/dist/backup.d.ts +1 -1
  2. package/dist/backup.js.map +1 -1
  3. package/dist/cli.js +6 -0
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/change-advice.d.ts +8 -6
  6. package/dist/commands/change-advice.js +2 -0
  7. package/dist/commands/change-advice.js.map +1 -1
  8. package/dist/commands/change-evidence-command.js +2 -0
  9. package/dist/commands/change-evidence-command.js.map +1 -1
  10. package/dist/commands/change-evidence-entry.js +1 -0
  11. package/dist/commands/change-evidence-entry.js.map +1 -1
  12. package/dist/commands/change-evidence.js +4 -1
  13. package/dist/commands/change-evidence.js.map +1 -1
  14. package/dist/commands/change-finish.js +16 -0
  15. package/dist/commands/change-finish.js.map +1 -1
  16. package/dist/commands/change-lifecycle-entry.js +2 -0
  17. package/dist/commands/change-lifecycle-entry.js.map +1 -1
  18. package/dist/commands/change-lifecycle.js +3 -0
  19. package/dist/commands/change-lifecycle.js.map +1 -1
  20. package/dist/commands/change-metrics-command.js +1 -0
  21. package/dist/commands/change-metrics-command.js.map +1 -1
  22. package/dist/commands/change-next-command.js +1 -0
  23. package/dist/commands/change-next-command.js.map +1 -1
  24. package/dist/commands/change-review-gates.d.ts +5 -1
  25. package/dist/commands/change-review-gates.js +4 -0
  26. package/dist/commands/change-review-gates.js.map +1 -1
  27. package/dist/commands/change-scope-gate.js +1 -0
  28. package/dist/commands/change-scope-gate.js.map +1 -1
  29. package/dist/commands/change-start.js +7 -4
  30. package/dist/commands/change-start.js.map +1 -1
  31. package/dist/commands/change-state-command.js +1 -0
  32. package/dist/commands/change-state-command.js.map +1 -1
  33. package/dist/commands/change-status-command.js +2 -1
  34. package/dist/commands/change-status-command.js.map +1 -1
  35. package/dist/commands/change-status-context.js +4 -0
  36. package/dist/commands/change-status-context.js.map +1 -1
  37. package/dist/commands/change-utils.js +2 -0
  38. package/dist/commands/change-utils.js.map +1 -1
  39. package/dist/commands/change-validate-entry.js +1 -0
  40. package/dist/commands/change-validate-entry.js.map +1 -1
  41. package/dist/commands/change-validate.js +1 -0
  42. package/dist/commands/change-validate.js.map +1 -1
  43. package/dist/commands/change.d.ts +11 -9
  44. package/dist/commands/change.js +43 -1
  45. package/dist/commands/change.js.map +1 -1
  46. package/dist/commands/dashboard.d.ts +9 -7
  47. package/dist/commands/dashboard.js +3 -0
  48. package/dist/commands/dashboard.js.map +1 -1
  49. package/dist/commands/goal-advance.d.ts +11 -3
  50. package/dist/commands/goal-advance.js +330 -21
  51. package/dist/commands/goal-advance.js.map +1 -1
  52. package/dist/commands/goal-advance.test.d.ts +1 -0
  53. package/dist/commands/goal-advance.test.js +271 -0
  54. package/dist/commands/goal-advance.test.js.map +1 -0
  55. package/dist/commands/goal-help.js +32 -15
  56. package/dist/commands/goal-help.js.map +1 -1
  57. package/dist/commands/goal-validate-state.d.ts +59 -1
  58. package/dist/commands/goal-validate-state.js +310 -4
  59. package/dist/commands/goal-validate-state.js.map +1 -1
  60. package/dist/commands/goal-validate.d.ts +5 -0
  61. package/dist/commands/goal-validate.js +120 -14
  62. package/dist/commands/goal-validate.js.map +1 -1
  63. package/dist/commands/hooks-install.js +1 -0
  64. package/dist/commands/hooks-install.js.map +1 -1
  65. package/dist/commands/hooks-status.js +1 -0
  66. package/dist/commands/hooks-status.js.map +1 -1
  67. package/dist/commands/memory.js +0 -2
  68. package/dist/commands/memory.js.map +1 -1
  69. package/dist/commands/opencode-auto.js +2 -0
  70. package/dist/commands/opencode-auto.js.map +1 -1
  71. package/dist/commands/opencode-status.js +1 -0
  72. package/dist/commands/opencode-status.js.map +1 -1
  73. package/dist/commands/opencode-supervise.js +7 -0
  74. package/dist/commands/opencode-supervise.js.map +1 -1
  75. package/dist/commands/rollback.js +1 -0
  76. package/dist/commands/rollback.js.map +1 -1
  77. package/dist/commands/update.js +2 -1
  78. package/dist/commands/update.js.map +1 -1
  79. package/dist/commands/validate.js +3 -0
  80. package/dist/commands/validate.js.map +1 -1
  81. package/dist/commands/ws-deliver.js +2 -2
  82. package/dist/commands/ws-deliver.js.map +1 -1
  83. package/dist/commands/ws-finish.d.ts +7 -0
  84. package/dist/commands/ws-finish.js +19 -128
  85. package/dist/commands/ws-finish.js.map +1 -1
  86. package/dist/commands/ws-finish.test.d.ts +1 -0
  87. package/dist/commands/ws-finish.test.js +167 -0
  88. package/dist/commands/ws-finish.test.js.map +1 -0
  89. package/dist/commands/ws-migrate.js +1 -0
  90. package/dist/commands/ws-migrate.js.map +1 -1
  91. package/dist/commands/ws-pull.js.map +1 -1
  92. package/dist/commands/ws-push.js +0 -3
  93. package/dist/commands/ws-push.js.map +1 -1
  94. package/dist/commands/ws-submodule-setup.js.map +1 -1
  95. package/dist/dashboard/app.js +1 -1
  96. package/dist/dashboard/app.js.map +1 -1
  97. package/dist/governance.js +5 -0
  98. package/dist/governance.js.map +1 -1
  99. package/dist/journal.js +9 -3
  100. package/dist/journal.js.map +1 -1
  101. package/dist/json-schema-lite.js +2 -0
  102. package/dist/json-schema-lite.js.map +1 -1
  103. package/dist/manifest.d.ts +21 -2
  104. package/dist/manifest.js +1 -0
  105. package/dist/manifest.js.map +1 -1
  106. package/dist/memory-bank/store.js +0 -1
  107. package/dist/memory-bank/store.js.map +1 -1
  108. package/dist/opencode-env.js +3 -0
  109. package/dist/opencode-env.js.map +1 -1
  110. package/dist/spec.js +7 -0
  111. package/dist/spec.js.map +1 -1
  112. package/package.json +4 -3
@@ -0,0 +1,271 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from "vitest";
2
+ import fs from "node:fs/promises";
3
+ import path from "node:path";
4
+ import os from "node:os";
5
+ import { goalAdvanceCommand } from "./goal-advance.js";
6
+ import { VALID_PHASES, createInitialGoalState, analyzeGoalDirtyState, healGoalState, validateGoalState, writeGoalState, readGoalState, } from "./goal-validate-state.js";
7
+ import { goalValidateStateCommand } from "./goal-validate.js";
8
+ function allCompleteState(goalId, overall) {
9
+ const base = createInitialGoalState(goalId);
10
+ const now = new Date().toISOString();
11
+ for (const phase of VALID_PHASES) {
12
+ base.checkpoints[phase] = {
13
+ status: "complete",
14
+ attempts: 1,
15
+ completed_at: now,
16
+ error: null,
17
+ };
18
+ }
19
+ base.status = overall;
20
+ base.current_phase = "finish";
21
+ return base;
22
+ }
23
+ function midState(goalId, current) {
24
+ const base = createInitialGoalState(goalId);
25
+ const now = new Date().toISOString();
26
+ const idx = VALID_PHASES.indexOf(current);
27
+ for (let i = 0; i < idx; i++) {
28
+ const p = VALID_PHASES[i];
29
+ base.checkpoints[p] = {
30
+ status: "complete",
31
+ attempts: 1,
32
+ completed_at: now,
33
+ error: null,
34
+ };
35
+ }
36
+ base.checkpoints[current] = {
37
+ status: "in_progress",
38
+ attempts: 1,
39
+ completed_at: null,
40
+ error: null,
41
+ };
42
+ base.current_phase = current;
43
+ base.status = "active";
44
+ return base;
45
+ }
46
+ describe("goal dirty analysis + heal", () => {
47
+ it("detects all checkpoints complete but status still active", () => {
48
+ const state = allCompleteState("G-TEST", "active");
49
+ const dirty = analyzeGoalDirtyState(state);
50
+ expect(dirty.dirty).toBe(true);
51
+ expect(dirty.reasons).toContain("all_checkpoints_complete_status_not_complete");
52
+ });
53
+ it("detects status active with current_phase past all complete", () => {
54
+ const state = allCompleteState("G-TEST", "active");
55
+ state.current_phase = "dev";
56
+ const dirty = analyzeGoalDirtyState(state);
57
+ expect(dirty.dirty).toBe(true);
58
+ expect(dirty.reasons).toContain("status_active_current_phase_after_all_complete");
59
+ });
60
+ it("heals complete+active to status=complete", () => {
61
+ const state = allCompleteState("G-TEST", "active");
62
+ const heal = healGoalState(state);
63
+ expect(heal.healed).toBe(true);
64
+ expect(heal.state.status).toBe("complete");
65
+ expect(analyzeGoalDirtyState(heal.state).dirty).toBe(false);
66
+ });
67
+ it("heals status=complete with incomplete checkpoints by reopening active", () => {
68
+ const state = allCompleteState("G-TEST", "complete");
69
+ state.checkpoints["finish"] = {
70
+ status: "pending",
71
+ attempts: 0,
72
+ completed_at: null,
73
+ error: null,
74
+ };
75
+ const dirty = analyzeGoalDirtyState(state);
76
+ expect(dirty.dirty).toBe(true);
77
+ expect(dirty.reasons).toContain("status_complete_with_incomplete_checkpoints");
78
+ const heal = healGoalState(state);
79
+ expect(heal.state.status).toBe("active");
80
+ expect(heal.state.current_phase).toBe("finish");
81
+ });
82
+ it("heals missing completed_at on complete phases", () => {
83
+ const state = midState("G-TEST", "goal_def");
84
+ state.checkpoints["intake"] = {
85
+ status: "complete",
86
+ attempts: 1,
87
+ completed_at: null,
88
+ error: null,
89
+ };
90
+ const dirty = analyzeGoalDirtyState(state);
91
+ expect(dirty.reasons).toContain("complete_missing_completed_at");
92
+ const heal = healGoalState(state);
93
+ expect(heal.state.checkpoints["intake"].completed_at).toBeTruthy();
94
+ });
95
+ it("validateGoalState rejects dirty by default", () => {
96
+ const state = allCompleteState("G-TEST", "active");
97
+ const result = validateGoalState(state);
98
+ expect(result.valid).toBe(false);
99
+ expect(result.errors.some((e) => e.includes("Dirty state"))).toBe(true);
100
+ });
101
+ it("validateGoalState can skip dirty with includeDirty:false", () => {
102
+ const state = allCompleteState("G-TEST", "active");
103
+ // structural only — all complete is structurally fine
104
+ const result = validateGoalState(state, { includeDirty: false });
105
+ expect(result.valid).toBe(true);
106
+ });
107
+ });
108
+ describe("goalAdvanceCommand sole writer + heal", () => {
109
+ let tmpDir;
110
+ let goalDir;
111
+ beforeEach(async () => {
112
+ tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "goal-advance-"));
113
+ goalDir = path.join(tmpDir, ".aiws", "goals");
114
+ await fs.mkdir(goalDir, { recursive: true });
115
+ });
116
+ afterEach(async () => {
117
+ await fs.rm(tmpDir, { recursive: true, force: true });
118
+ });
119
+ it("auto-advances in_progress phase to next", async () => {
120
+ const state = midState("G-ADV", "intake");
121
+ await writeGoalState(path.join(goalDir, "G-ADV.state.json"), state);
122
+ const { ok, output } = await goalAdvanceCommand({
123
+ goalDir,
124
+ goalId: "G-ADV",
125
+ json: true,
126
+ });
127
+ expect(ok).toBe(true);
128
+ const parsed = JSON.parse(output);
129
+ expect(parsed.ok).toBe(true);
130
+ expect(parsed.current_phase).toBe("goal_def");
131
+ expect(parsed.sole_writer).toBe("aiws goal advance");
132
+ const after = await readGoalState(path.join(goalDir, "G-ADV.state.json"));
133
+ expect(after.checkpoints["intake"].status).toBe("complete");
134
+ expect(after.checkpoints["goal_def"].status).toBe("in_progress");
135
+ expect(after.current_phase).toBe("goal_def");
136
+ });
137
+ it("refuses dirty state without --heal", async () => {
138
+ const state = allCompleteState("G-DIRTY", "active");
139
+ await writeGoalState(path.join(goalDir, "G-DIRTY.state.json"), state);
140
+ const { ok, output } = await goalAdvanceCommand({
141
+ goalDir,
142
+ goalId: "G-DIRTY",
143
+ });
144
+ expect(ok).toBe(false);
145
+ expect(output).toMatch(/Dirty goal state/i);
146
+ expect(output).toMatch(/--heal/);
147
+ });
148
+ it("heals all-complete+active to complete with --heal", async () => {
149
+ const state = allCompleteState("G-HEAL", "active");
150
+ await writeGoalState(path.join(goalDir, "G-HEAL.state.json"), state);
151
+ const { ok, output } = await goalAdvanceCommand({
152
+ goalDir,
153
+ goalId: "G-HEAL",
154
+ heal: true,
155
+ json: true,
156
+ });
157
+ expect(ok).toBe(true);
158
+ const parsed = JSON.parse(output);
159
+ expect(parsed.done || parsed.status === "complete").toBe(true);
160
+ const after = await readGoalState(path.join(goalDir, "G-HEAL.state.json"));
161
+ expect(after.status).toBe("complete");
162
+ });
163
+ it("heals status complete with incomplete checkpoints", async () => {
164
+ const state = allCompleteState("G-REOPEN", "complete");
165
+ state.checkpoints["finish"] = {
166
+ status: "pending",
167
+ attempts: 0,
168
+ completed_at: null,
169
+ error: null,
170
+ };
171
+ await writeGoalState(path.join(goalDir, "G-REOPEN.state.json"), state);
172
+ const { ok } = await goalAdvanceCommand({
173
+ goalDir,
174
+ goalId: "G-REOPEN",
175
+ heal: true,
176
+ });
177
+ expect(ok).toBe(true);
178
+ const after = await readGoalState(path.join(goalDir, "G-REOPEN.state.json"));
179
+ expect(after.status).toBe("active");
180
+ expect(after.current_phase).toBe("finish");
181
+ });
182
+ it("migrates missing state.json from active .md with --heal", async () => {
183
+ const md = `---
184
+ ws_goal:
185
+ version: 1
186
+ state: active
187
+ iteration: 1
188
+ ---
189
+
190
+ # G-MIG: migration test
191
+ `;
192
+ await fs.writeFile(path.join(goalDir, "G-MIG.md"), md, "utf8");
193
+ const { ok, output } = await goalAdvanceCommand({
194
+ goalDir,
195
+ goalId: "G-MIG",
196
+ heal: true,
197
+ json: true,
198
+ });
199
+ expect(ok).toBe(true);
200
+ const statePath = path.join(goalDir, "G-MIG.state.json");
201
+ await expect(fs.access(statePath)).resolves.toBeUndefined();
202
+ const after = await readGoalState(statePath);
203
+ expect(after.status).toBe("active");
204
+ expect(after.current_phase).toBe("intake");
205
+ expect(after.checkpoints["intake"].status).toBe("in_progress");
206
+ expect(output).toMatch(/Migrat|heal|intake/i);
207
+ });
208
+ it("dry-run does not write", async () => {
209
+ const state = midState("G-DRY", "intake");
210
+ const statePath = path.join(goalDir, "G-DRY.state.json");
211
+ await writeGoalState(statePath, state);
212
+ const before = await fs.readFile(statePath, "utf8");
213
+ const { ok, output } = await goalAdvanceCommand({
214
+ goalDir,
215
+ goalId: "G-DRY",
216
+ dryRun: true,
217
+ });
218
+ expect(ok).toBe(true);
219
+ expect(output).toMatch(/DRY RUN/i);
220
+ const after = await fs.readFile(statePath, "utf8");
221
+ // dry-run may still have same logical content (updated_at may differ only if wrote)
222
+ const afterState = JSON.parse(after);
223
+ expect(afterState.checkpoints.intake.status).toBe("in_progress");
224
+ expect(afterState.current_phase).toBe("intake");
225
+ // ensure content wasn't rewritten with completed intake
226
+ expect(JSON.parse(before).checkpoints.intake.status).toBe("in_progress");
227
+ });
228
+ it("blocks advance to phase when prerequisite incomplete", async () => {
229
+ const state = midState("G-BLOCK", "intake");
230
+ await writeGoalState(path.join(goalDir, "G-BLOCK.state.json"), state);
231
+ const { ok, output } = await goalAdvanceCommand({
232
+ goalDir,
233
+ goalId: "G-BLOCK",
234
+ phase: "dev",
235
+ });
236
+ expect(ok).toBe(false);
237
+ expect(output).toMatch(/prerequisite|Cannot advance/i);
238
+ });
239
+ });
240
+ describe("goalValidateStateCommand heal", () => {
241
+ let tmpDir;
242
+ let goalDir;
243
+ beforeEach(async () => {
244
+ tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "goal-validate-"));
245
+ goalDir = path.join(tmpDir, ".aiws", "goals");
246
+ await fs.mkdir(goalDir, { recursive: true });
247
+ });
248
+ afterEach(async () => {
249
+ await fs.rm(tmpDir, { recursive: true, force: true });
250
+ });
251
+ it("fails dirty without heal and passes after heal", async () => {
252
+ const state = allCompleteState("G-V", "active");
253
+ await writeGoalState(path.join(goalDir, "G-V.state.json"), state);
254
+ const fail = await goalValidateStateCommand({
255
+ goalDir,
256
+ goalId: "G-V",
257
+ });
258
+ expect(fail.ok).toBe(false);
259
+ expect(fail.output).toMatch(/Dirty|FAIL/i);
260
+ const healed = await goalValidateStateCommand({
261
+ goalDir,
262
+ goalId: "G-V",
263
+ heal: true,
264
+ });
265
+ expect(healed.ok).toBe(true);
266
+ expect(healed.output).toMatch(/Healed|PASS/i);
267
+ const after = await readGoalState(path.join(goalDir, "G-V.state.json"));
268
+ expect(after.status).toBe("complete");
269
+ });
270
+ });
271
+ //# sourceMappingURL=goal-advance.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"goal-advance.test.js","sourceRoot":"","sources":["../../src/commands/goal-advance.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAEL,YAAY,EACZ,sBAAsB,EACtB,qBAAqB,EACrB,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,aAAa,GACd,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAE9D,SAAS,gBAAgB,CAAC,MAAc,EAAE,OAAe;IACvD,MAAM,IAAI,GAAG,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAC5C,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACrC,KAAK,MAAM,KAAK,IAAI,YAAY,EAAE,CAAC;QACjC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG;YACxB,MAAM,EAAE,UAAU;YAClB,QAAQ,EAAE,CAAC;YACX,YAAY,EAAE,GAAG;YACjB,KAAK,EAAE,IAAI;SACZ,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC;IACtB,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC;IAC9B,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,QAAQ,CAAC,MAAc,EAAE,OAAe;IAC/C,MAAM,IAAI,GAAG,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAC5C,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACrC,MAAM,GAAG,GAAG,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7B,MAAM,CAAC,GAAG,YAAY,CAAC,CAAC,CAAE,CAAC;QAC3B,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG;YACpB,MAAM,EAAE,UAAU;YAClB,QAAQ,EAAE,CAAC;YACX,YAAY,EAAE,GAAG;YACjB,KAAK,EAAE,IAAI;SACZ,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,GAAG;QAC1B,MAAM,EAAE,aAAa;QACrB,QAAQ,EAAE,CAAC;QACX,YAAY,EAAE,IAAI;QAClB,KAAK,EAAE,IAAI;KACZ,CAAC;IACF,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC;IAC7B,IAAI,CAAC,MAAM,GAAG,QAAQ,CAAC;IACvB,OAAO,IAAI,CAAC;AACd,CAAC;AAED,QAAQ,CAAC,4BAA4B,EAAE,GAAG,EAAE;IAC1C,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,MAAM,KAAK,GAAG,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACnD,MAAM,KAAK,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;QAC3C,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,SAAS,CAC7B,8CAA8C,CAC/C,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACpE,MAAM,KAAK,GAAG,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACnD,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC;QAC5B,MAAM,KAAK,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;QAC3C,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,SAAS,CAC7B,gDAAgD,CACjD,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,KAAK,GAAG,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACnD,MAAM,IAAI,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;QAClC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC3C,MAAM,CAAC,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uEAAuE,EAAE,GAAG,EAAE;QAC/E,MAAM,KAAK,GAAG,gBAAgB,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QACrD,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,GAAG;YAC5B,MAAM,EAAE,SAAS;YACjB,QAAQ,EAAE,CAAC;YACX,YAAY,EAAE,IAAI;YAClB,KAAK,EAAE,IAAI;SACZ,CAAC;QACF,MAAM,KAAK,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;QAC3C,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,SAAS,CAC7B,6CAA6C,CAC9C,CAAC;QACF,MAAM,IAAI,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;QAClC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACzC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QAC7C,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,GAAG;YAC5B,MAAM,EAAE,UAAU;YAClB,QAAQ,EAAE,CAAC;YACX,YAAY,EAAE,IAAI;YAClB,KAAK,EAAE,IAAI;SACZ,CAAC;QACF,MAAM,KAAK,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;QAC3C,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,+BAA+B,CAAC,CAAC;QACjE,MAAM,IAAI,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;QAClC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAE,CAAC,YAAY,CAAC,CAAC,UAAU,EAAE,CAAC;IACtE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,KAAK,GAAG,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACnD,MAAM,MAAM,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;QACxC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACjC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,MAAM,KAAK,GAAG,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACnD,sDAAsD;QACtD,MAAM,MAAM,GAAG,iBAAiB,CAAC,KAAK,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC;QACjE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,uCAAuC,EAAE,GAAG,EAAE;IACrD,IAAI,MAAc,CAAC;IACnB,IAAI,OAAe,CAAC;IAEpB,UAAU,CAAC,KAAK,IAAI,EAAE;QACpB,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC;QACnE,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAC9C,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,MAAM,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;QACvD,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QAC1C,MAAM,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,kBAAkB,CAAC,EAAE,KAAK,CAAC,CAAC;QAEpE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,MAAM,kBAAkB,CAAC;YAC9C,OAAO;YACP,MAAM,EAAE,OAAO;YACf,IAAI,EAAE,IAAI;SACX,CAAC,CAAC;QACH,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAClC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7B,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC9C,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;QAErD,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,kBAAkB,CAAC,CAAC,CAAC;QAC1E,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC7D,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,UAAU,CAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAClE,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;QAClD,MAAM,KAAK,GAAG,gBAAgB,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QACpD,MAAM,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,oBAAoB,CAAC,EAAE,KAAK,CAAC,CAAC;QAEtE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,MAAM,kBAAkB,CAAC;YAC9C,OAAO;YACP,MAAM,EAAE,SAAS;SAClB,CAAC,CAAC;QACH,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvB,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;QAC5C,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;QACjE,MAAM,KAAK,GAAG,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACnD,MAAM,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,mBAAmB,CAAC,EAAE,KAAK,CAAC,CAAC;QAErE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,MAAM,kBAAkB,CAAC;YAC9C,OAAO;YACP,MAAM,EAAE,QAAQ;YAChB,IAAI,EAAE,IAAI;YACV,IAAI,EAAE,IAAI;SACX,CAAC,CAAC;QACH,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAClC,MAAM,CAAC,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAE/D,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC;QAC3E,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;QACjE,MAAM,KAAK,GAAG,gBAAgB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;QACvD,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,GAAG;YAC5B,MAAM,EAAE,SAAS;YACjB,QAAQ,EAAE,CAAC;YACX,YAAY,EAAE,IAAI;YAClB,KAAK,EAAE,IAAI;SACZ,CAAC;QACF,MAAM,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,qBAAqB,CAAC,EAAE,KAAK,CAAC,CAAC;QAEvE,MAAM,EAAE,EAAE,EAAE,GAAG,MAAM,kBAAkB,CAAC;YACtC,OAAO;YACP,MAAM,EAAE,UAAU;YAClB,IAAI,EAAE,IAAI;SACX,CAAC,CAAC;QACH,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtB,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,qBAAqB,CAAC,CAAC,CAAC;QAC7E,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACpC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,KAAK,IAAI,EAAE;QACvE,MAAM,EAAE,GAAG;;;;;;;;CAQd,CAAC;QACE,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;QAE/D,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,MAAM,kBAAkB,CAAC;YAC9C,OAAO;YACP,MAAM,EAAE,OAAO;YACf,IAAI,EAAE,IAAI;YACV,IAAI,EAAE,IAAI;SACX,CAAC,CAAC;QACH,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtB,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,kBAAkB,CAAC,CAAC;QACzD,MAAM,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;QAC5D,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,SAAS,CAAC,CAAC;QAC7C,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACpC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC3C,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAChE,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wBAAwB,EAAE,KAAK,IAAI,EAAE;QACtC,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QAC1C,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,kBAAkB,CAAC,CAAC;QACzD,MAAM,cAAc,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QACvC,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QAEpD,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,MAAM,kBAAkB,CAAC;YAC9C,OAAO;YACP,MAAM,EAAE,OAAO;YACf,MAAM,EAAE,IAAI;SACb,CAAC,CAAC;QACH,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtB,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACnC,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QACnD,oFAAoF;QACpF,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACrC,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACjE,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAChD,wDAAwD;QACxD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC3E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sDAAsD,EAAE,KAAK,IAAI,EAAE;QACpE,MAAM,KAAK,GAAG,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QAC5C,MAAM,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,oBAAoB,CAAC,EAAE,KAAK,CAAC,CAAC;QAEtE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,MAAM,kBAAkB,CAAC;YAC9C,OAAO;YACP,MAAM,EAAE,SAAS;YACjB,KAAK,EAAE,KAAK;SACb,CAAC,CAAC;QACH,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvB,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,8BAA8B,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,+BAA+B,EAAE,GAAG,EAAE;IAC7C,IAAI,MAAc,CAAC;IACnB,IAAI,OAAe,CAAC;IAEpB,UAAU,CAAC,KAAK,IAAI,EAAE;QACpB,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;QACpE,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAC9C,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,MAAM,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;QAC9D,MAAM,KAAK,GAAG,gBAAgB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QAChD,MAAM,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,gBAAgB,CAAC,EAAE,KAAK,CAAC,CAAC;QAElE,MAAM,IAAI,GAAG,MAAM,wBAAwB,CAAC;YAC1C,OAAO;YACP,MAAM,EAAE,KAAK;SACd,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC5B,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;QAE3C,MAAM,MAAM,GAAG,MAAM,wBAAwB,CAAC;YAC5C,OAAO;YACP,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,IAAI;SACX,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7B,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QAE9C,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC;QACxE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,32 +1,49 @@
1
1
  export function printGoalHelp() {
2
2
  console.log(`aiws goal
3
3
 
4
+ Authority CLI for goal state machine (contract §10 / TOOLING-003D).
5
+ \`aiws goal advance\` is the sole phase-boundary writer for
6
+ \`.aiws/goals/<id>.state.json\` (checkpoint status, current_phase, status).
7
+ Skills/agents MUST NOT hand-edit those fields — call advance at each phase boundary.
8
+
4
9
  Usage:
5
- aiws goal advance [--goal-id <id>] [--phase <phase>] [--dry-run] [--json]
6
- aiws goal validate-state [--goal-id <id>]
10
+ aiws goal advance [--goal-id <id>] [--phase <phase>] [--dry-run] [--heal] [--json]
11
+ aiws goal validate-state [--goal-id <id>] [--heal] [--json]
12
+ aiws goal help
7
13
 
8
14
  Subcommands:
9
- advance Advance a goal to the next phase (auto-detect) or to an
10
- explicit phase (--phase). Completes current phase first if
11
- it is in_progress, then starts the next phase.
12
- validate-state Validate one or all goal state files for structural
13
- integrity. Reports errors and warnings.
15
+ advance Sole writer: complete current in_progress phase (if any),
16
+ validate, then start next phase (or --phase). Use --heal for
17
+ dirty FSM recovery or §7.6 migration (active .md, no state.json).
18
+ validate-state Validate one or all goal state files (structure + dirty).
19
+ With --heal, write healed snapshots (same heal path as advance).
14
20
 
15
21
  Options:
16
22
  --goal-id <id> Target a specific goal by ID (e.g., G-014). If omitted,
17
- auto-detects the active goal.
18
- --phase <phase> Explicit target phase. Valid values:
23
+ auto-detects the active goal (advance) or validates all
24
+ (validate-state).
25
+ --phase <phase> Explicit target phase (advance only). Valid values:
19
26
  intake, goal_def, dep_check, ws_analysis, plan, dev,
20
27
  review, finish
21
- --dry-run Show what would change without writing (advance only)
22
- --json Output structured JSON for AI consumption. Includes
23
- next_actions guidance: phase name, description, blockers,
24
- and whether user input is needed.
28
+ --dry-run Show what would change without writing
29
+ --heal Heal dirty state before advance, or heal on validate-state:
30
+ - all checkpoints complete but status still active → complete
31
+ - status complete with incomplete checkpoints → reopen active
32
+ - missing completed_at / missing checkpoint shells
33
+ - missing state.json with active/paused .md → migrate (§7.6)
34
+ --json Structured JSON for AI (includes next_actions, sole_writer,
35
+ heal_actions when applicable)
36
+
37
+ Dirty / heal:
38
+ Hand-edited or drifted state is rejected by validate-state and by advance
39
+ (without --heal). Recovery is always via CLI heal path — not freehand JSON.
25
40
 
26
41
  Notes:
27
- - Phase sequence is enforced: no phase can complete before its predecessors.
28
- - State files are stored as .aiws/goals/<goal-id>.state.json.
42
+ - Phase sequence is enforced: no phase completes before its predecessors.
43
+ - State files: .aiws/goals/<goal-id>.state.json (atomic write).
29
44
  - Groups (if defined) are walked in topological order.
45
+ - Platform continuation (Ralph/Boulder) may re-invoke advance; they do not
46
+ own the FSM write path.
30
47
  `);
31
48
  }
32
49
  //# sourceMappingURL=goal-help.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"goal-help.js","sourceRoot":"","sources":["../../src/commands/goal-help.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,aAAa;IAC3B,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4Bb,CAAC,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"goal-help.js","sourceRoot":"","sources":["../../src/commands/goal-help.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,aAAa;IAC3B,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6Cb,CAAC,CAAC;AACH,CAAC"}
@@ -32,6 +32,62 @@ export interface GoalState {
32
32
  created_at?: string;
33
33
  updated_at?: string;
34
34
  }
35
+ /**
36
+ * Dirty-state reasons that validate-state can reject and advance --heal can fix.
37
+ * Sole writer for phase transitions remains `aiws goal advance` (contract §10).
38
+ */
39
+ export type GoalDirtyReason = "all_checkpoints_complete_status_not_complete" | "status_active_current_phase_after_all_complete" | "status_complete_with_incomplete_checkpoints" | "complete_missing_completed_at" | "missing_required_checkpoints" | "current_phase_mismatch";
40
+ export interface GoalDirtyAnalysis {
41
+ dirty: boolean;
42
+ reasons: GoalDirtyReason[];
43
+ details: string[];
44
+ healable: boolean;
45
+ }
46
+ /**
47
+ * Detect semantic dirty states beyond pure structural validation.
48
+ * Examples: all checkpoints complete but overall status still active;
49
+ * status complete while some phases pending; missing completed_at.
50
+ */
51
+ export declare function analyzeGoalDirtyState(state: GoalState): GoalDirtyAnalysis;
52
+ export interface HealGoalStateResult {
53
+ healed: boolean;
54
+ state: GoalState;
55
+ actions: string[];
56
+ dirtyBefore: GoalDirtyAnalysis;
57
+ }
58
+ /**
59
+ * Heal dirty goal state into a legal FSM snapshot.
60
+ * Does not invent progress: only reconciles status/current_phase/completed_at/missing shells.
61
+ * Phase boundary transitions after heal still go through advance.
62
+ */
63
+ export declare function healGoalState(state: GoalState): HealGoalStateResult;
64
+ /**
65
+ * Create a minimal valid initial goal state (all pending).
66
+ */
67
+ export declare function createInitialGoalState(goalId: string): GoalState;
68
+ /**
69
+ * Parse ws_goal.state from goal markdown frontmatter (simple, no full YAML dep).
70
+ */
71
+ export declare function parseGoalMarkdownState(mdContent: string): {
72
+ state: string | null;
73
+ iteration: number | null;
74
+ };
75
+ /**
76
+ * Find goals that have .md with active/paused but no .state.json (migration candidates §7.6).
77
+ */
78
+ export declare function findGoalsNeedingMigration(goalDir: string): Promise<Array<{
79
+ goalId: string;
80
+ mdPath: string;
81
+ mdState: string;
82
+ }>>;
83
+ /**
84
+ * Migrate legacy goal .md → state.json (all checkpoints pending, current_phase null per §7.6).
85
+ */
86
+ export declare function migrateGoalFromMarkdown(goalDir: string, goalId: string): Promise<{
87
+ ok: boolean;
88
+ statePath: string;
89
+ message: string;
90
+ }>;
35
91
  /**
36
92
  * Validate a goal state's structural integrity.
37
93
  *
@@ -43,7 +99,9 @@ export interface GoalState {
43
99
  * e) Group statuses are valid (pending/in_progress/complete)
44
100
  * f) Groups with a `phase` set must have that parent phase complete
45
101
  */
46
- export declare function validateGoalState(state: GoalState): {
102
+ export declare function validateGoalState(state: GoalState, options?: {
103
+ includeDirty?: boolean;
104
+ }): {
47
105
  valid: boolean;
48
106
  errors: string[];
49
107
  warnings: string[];