@iq-context/core 0.1.0 → 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.
- package/LICENSE +21 -0
- package/dist/capture.js +2 -1
- package/dist/capture.js.map +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.js +10 -1
- package/dist/config.js.map +1 -1
- package/dist/discovery.d.ts +9 -0
- package/dist/discovery.js +25 -0
- package/dist/discovery.js.map +1 -1
- package/dist/doctor.js +140 -112
- package/dist/doctor.js.map +1 -1
- package/dist/find.js +2 -1
- package/dist/find.js.map +1 -1
- package/dist/git.d.ts +1 -0
- package/dist/git.js +15 -0
- package/dist/git.js.map +1 -0
- package/dist/go.js +6 -1
- package/dist/go.js.map +1 -1
- package/dist/headline.d.ts +13 -0
- package/dist/headline.js +32 -0
- package/dist/headline.js.map +1 -0
- package/dist/index.d.ts +14 -3
- package/dist/index.js +12 -2
- package/dist/index.js.map +1 -1
- package/dist/init.js +93 -51
- package/dist/init.js.map +1 -1
- package/dist/invariantSnapshot.d.ts +2 -0
- package/dist/invariantSnapshot.js +219 -0
- package/dist/invariantSnapshot.js.map +1 -0
- package/dist/invariantTypes.d.ts +100 -0
- package/dist/invariantTypes.js +4 -0
- package/dist/invariantTypes.js.map +1 -0
- package/dist/invariants.d.ts +13 -0
- package/dist/invariants.js +415 -0
- package/dist/invariants.js.map +1 -0
- package/dist/listMutation.d.ts +4 -0
- package/dist/listMutation.js +37 -0
- package/dist/listMutation.js.map +1 -0
- package/dist/obligations.d.ts +3 -0
- package/dist/obligations.js +84 -0
- package/dist/obligations.js.map +1 -0
- package/dist/persistence.js +7 -4
- package/dist/persistence.js.map +1 -1
- package/dist/save.js +34 -34
- package/dist/save.js.map +1 -1
- package/dist/staleness.d.ts +2 -2
- package/dist/staleness.js +12 -89
- package/dist/staleness.js.map +1 -1
- package/dist/state.d.ts +6 -1
- package/dist/state.js +63 -23
- package/dist/state.js.map +1 -1
- package/dist/stateSchemas.d.ts +16 -0
- package/dist/stateSchemas.js +212 -0
- package/dist/stateSchemas.js.map +1 -0
- package/dist/status.js +1 -1
- package/dist/status.js.map +1 -1
- package/dist/trackedPath.d.ts +3 -0
- package/dist/trackedPath.js +27 -0
- package/dist/trackedPath.js.map +1 -0
- package/dist/types.d.ts +33 -18
- package/dist/workstream.js +3 -8
- package/dist/workstream.js.map +1 -1
- package/dist/workstreamId.d.ts +2 -0
- package/dist/workstreamId.js +67 -0
- package/dist/workstreamId.js.map +1 -0
- package/dist/wrap.js +100 -46
- package/dist/wrap.js.map +1 -1
- package/package.json +12 -2
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
const REQUIREMENT_LABELS = {
|
|
2
|
+
project: "project-state.json",
|
|
3
|
+
focus: "focus-state.json",
|
|
4
|
+
config: "config.yaml",
|
|
5
|
+
pointer: "workstreams/current.txt",
|
|
6
|
+
workstreamDirs: "the workstreams directory listing",
|
|
7
|
+
};
|
|
8
|
+
export function pass() {
|
|
9
|
+
return { status: "pass" };
|
|
10
|
+
}
|
|
11
|
+
export function skipped(reason) {
|
|
12
|
+
return { status: "skipped", reason };
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Collapses a per-scope evaluation into an outcome.
|
|
16
|
+
*
|
|
17
|
+
* Precedence: a real contradiction outranks incompleteness, so violations win
|
|
18
|
+
* and carry the unevaluated scopes along for reporting. With no violations and
|
|
19
|
+
* at least one unevaluated scope the result is "partial", never "pass".
|
|
20
|
+
*/
|
|
21
|
+
export function resolveOutcome(violations, skippedScopes = []) {
|
|
22
|
+
if (violations.length > 0) {
|
|
23
|
+
return { status: "violated", violations, skippedScopes };
|
|
24
|
+
}
|
|
25
|
+
if (skippedScopes.length > 0) {
|
|
26
|
+
return { status: "partial", skippedScopes };
|
|
27
|
+
}
|
|
28
|
+
return pass();
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Unwraps a slot the invariant declared in `requires`. The evaluator guarantees
|
|
32
|
+
* it loaded, so reaching the throw means an invariant read a slot it did not
|
|
33
|
+
* declare.
|
|
34
|
+
*/
|
|
35
|
+
function must(result, what) {
|
|
36
|
+
if (!result.loaded) {
|
|
37
|
+
throw new Error(`Invariant evaluated without its required input: ${what}.`);
|
|
38
|
+
}
|
|
39
|
+
return result.value;
|
|
40
|
+
}
|
|
41
|
+
const focusTargetExists = {
|
|
42
|
+
id: "focus-target-exists",
|
|
43
|
+
description: "focus points to an existing workstream directory",
|
|
44
|
+
requires: ["focus", "workstreamDirs"],
|
|
45
|
+
evaluate(snapshot) {
|
|
46
|
+
const targetId = must(snapshot.focus, "focus").current_workstream_id;
|
|
47
|
+
const present = must(snapshot.workstreamDirs, "workstreamDirs").valid;
|
|
48
|
+
if (present.includes(targetId)) {
|
|
49
|
+
return pass();
|
|
50
|
+
}
|
|
51
|
+
return resolveOutcome([{
|
|
52
|
+
invariantId: "focus-target-exists",
|
|
53
|
+
severity: "error",
|
|
54
|
+
scope: { kind: "focus" },
|
|
55
|
+
message: `Focus points to workstream "${targetId}", which has no directory under .iq-context/workstreams.`,
|
|
56
|
+
}]);
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
const pointerTargetExists = {
|
|
60
|
+
id: "pointer-target-exists",
|
|
61
|
+
description: "the current workstream pointer names an existing workstream directory",
|
|
62
|
+
requires: ["pointer", "workstreamDirs"],
|
|
63
|
+
evaluate(snapshot) {
|
|
64
|
+
const targetId = must(snapshot.pointer, "pointer");
|
|
65
|
+
const present = must(snapshot.workstreamDirs, "workstreamDirs").valid;
|
|
66
|
+
if (targetId === null || present.includes(targetId)) {
|
|
67
|
+
return pass();
|
|
68
|
+
}
|
|
69
|
+
return resolveOutcome([{
|
|
70
|
+
invariantId: "pointer-target-exists",
|
|
71
|
+
severity: "warning",
|
|
72
|
+
scope: { kind: "project" },
|
|
73
|
+
message: `workstreams/current.txt points to "${targetId}", which has no directory. Runtime will fall back to focus state or live-workstream discovery.`,
|
|
74
|
+
}]);
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
const projectListResolves = {
|
|
78
|
+
id: "project-list-resolves",
|
|
79
|
+
description: "every workstream listed in project state has a directory",
|
|
80
|
+
requires: ["project", "workstreamDirs"],
|
|
81
|
+
evaluate(snapshot) {
|
|
82
|
+
const present = must(snapshot.workstreamDirs, "workstreamDirs").valid;
|
|
83
|
+
return resolveOutcome(must(snapshot.project, "project").workstreams
|
|
84
|
+
.filter((id) => !present.includes(id))
|
|
85
|
+
.map((id) => ({
|
|
86
|
+
invariantId: "project-list-resolves",
|
|
87
|
+
severity: "error",
|
|
88
|
+
scope: { kind: "project" },
|
|
89
|
+
message: `project-state.json lists workstream "${id}", which has no directory under .iq-context/workstreams.`,
|
|
90
|
+
})));
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
const noDuplicateWorkstreams = {
|
|
94
|
+
id: "no-duplicate-workstreams",
|
|
95
|
+
description: "project state lists no duplicate workstream ids",
|
|
96
|
+
requires: ["project"],
|
|
97
|
+
evaluate(snapshot) {
|
|
98
|
+
const seen = new Set();
|
|
99
|
+
const duplicates = new Set();
|
|
100
|
+
for (const id of must(snapshot.project, "project").workstreams) {
|
|
101
|
+
if (seen.has(id)) {
|
|
102
|
+
duplicates.add(id);
|
|
103
|
+
}
|
|
104
|
+
seen.add(id);
|
|
105
|
+
}
|
|
106
|
+
return resolveOutcome([...duplicates].map((id) => ({
|
|
107
|
+
invariantId: "no-duplicate-workstreams",
|
|
108
|
+
severity: "error",
|
|
109
|
+
scope: { kind: "project" },
|
|
110
|
+
message: `project-state.json lists workstream "${id}" more than once.`,
|
|
111
|
+
})));
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
const workstreamDirListed = {
|
|
115
|
+
id: "workstream-dir-listed",
|
|
116
|
+
description: "every workstream directory is listed in project state",
|
|
117
|
+
requires: ["project", "workstreamDirs"],
|
|
118
|
+
evaluate(snapshot) {
|
|
119
|
+
const listed = new Set(must(snapshot.project, "project").workstreams);
|
|
120
|
+
return resolveOutcome(must(snapshot.workstreamDirs, "workstreamDirs").valid
|
|
121
|
+
.filter((id) => !listed.has(id))
|
|
122
|
+
.map((id) => ({
|
|
123
|
+
invariantId: "workstream-dir-listed",
|
|
124
|
+
severity: "warning",
|
|
125
|
+
scope: { kind: "workstream", workstreamId: id },
|
|
126
|
+
message: `Workstream directory "${id}" exists but is not listed in project-state.json.`,
|
|
127
|
+
})));
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
const workstreamIdMatchesDir = {
|
|
131
|
+
id: "workstream-id-matches-dir",
|
|
132
|
+
description: "each workstream state file matches its directory name",
|
|
133
|
+
requires: ["workstreamDirs"],
|
|
134
|
+
evaluate(snapshot) {
|
|
135
|
+
const violations = [];
|
|
136
|
+
const skippedScopes = [];
|
|
137
|
+
for (const workstream of snapshot.workstreams) {
|
|
138
|
+
if (!workstream.state.loaded) {
|
|
139
|
+
skippedScopes.push(workstream.id);
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
const persistedId = workstream.state.value.workstream_id;
|
|
143
|
+
if (persistedId !== workstream.id) {
|
|
144
|
+
violations.push({
|
|
145
|
+
invariantId: "workstream-id-matches-dir",
|
|
146
|
+
severity: "error",
|
|
147
|
+
scope: { kind: "workstream", workstreamId: workstream.id },
|
|
148
|
+
message: `Workstream directory "${workstream.id}" contains state.json with workstream_id "${persistedId}".`,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return resolveOutcome(violations, skippedScopes);
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
const configMatchesProject = {
|
|
156
|
+
id: "config-matches-project",
|
|
157
|
+
description: "config defaults and tracked artifacts match project state",
|
|
158
|
+
requires: ["config", "project"],
|
|
159
|
+
evaluate(snapshot) {
|
|
160
|
+
const config = must(snapshot.config, "config");
|
|
161
|
+
const project = must(snapshot.project, "project");
|
|
162
|
+
const violations = [];
|
|
163
|
+
const scalars = [
|
|
164
|
+
["project_id", config.project_id, project.project_id],
|
|
165
|
+
["project_name", config.project_name, project.project_name],
|
|
166
|
+
["default_briefing_mode", config.default_briefing_mode, project.default_briefing_mode],
|
|
167
|
+
];
|
|
168
|
+
for (const [field, configValue, projectValue] of scalars) {
|
|
169
|
+
if (configValue !== projectValue) {
|
|
170
|
+
violations.push({
|
|
171
|
+
invariantId: "config-matches-project",
|
|
172
|
+
severity: "error",
|
|
173
|
+
scope: { kind: "config" },
|
|
174
|
+
message: `${field} mismatch: config.yaml has "${configValue}", project-state.json has "${projectValue}".`,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
// Ordered comparison: nothing in the codebase reorders these lists, and
|
|
179
|
+
// set-normalizing would hide duplicate entries.
|
|
180
|
+
if (JSON.stringify(config.tracked_artifacts) !== JSON.stringify(project.tracked_artifacts)) {
|
|
181
|
+
violations.push({
|
|
182
|
+
invariantId: "config-matches-project",
|
|
183
|
+
severity: "error",
|
|
184
|
+
scope: { kind: "config" },
|
|
185
|
+
message: "tracked_artifacts mismatch between config.yaml and project-state.json.",
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
return resolveOutcome(violations);
|
|
189
|
+
},
|
|
190
|
+
};
|
|
191
|
+
const configDefaultWorkstreamResolves = {
|
|
192
|
+
id: "config-default-workstream-resolves",
|
|
193
|
+
description: "the configured default workstream has a directory",
|
|
194
|
+
requires: ["config", "workstreamDirs"],
|
|
195
|
+
evaluate(snapshot) {
|
|
196
|
+
const defaultWorkstream = must(snapshot.config, "config").default_workstream;
|
|
197
|
+
const present = must(snapshot.workstreamDirs, "workstreamDirs").valid;
|
|
198
|
+
if (present.includes(defaultWorkstream)) {
|
|
199
|
+
return pass();
|
|
200
|
+
}
|
|
201
|
+
return resolveOutcome([{
|
|
202
|
+
invariantId: "config-default-workstream-resolves",
|
|
203
|
+
severity: "warning",
|
|
204
|
+
scope: { kind: "config" },
|
|
205
|
+
message: `config.yaml default_workstream is "${defaultWorkstream}", which has no directory under .iq-context/workstreams.`,
|
|
206
|
+
}]);
|
|
207
|
+
},
|
|
208
|
+
};
|
|
209
|
+
const workstreamCaptureScope = {
|
|
210
|
+
id: "workstream-capture-scope",
|
|
211
|
+
description: "workstream capture entries are scoped to their own workstream",
|
|
212
|
+
requires: ["workstreamDirs"],
|
|
213
|
+
evaluate(snapshot) {
|
|
214
|
+
const violations = [];
|
|
215
|
+
const skippedScopes = [];
|
|
216
|
+
for (const workstream of snapshot.workstreams) {
|
|
217
|
+
let unparseable = 0;
|
|
218
|
+
for (const capture of workstream.captures) {
|
|
219
|
+
if (!capture.loaded) {
|
|
220
|
+
unparseable += 1;
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
const entry = capture.value;
|
|
224
|
+
if (entry.scope !== "workstream" || entry.workstream_id !== workstream.id) {
|
|
225
|
+
violations.push({
|
|
226
|
+
invariantId: "workstream-capture-scope",
|
|
227
|
+
severity: "warning",
|
|
228
|
+
scope: { kind: "workstream", workstreamId: workstream.id },
|
|
229
|
+
message: `Capture ${entry.id} in workstream "${workstream.id}" has scope "${entry.scope}" and workstream_id "${String(entry.workstream_id)}".`,
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
if (unparseable > 0) {
|
|
234
|
+
skippedScopes.push(`${workstream.id} (${unparseable} unreadable capture line(s))`);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return resolveOutcome(violations, skippedScopes);
|
|
238
|
+
},
|
|
239
|
+
};
|
|
240
|
+
const projectCaptureScope = {
|
|
241
|
+
id: "project-capture-scope",
|
|
242
|
+
description: "project capture entries are project-scoped",
|
|
243
|
+
requires: [],
|
|
244
|
+
evaluate(snapshot) {
|
|
245
|
+
const violations = [];
|
|
246
|
+
let unparseable = 0;
|
|
247
|
+
for (const capture of snapshot.projectCaptures) {
|
|
248
|
+
if (!capture.loaded) {
|
|
249
|
+
unparseable += 1;
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
const entry = capture.value;
|
|
253
|
+
if (entry.scope !== "project" || entry.workstream_id !== null) {
|
|
254
|
+
violations.push({
|
|
255
|
+
invariantId: "project-capture-scope",
|
|
256
|
+
severity: "warning",
|
|
257
|
+
scope: { kind: "project" },
|
|
258
|
+
message: `Capture ${entry.id} in the project log has scope "${entry.scope}" and workstream_id "${String(entry.workstream_id)}".`,
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return resolveOutcome(violations, unparseable > 0 ? [`project log (${unparseable} unreadable capture line(s))`] : []);
|
|
263
|
+
},
|
|
264
|
+
};
|
|
265
|
+
const completedAtMatchesLifecycle = {
|
|
266
|
+
id: "completed-at-matches-lifecycle",
|
|
267
|
+
description: "completed_at is set exactly when a workstream is completed",
|
|
268
|
+
requires: ["workstreamDirs"],
|
|
269
|
+
evaluate(snapshot) {
|
|
270
|
+
const violations = [];
|
|
271
|
+
const skippedScopes = [];
|
|
272
|
+
for (const workstream of snapshot.workstreams) {
|
|
273
|
+
if (!workstream.state.loaded) {
|
|
274
|
+
skippedScopes.push(workstream.id);
|
|
275
|
+
continue;
|
|
276
|
+
}
|
|
277
|
+
const state = workstream.state.value;
|
|
278
|
+
const isCompleted = state.lifecycle_status === "completed";
|
|
279
|
+
const hasTimestamp = state.completed_at !== null;
|
|
280
|
+
if (isCompleted !== hasTimestamp) {
|
|
281
|
+
violations.push({
|
|
282
|
+
invariantId: "completed-at-matches-lifecycle",
|
|
283
|
+
severity: "warning",
|
|
284
|
+
scope: { kind: "workstream", workstreamId: workstream.id },
|
|
285
|
+
message: isCompleted
|
|
286
|
+
? `Workstream "${workstream.id}" is completed but has no completed_at timestamp.`
|
|
287
|
+
: `Workstream "${workstream.id}" has completed_at set but lifecycle_status is "${state.lifecycle_status}".`,
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
return resolveOutcome(violations, skippedScopes);
|
|
292
|
+
},
|
|
293
|
+
};
|
|
294
|
+
const completedWorkstreamNoRemainingWork = {
|
|
295
|
+
id: "completed-workstream-no-remaining-work",
|
|
296
|
+
description: "a completed workstream carries no unfinished work",
|
|
297
|
+
requires: ["workstreamDirs"],
|
|
298
|
+
evaluate(snapshot) {
|
|
299
|
+
const violations = [];
|
|
300
|
+
const skippedScopes = [];
|
|
301
|
+
for (const workstream of snapshot.workstreams) {
|
|
302
|
+
if (!workstream.state.loaded) {
|
|
303
|
+
// Lifecycle is unknown, so this workstream may or may not have needed
|
|
304
|
+
// checking. Record it rather than assume it was irrelevant.
|
|
305
|
+
skippedScopes.push(workstream.id);
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
if (workstream.state.value.lifecycle_status !== "completed") {
|
|
309
|
+
// Not completed: nothing to check, so an unreadable resume file here is
|
|
310
|
+
// not a skipped scope. Recording it would strand this invariant in
|
|
311
|
+
// permanent "partial" for any project with one corrupt workstream.
|
|
312
|
+
continue;
|
|
313
|
+
}
|
|
314
|
+
if (workstream.state.value.next_actions.length > 0) {
|
|
315
|
+
violations.push({
|
|
316
|
+
invariantId: "completed-workstream-no-remaining-work",
|
|
317
|
+
severity: "warning",
|
|
318
|
+
scope: { kind: "workstream", workstreamId: workstream.id },
|
|
319
|
+
message: `Completed workstream "${workstream.id}" still lists ${workstream.state.value.next_actions.length} next action(s).`,
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
if (!workstream.resume.loaded) {
|
|
323
|
+
skippedScopes.push(workstream.id);
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
if (workstream.resume.value.remaining_tasks.length > 0) {
|
|
327
|
+
violations.push({
|
|
328
|
+
invariantId: "completed-workstream-no-remaining-work",
|
|
329
|
+
severity: "warning",
|
|
330
|
+
scope: { kind: "workstream", workstreamId: workstream.id },
|
|
331
|
+
message: `Completed workstream "${workstream.id}" still lists remaining resume tasks: ${workstream.resume.value.remaining_tasks.join(", ")}.`,
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
return resolveOutcome(violations, skippedScopes);
|
|
336
|
+
},
|
|
337
|
+
};
|
|
338
|
+
const nextActionsMatchRemainingTasks = {
|
|
339
|
+
id: "next-actions-match-remaining-tasks",
|
|
340
|
+
description: "a live workstream's next actions and resume remaining tasks agree",
|
|
341
|
+
requires: ["workstreamDirs"],
|
|
342
|
+
evaluate(snapshot) {
|
|
343
|
+
const violations = [];
|
|
344
|
+
const skippedScopes = [];
|
|
345
|
+
for (const workstream of snapshot.workstreams) {
|
|
346
|
+
if (!workstream.state.loaded) {
|
|
347
|
+
skippedScopes.push(workstream.id);
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
const state = workstream.state.value;
|
|
351
|
+
if (state.lifecycle_status === "completed" || state.lifecycle_status === "abandoned") {
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
354
|
+
if (!workstream.resume.loaded) {
|
|
355
|
+
skippedScopes.push(workstream.id);
|
|
356
|
+
continue;
|
|
357
|
+
}
|
|
358
|
+
const nextActions = state.next_actions.map((value) => value.trim());
|
|
359
|
+
const remainingTasks = workstream.resume.value.remaining_tasks.map((value) => value.trim());
|
|
360
|
+
if (JSON.stringify(nextActions) === JSON.stringify(remainingTasks)) {
|
|
361
|
+
continue;
|
|
362
|
+
}
|
|
363
|
+
violations.push({
|
|
364
|
+
invariantId: "next-actions-match-remaining-tasks",
|
|
365
|
+
severity: "warning",
|
|
366
|
+
scope: { kind: "workstream", workstreamId: workstream.id },
|
|
367
|
+
message: buildNextActionsRepairMessage(workstream.id, nextActions, remainingTasks.length),
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
return resolveOutcome(violations, skippedScopes);
|
|
371
|
+
},
|
|
372
|
+
};
|
|
373
|
+
function buildNextActionsRepairMessage(workstreamId, nextActions, remainingTaskCount) {
|
|
374
|
+
const lines = [
|
|
375
|
+
`Workstream "${workstreamId}" records ${nextActions.length} remaining actions in one place and ${remainingTaskCount} in another.`,
|
|
376
|
+
];
|
|
377
|
+
if (nextActions.length > 0) {
|
|
378
|
+
lines.push("Repair by restating them:", ` iq-context save --workstream ${workstreamId}${nextActions
|
|
379
|
+
.map((action) => ` --next "${quoteCommandValue(action)}"`)
|
|
380
|
+
.join("")}`, "Or clear both:");
|
|
381
|
+
}
|
|
382
|
+
lines.push(` iq-context save --workstream ${workstreamId} --clear next`);
|
|
383
|
+
return lines.join("\n");
|
|
384
|
+
}
|
|
385
|
+
function quoteCommandValue(value) {
|
|
386
|
+
return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
387
|
+
}
|
|
388
|
+
export const INVARIANTS = [
|
|
389
|
+
focusTargetExists,
|
|
390
|
+
pointerTargetExists,
|
|
391
|
+
projectListResolves,
|
|
392
|
+
noDuplicateWorkstreams,
|
|
393
|
+
workstreamDirListed,
|
|
394
|
+
workstreamIdMatchesDir,
|
|
395
|
+
configMatchesProject,
|
|
396
|
+
configDefaultWorkstreamResolves,
|
|
397
|
+
workstreamCaptureScope,
|
|
398
|
+
projectCaptureScope,
|
|
399
|
+
completedAtMatchesLifecycle,
|
|
400
|
+
completedWorkstreamNoRemainingWork,
|
|
401
|
+
nextActionsMatchRemainingTasks,
|
|
402
|
+
];
|
|
403
|
+
export function evaluateInvariants(snapshot) {
|
|
404
|
+
return INVARIANTS.map((invariant) => {
|
|
405
|
+
const unmet = invariant.requires.filter((requirement) => !snapshot[requirement].loaded);
|
|
406
|
+
if (unmet.length > 0) {
|
|
407
|
+
return {
|
|
408
|
+
invariant,
|
|
409
|
+
outcome: skipped(`${unmet.map((requirement) => REQUIREMENT_LABELS[requirement]).join(" and ")} did not load`),
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
return { invariant, outcome: invariant.evaluate(snapshot) };
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
//# sourceMappingURL=invariants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invariants.js","sourceRoot":"","sources":["../src/invariants.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ListDelta } from "./types.js";
|
|
2
|
+
export declare function replaceList(previous: string[], incoming: string[], clearRequested: boolean, normalize?: (value: string) => string): ListDelta;
|
|
3
|
+
export declare function appendList(previous: string[], incoming: string[], clearRequested: boolean): ListDelta;
|
|
4
|
+
export declare function clearList(previous: string[], clearRequested: boolean): ListDelta;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export function replaceList(previous, incoming, clearRequested, normalize = (value) => value.trim()) {
|
|
2
|
+
const provided = incoming.length > 0;
|
|
3
|
+
const current = clearRequested || provided
|
|
4
|
+
? uniqueValues(incoming, normalize)
|
|
5
|
+
: previous;
|
|
6
|
+
return buildListDelta(previous, current, clearRequested, provided);
|
|
7
|
+
}
|
|
8
|
+
export function appendList(previous, incoming, clearRequested) {
|
|
9
|
+
const provided = incoming.length > 0;
|
|
10
|
+
const base = clearRequested ? [] : previous;
|
|
11
|
+
const current = provided ? uniqueValues([...base, ...incoming]) : base;
|
|
12
|
+
return buildListDelta(previous, current, clearRequested, provided);
|
|
13
|
+
}
|
|
14
|
+
export function clearList(previous, clearRequested) {
|
|
15
|
+
return buildListDelta(previous, clearRequested ? [] : previous, clearRequested, false);
|
|
16
|
+
}
|
|
17
|
+
function buildListDelta(previous, current, clearRequested, provided) {
|
|
18
|
+
const previousSet = new Set(previous);
|
|
19
|
+
const currentSet = new Set(current);
|
|
20
|
+
const added = current.filter((value) => !previousSet.has(value));
|
|
21
|
+
const removed = previous.filter((value) => !currentSet.has(value));
|
|
22
|
+
return {
|
|
23
|
+
previous,
|
|
24
|
+
current,
|
|
25
|
+
added,
|
|
26
|
+
removed,
|
|
27
|
+
reordered: added.length === 0
|
|
28
|
+
&& removed.length === 0
|
|
29
|
+
&& previous.some((value, index) => current[index] !== value),
|
|
30
|
+
clearRequested,
|
|
31
|
+
provided,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function uniqueValues(values, normalize = (value) => value.trim()) {
|
|
35
|
+
return Array.from(new Set(values.map(normalize).filter(Boolean)));
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=listMutation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listMutation.js","sourceRoot":"","sources":["../src/listMutation.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,WAAW,CACzB,QAAkB,EAClB,QAAkB,EAClB,cAAuB,EACvB,YAAuC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE;IAE9D,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;IACrC,MAAM,OAAO,GAAG,cAAc,IAAI,QAAQ;QACxC,CAAC,CAAC,YAAY,CAAC,QAAQ,EAAE,SAAS,CAAC;QACnC,CAAC,CAAC,QAAQ,CAAC;IACb,OAAO,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE,cAAc,EAAE,QAAQ,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,UAAU,CACxB,QAAkB,EAClB,QAAkB,EAClB,cAAuB;IAEvB,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;IACrC,MAAM,IAAI,GAAG,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;IAC5C,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACvE,OAAO,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE,cAAc,EAAE,QAAQ,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,QAAkB,EAAE,cAAuB;IACnE,OAAO,cAAc,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,cAAc,EAAE,KAAK,CAAC,CAAC;AACzF,CAAC;AAED,SAAS,cAAc,CACrB,QAAkB,EAClB,OAAiB,EACjB,cAAuB,EACvB,QAAiB;IAEjB,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;IACtC,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;IACpC,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;IACjE,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;IACnE,OAAO;QACL,QAAQ;QACR,OAAO;QACP,KAAK;QACL,OAAO;QACP,SAAS,EAAE,KAAK,CAAC,MAAM,KAAK,CAAC;eACxB,OAAO,CAAC,MAAM,KAAK,CAAC;eACpB,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC;QAC9D,cAAc;QACd,QAAQ;KACT,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CACnB,MAAgB,EAChB,YAAuC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE;IAE9D,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AACpE,CAAC"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
const CLOSED_STATUSES = new Set(["met", "closed", "retired", "done"]);
|
|
4
|
+
export function parseObligationTable(markdown, sourcePath) {
|
|
5
|
+
const lines = markdown.split(/\r?\n/);
|
|
6
|
+
const headingIndex = lines.findIndex((line) => /^##\s+obligations\s*#*\s*$/i.test(line.trim()));
|
|
7
|
+
if (headingIndex === -1) {
|
|
8
|
+
return [];
|
|
9
|
+
}
|
|
10
|
+
const sectionLines = [];
|
|
11
|
+
for (const line of lines.slice(headingIndex + 1)) {
|
|
12
|
+
if (/^#{1,2}\s+/.test(line.trim())) {
|
|
13
|
+
break;
|
|
14
|
+
}
|
|
15
|
+
sectionLines.push(line);
|
|
16
|
+
}
|
|
17
|
+
const obligations = [];
|
|
18
|
+
for (let index = 0; index < sectionLines.length - 1; index += 1) {
|
|
19
|
+
const headers = parseMarkdownRow(sectionLines[index]);
|
|
20
|
+
const separator = parseMarkdownRow(sectionLines[index + 1]);
|
|
21
|
+
if (!headers
|
|
22
|
+
|| !separator
|
|
23
|
+
|| separator.length !== headers.length
|
|
24
|
+
|| !separator.every((cell) => /^:?-{3,}:?$/.test(cell))) {
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
const columnIndexes = new Map(headers.map((header, columnIndex) => [header.trim().toLowerCase(), columnIndex]));
|
|
28
|
+
if (!columnIndexes.has("obligation")) {
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
for (const line of sectionLines.slice(index + 2)) {
|
|
32
|
+
if (line.trim().length === 0) {
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
const cells = parseMarkdownRow(line);
|
|
36
|
+
if (!cells) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
const obligationCell = getCell(cells, columnIndexes, "obligation");
|
|
40
|
+
const separatorIndex = obligationCell.indexOf(": ");
|
|
41
|
+
if (separatorIndex <= 0 || separatorIndex >= obligationCell.length - 2) {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
const id = obligationCell.slice(0, separatorIndex).trim();
|
|
45
|
+
const description = obligationCell.slice(separatorIndex + 2).trim();
|
|
46
|
+
if (!id || !description) {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
obligations.push({
|
|
50
|
+
id,
|
|
51
|
+
description,
|
|
52
|
+
kind: getCell(cells, columnIndexes, "kind"),
|
|
53
|
+
trigger: getCell(cells, columnIndexes, "trigger"),
|
|
54
|
+
origin: getCell(cells, columnIndexes, "origin"),
|
|
55
|
+
status: getCell(cells, columnIndexes, "status"),
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
return obligations;
|
|
61
|
+
}
|
|
62
|
+
export function loadOpenObligations(projectRoot) {
|
|
63
|
+
const sourcePath = path.join(projectRoot, "docs", "north-star-board", "board-log.md");
|
|
64
|
+
if (!fs.existsSync(sourcePath)) {
|
|
65
|
+
return [];
|
|
66
|
+
}
|
|
67
|
+
return parseObligationTable(fs.readFileSync(sourcePath, "utf8"), sourcePath)
|
|
68
|
+
.filter((obligation) => !CLOSED_STATUSES.has(obligation.status.trim().toLowerCase()));
|
|
69
|
+
}
|
|
70
|
+
function parseMarkdownRow(line) {
|
|
71
|
+
const trimmed = line.trim();
|
|
72
|
+
if (!trimmed.startsWith("|")) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
const row = trimmed.endsWith("|") ? trimmed.slice(1, -1) : trimmed.slice(1);
|
|
76
|
+
return row
|
|
77
|
+
.split(/(?<!\\)\|/)
|
|
78
|
+
.map((cell) => cell.replace(/\\\|/g, "|").trim());
|
|
79
|
+
}
|
|
80
|
+
function getCell(cells, columnIndexes, columnName) {
|
|
81
|
+
const index = columnIndexes.get(columnName);
|
|
82
|
+
return index === undefined ? "" : (cells[index] ?? "").trim();
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=obligations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"obligations.js","sourceRoot":"","sources":["../src/obligations.ts"],"names":[],"mappings":"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"}
|
package/dist/persistence.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
1
2
|
import fs from "node:fs";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
export class WriteConflictError extends Error {
|
|
@@ -15,14 +16,16 @@ export function writeTextFileAtomic(filePath, content) {
|
|
|
15
16
|
}
|
|
16
17
|
const directory = path.dirname(filePath);
|
|
17
18
|
fs.mkdirSync(directory, { recursive: true });
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
// Scratch state stays a sibling file, never a directory: some state files
|
|
20
|
+
// live in directories that are scanned, and an interrupted write must not
|
|
21
|
+
// leave behind an entry that reads as a malformed member of that directory.
|
|
22
|
+
const tempPath = path.join(directory, `.${path.basename(filePath)}-${process.pid}-${randomUUID()}.tmp`);
|
|
20
23
|
try {
|
|
21
|
-
fs.writeFileSync(tempPath, content, "utf8");
|
|
24
|
+
fs.writeFileSync(tempPath, content, { encoding: "utf8", flag: "wx" });
|
|
22
25
|
fs.renameSync(tempPath, filePath);
|
|
23
26
|
}
|
|
24
27
|
finally {
|
|
25
|
-
fs.rmSync(
|
|
28
|
+
fs.rmSync(tempPath, { force: true });
|
|
26
29
|
}
|
|
27
30
|
}
|
|
28
31
|
export function isWriteConflictError(error) {
|
package/dist/persistence.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"persistence.js","sourceRoot":"","sources":["../src/persistence.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAC3C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED,MAAM,UAAU,mBAAmB,CAAC,QAAgB,EAAE,KAAc;IAClE,mBAAmB,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AACvE,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,QAAgB,EAAE,OAAe;IACnE,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;QAC/D,MAAM,IAAI,kBAAkB,CAAC,sDAAsD,QAAQ,EAAE,CAAC,CAAC;IACjG,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACzC,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE7C,
|
|
1
|
+
{"version":3,"file":"persistence.js","sourceRoot":"","sources":["../src/persistence.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAC3C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED,MAAM,UAAU,mBAAmB,CAAC,QAAgB,EAAE,KAAc;IAClE,mBAAmB,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AACvE,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,QAAgB,EAAE,OAAe;IACnE,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;QAC/D,MAAM,IAAI,kBAAkB,CAAC,sDAAsD,QAAQ,EAAE,CAAC,CAAC;IACjG,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACzC,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE7C,0EAA0E;IAC1E,0EAA0E;IAC1E,4EAA4E;IAC5E,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CACxB,SAAS,EACT,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,GAAG,IAAI,UAAU,EAAE,MAAM,CACjE,CAAC;IAEF,IAAI,CAAC;QACH,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACtE,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACpC,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACvC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAc;IACjD,OAAO,KAAK,YAAY,kBAAkB;WACrC,CAAC,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,oBAAoB,CAAC,CAAC;AACvE,CAAC"}
|