@tacuchi/agent-workflow-cli 20.21.0 → 20.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -6
- package/dist/adapters/git-cli.js +42 -0
- package/dist/adapters/git-cli.js.map +1 -1
- package/dist/application/artifacts-service.js +5 -5
- package/dist/application/artifacts-service.js.map +1 -1
- package/dist/application/checkpoint-service.js +60 -55
- package/dist/application/checkpoint-service.js.map +1 -1
- package/dist/application/checkpoint-write-service.js +61 -66
- package/dist/application/checkpoint-write-service.js.map +1 -1
- package/dist/application/decisiones-service.js +5 -5
- package/dist/application/decisiones-service.js.map +1 -1
- package/dist/application/export-service.js +250 -0
- package/dist/application/export-service.js.map +1 -0
- package/dist/application/fix-git-service.js +244 -0
- package/dist/application/fix-git-service.js.map +1 -0
- package/dist/application/history-update-service.js +35 -24
- package/dist/application/history-update-service.js.map +1 -1
- package/dist/application/lifecycle-target.js +39 -0
- package/dist/application/lifecycle-target.js.map +1 -0
- package/dist/application/markdown.js +61 -16
- package/dist/application/markdown.js.map +1 -1
- package/dist/application/parsers/phases.js +38 -45
- package/dist/application/parsers/phases.js.map +1 -1
- package/dist/application/parsers/plan-status.js +75 -0
- package/dist/application/parsers/plan-status.js.map +1 -0
- package/dist/application/parsers/spec-relation.js +80 -0
- package/dist/application/parsers/spec-relation.js.map +1 -0
- package/dist/application/paths-service.js +8 -0
- package/dist/application/paths-service.js.map +1 -1
- package/dist/application/persist-service.js +285 -0
- package/dist/application/persist-service.js.map +1 -0
- package/dist/application/release-data/artifacts.js +17 -21
- package/dist/application/release-data/artifacts.js.map +1 -1
- package/dist/application/resume-service.js +184 -0
- package/dist/application/resume-service.js.map +1 -0
- package/dist/application/semantic-operation/protocol.js +247 -0
- package/dist/application/semantic-operation/protocol.js.map +1 -0
- package/dist/application/semantic-operation/publish.js +80 -0
- package/dist/application/semantic-operation/publish.js.map +1 -0
- package/dist/application/session-binding-service.js +125 -0
- package/dist/application/session-binding-service.js.map +1 -0
- package/dist/application/session-close-service.js +60 -39
- package/dist/application/session-close-service.js.map +1 -1
- package/dist/application/session-create-service.js +45 -19
- package/dist/application/session-create-service.js.map +1 -1
- package/dist/application/session-resolver.js +180 -44
- package/dist/application/session-resolver.js.map +1 -1
- package/dist/application/session-resume-service.js +39 -9
- package/dist/application/session-resume-service.js.map +1 -1
- package/dist/application/sessions-service.js +0 -2
- package/dist/application/sessions-service.js.map +1 -1
- package/dist/application/status-service.js +24 -352
- package/dist/application/status-service.js.map +1 -1
- package/dist/application/tasks-service.js +5 -5
- package/dist/application/tasks-service.js.map +1 -1
- package/dist/application/workline-index-service.js +510 -0
- package/dist/application/workline-index-service.js.map +1 -0
- package/dist/cli/commands/checkpoint-read.js +10 -6
- package/dist/cli/commands/checkpoint-read.js.map +1 -1
- package/dist/cli/commands/checkpoint-write.js +38 -11
- package/dist/cli/commands/checkpoint-write.js.map +1 -1
- package/dist/cli/commands/export.js +117 -0
- package/dist/cli/commands/export.js.map +1 -0
- package/dist/cli/commands/fix-git.js +109 -0
- package/dist/cli/commands/fix-git.js.map +1 -0
- package/dist/cli/commands/generate-launch.js +35 -3
- package/dist/cli/commands/generate-launch.js.map +1 -1
- package/dist/cli/commands/history-update.js +1 -1
- package/dist/cli/commands/history-update.js.map +1 -1
- package/dist/cli/commands/index.js +11 -0
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/persist.js +67 -0
- package/dist/cli/commands/persist.js.map +1 -0
- package/dist/cli/commands/resume-summary.js +14 -3
- package/dist/cli/commands/resume-summary.js.map +1 -1
- package/dist/cli/commands/resume.js +73 -0
- package/dist/cli/commands/resume.js.map +1 -0
- package/dist/cli/commands/session-artifacts.js +12 -11
- package/dist/cli/commands/session-artifacts.js.map +1 -1
- package/dist/cli/commands/session-close.js +8 -7
- package/dist/cli/commands/session-close.js.map +1 -1
- package/dist/cli/commands/session-create.js +5 -1
- package/dist/cli/commands/session-create.js.map +1 -1
- package/dist/cli/commands/session-resume.js +16 -10
- package/dist/cli/commands/session-resume.js.map +1 -1
- package/dist/cli/commands/status.js +66 -2
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/commands/workspace-init.js +21 -2
- package/dist/cli/commands/workspace-init.js.map +1 -1
- package/dist/cli/context-id.js +133 -0
- package/dist/cli/context-id.js.map +1 -0
- package/dist/cli/help-groups.js +16 -1
- package/dist/cli/help-groups.js.map +1 -1
- package/dist/cli/main.js +44 -16
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/output-mode.js +41 -0
- package/dist/cli/output-mode.js.map +1 -0
- package/dist/cli/parser.js +6 -0
- package/dist/cli/parser.js.map +1 -1
- package/dist/cli/registry.js.map +1 -1
- package/dist/cli/render.js +53 -0
- package/dist/cli/render.js.map +1 -1
- package/package.json +1 -1
- package/skills/w/SKILL.md +3 -1
- package/skills/w/commands/export-diagrams.md +19 -10
- package/skills/w/commands/export-manuals.md +20 -10
- package/skills/w/commands/export-reports.md +20 -11
- package/skills/w/commands/export-scripts.md +20 -10
- package/skills/w/commands/fix-git.md +31 -12
- package/skills/w/commands/generate-launch.md +1 -1
- package/skills/w/commands/persist.md +33 -68
- package/skills/w/commands/plan-new.md +1 -1
- package/skills/w/commands/resume.md +25 -41
- package/skills/w/commands/spec-refine.md +12 -0
- package/skills/w/commands/status.md +12 -40
- package/skills/w/commands/workspace-init.md +3 -3
- package/skills/w/hooks/README.md +21 -2
- package/skills/w/hooks/hooks.template.json +2 -2
- package/skills/w/loops/README.md +5 -3
- package/skills/w/loops/plan-exec-loop/LOOP.md +10 -5
- package/skills/w/loops/plan-new-loop/LOOP.md +17 -8
- package/skills/w/loops/plan-refine-loop/LOOP.md +3 -1
- package/skills/w/loops/spec-refine-loop/LOOP.md +20 -7
- package/skills/w/roles/git/ROLE.md +7 -8
|
@@ -0,0 +1,510 @@
|
|
|
1
|
+
import { basename, join, relative } from "node:path";
|
|
2
|
+
import { localDateIso } from "./dates.js";
|
|
3
|
+
import { humanizeRelativeEs } from "./humanize-es.js";
|
|
4
|
+
import { firstNonEmptyLine, parseMdSection, parseMdSectionBilingual } from "./markdown.js";
|
|
5
|
+
import { parsePhases } from "./parsers/phases.js";
|
|
6
|
+
import { parsePlanStatus } from "./parsers/plan-status.js";
|
|
7
|
+
import { parseProjectBlock } from "./parsers/project-block.js";
|
|
8
|
+
import { parseSpecRelation } from "./parsers/spec-relation.js";
|
|
9
|
+
import { parseTasks } from "./parsers/tasks.js";
|
|
10
|
+
import { findArtifact } from "./session-artifacts.js";
|
|
11
|
+
import { SessionsService } from "./sessions-service.js";
|
|
12
|
+
/**
|
|
13
|
+
* The one reading of the workspace's Workline documents.
|
|
14
|
+
*
|
|
15
|
+
* `status` and `resume` used to answer the same questions from two places —
|
|
16
|
+
* one in the CLI, one re-derived by an agent reading JSON — and drifted. This
|
|
17
|
+
* module owns specs, plans, sessions, the spec→plan relation and the pending
|
|
18
|
+
* pipeline; both commands project it and neither decides anything on its own.
|
|
19
|
+
*
|
|
20
|
+
* Read-only by construction: nothing here opens a file for writing.
|
|
21
|
+
*/
|
|
22
|
+
const SPEC_STATUSES = ["draft", "refining", "ready-for-plan"];
|
|
23
|
+
/**
|
|
24
|
+
* Never throws on a reachable cwd: an uninitialized workspace returns
|
|
25
|
+
* `initialized:false` with empty collections, and a single unreadable file is
|
|
26
|
+
* skipped rather than tanking the whole read.
|
|
27
|
+
*/
|
|
28
|
+
export async function buildWorklineIndex(fs, env, paths, input = {}) {
|
|
29
|
+
const now = input.now ?? new Date();
|
|
30
|
+
const cwd = paths.workspaceDir();
|
|
31
|
+
const workspace = await readWorkspace(fs, paths, cwd);
|
|
32
|
+
const specs = await readSpecs(fs, cwd, now);
|
|
33
|
+
const plans = await readPlans(fs, cwd, specs, now);
|
|
34
|
+
const sessions = await readSessions(fs, env, paths, now);
|
|
35
|
+
const discarded = await readDiscarded(fs, sessions, cwd, now);
|
|
36
|
+
return {
|
|
37
|
+
workspace,
|
|
38
|
+
specs,
|
|
39
|
+
plans,
|
|
40
|
+
sessions,
|
|
41
|
+
discarded,
|
|
42
|
+
pipeline: derivePipeline(specs, plans, sessions),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
// ── pipeline ─────────────────────────────────────────────────────────────────
|
|
46
|
+
function derivePipeline(specs, plans, sessions) {
|
|
47
|
+
const plannedSpecs = new Set(plans.map((p) => (p.spec.status === "resolved" ? p.spec.number : null)).filter(isString));
|
|
48
|
+
const items = [];
|
|
49
|
+
for (const spec of specs) {
|
|
50
|
+
if (spec.status !== "ready-for-plan") {
|
|
51
|
+
items.push(specItem(spec, 1, "spec-unrefined", "/w:spec-refine"));
|
|
52
|
+
}
|
|
53
|
+
else if (!plannedSpecs.has(spec.number)) {
|
|
54
|
+
items.push(specItem(spec, 2, "spec-unplanned", "/w:plan-new"));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
for (const plan of plans) {
|
|
58
|
+
if (plan.plan_state === "done")
|
|
59
|
+
continue;
|
|
60
|
+
items.push({
|
|
61
|
+
kind: "plan-open",
|
|
62
|
+
priority: 3,
|
|
63
|
+
file: plan.file,
|
|
64
|
+
number: plan.number,
|
|
65
|
+
slug: plan.slug,
|
|
66
|
+
summary: planSummary(plan),
|
|
67
|
+
command: `/w:plan-exec ${plan.file}`,
|
|
68
|
+
started: plan.tasks_done > 0 || plan.phases_validated > 0,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
for (const session of sessions) {
|
|
72
|
+
if (session.state !== "active" || !session.has_checkpoint)
|
|
73
|
+
continue;
|
|
74
|
+
if (session.linked_doc !== null)
|
|
75
|
+
continue;
|
|
76
|
+
items.push({
|
|
77
|
+
kind: "checkpoint-orphan",
|
|
78
|
+
priority: 4,
|
|
79
|
+
file: session.folder,
|
|
80
|
+
number: session.code,
|
|
81
|
+
slug: session.folder,
|
|
82
|
+
summary: session.summary,
|
|
83
|
+
command: `aw session-resume --code ${session.folder} --reopen`,
|
|
84
|
+
started: true,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
return items.sort(comparePipeline);
|
|
88
|
+
}
|
|
89
|
+
function specItem(spec, priority, kind, command) {
|
|
90
|
+
return {
|
|
91
|
+
kind,
|
|
92
|
+
priority,
|
|
93
|
+
file: spec.file,
|
|
94
|
+
number: spec.number,
|
|
95
|
+
slug: spec.slug,
|
|
96
|
+
summary: `spec ${spec.number} — ${spec.status}`,
|
|
97
|
+
command: `${command} ${spec.file}`,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function planSummary(plan) {
|
|
101
|
+
const phases = plan.phases_total > 0 ? `, fases ${plan.phases_validated}/${plan.phases_total}` : "";
|
|
102
|
+
const blocked = plan.phases_blocked > 0 ? `, ${plan.phases_blocked} bloqueada(s)` : "";
|
|
103
|
+
return `plan ${plan.number} — ${plan.progress_pct}%${phases}${blocked}`;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Priority first, then started-before-untouched, then document number. The last
|
|
107
|
+
* key is presentation only — two items that reach it are still a tie for the
|
|
108
|
+
* caller, which is why `resume` compares priority and `started`, never order.
|
|
109
|
+
*/
|
|
110
|
+
function comparePipeline(a, b) {
|
|
111
|
+
if (a.priority !== b.priority)
|
|
112
|
+
return a.priority - b.priority;
|
|
113
|
+
const started = Number(b.started ?? false) - Number(a.started ?? false);
|
|
114
|
+
if (started !== 0)
|
|
115
|
+
return started;
|
|
116
|
+
return (a.number ?? "").localeCompare(b.number ?? "");
|
|
117
|
+
}
|
|
118
|
+
function isString(value) {
|
|
119
|
+
return value !== null;
|
|
120
|
+
}
|
|
121
|
+
// ── workspace ────────────────────────────────────────────────────────────────
|
|
122
|
+
async function readWorkspace(fs, paths, cwd) {
|
|
123
|
+
let name = basename(cwd);
|
|
124
|
+
for (const file of [join(cwd, "CLAUDE.md"), join(cwd, "AGENTS.md")]) {
|
|
125
|
+
try {
|
|
126
|
+
if (!(await fs.exists(file)))
|
|
127
|
+
continue;
|
|
128
|
+
const block = parseProjectBlock(await fs.readText(file), paths.blockMarkers());
|
|
129
|
+
if (block?.proyecto) {
|
|
130
|
+
name = block.proyecto;
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
// ignore; fall back to basename
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return { name, path: cwd, initialized: await safeExists(fs, paths.cwdRoot()) };
|
|
139
|
+
}
|
|
140
|
+
// ── specs ────────────────────────────────────────────────────────────────────
|
|
141
|
+
const SPEC_RE = /^(\d{3})-spec(?:-(.+))?\.md$/i;
|
|
142
|
+
async function readSpecs(fs, cwd, now) {
|
|
143
|
+
const files = dedupeRefined(await listMarkdown(fs, join(cwd, "docs", "specs"), SPEC_RE));
|
|
144
|
+
const out = [];
|
|
145
|
+
for (const f of files) {
|
|
146
|
+
try {
|
|
147
|
+
const text = await fs.readText(f.path);
|
|
148
|
+
const status = resolveSpecStatus(text);
|
|
149
|
+
const ts = await resolveTimestamp(fs, f.path, undefined, now);
|
|
150
|
+
out.push({
|
|
151
|
+
file: relFromCwd(f.path, cwd),
|
|
152
|
+
number: f.number,
|
|
153
|
+
slug: f.slug,
|
|
154
|
+
status,
|
|
155
|
+
refined: status === "ready-for-plan",
|
|
156
|
+
open_questions: countOpenQuestions(text),
|
|
157
|
+
date: ts.date,
|
|
158
|
+
relative: ts.relative,
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
// skip unreadable spec
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return sortByNumber(out);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* The only two trace sections that marked a spec as worked-through before the
|
|
169
|
+
* frontmatter `status` existed. `## Decisions` is NOT one of them: it belongs
|
|
170
|
+
* to the current spec schema and proves nothing about the refine gate.
|
|
171
|
+
*
|
|
172
|
+
* Exported so the doctrine guard can check this list against the marks the
|
|
173
|
+
* bundle documents — the two drifted apart once, and a spec nobody refined
|
|
174
|
+
* reached PLAN because of it.
|
|
175
|
+
*/
|
|
176
|
+
export const LEGACY_READY_MARKS = ["Refinement decisions", "Q&A traceability"];
|
|
177
|
+
/**
|
|
178
|
+
* Spec maturity. A declared frontmatter governs alone: an empty, unknown or
|
|
179
|
+
* unterminated declaration reads `draft` — never a legacy inference, which
|
|
180
|
+
* would send work to PLAN on a gate `spec-refine` never ran. Legacy
|
|
181
|
+
* compatibility runs only on a spec that carries no frontmatter at all.
|
|
182
|
+
*/
|
|
183
|
+
function resolveSpecStatus(text) {
|
|
184
|
+
const frontmatter = parseSpecFrontmatter(text);
|
|
185
|
+
if (frontmatter.kind === "malformed")
|
|
186
|
+
return "draft";
|
|
187
|
+
if (frontmatter.kind === "present") {
|
|
188
|
+
const declared = (frontmatter.status ?? "").toLowerCase();
|
|
189
|
+
return isSpecStatus(declared) ? declared : "draft";
|
|
190
|
+
}
|
|
191
|
+
return hasLegacyReadyMark(text) ? "ready-for-plan" : "draft";
|
|
192
|
+
}
|
|
193
|
+
function hasLegacyReadyMark(text) {
|
|
194
|
+
return LEGACY_READY_MARKS.some((h) => parseMdSectionLoose(text, h) !== undefined);
|
|
195
|
+
}
|
|
196
|
+
function isSpecStatus(value) {
|
|
197
|
+
return SPEC_STATUSES.includes(value);
|
|
198
|
+
}
|
|
199
|
+
const FRONTMATTER_FENCE = "---";
|
|
200
|
+
const FRONTMATTER_ENTRY = /^([A-Za-z0-9_-]+):\s*(.*)$/;
|
|
201
|
+
/**
|
|
202
|
+
* Classify the `---` block at the top of the file and read its `status` scalar.
|
|
203
|
+
* Specs only carry flat scalars there, so this stays a few lines instead of
|
|
204
|
+
* pulling a YAML dependency into the CLI.
|
|
205
|
+
*/
|
|
206
|
+
function parseSpecFrontmatter(text) {
|
|
207
|
+
const lines = text.split(/\r?\n/);
|
|
208
|
+
if ((lines[0] ?? "").trim() !== FRONTMATTER_FENCE)
|
|
209
|
+
return { kind: "absent" };
|
|
210
|
+
const end = lines.findIndex((l, i) => i > 0 && l.trim() === FRONTMATTER_FENCE);
|
|
211
|
+
if (end === -1)
|
|
212
|
+
return { kind: "malformed" };
|
|
213
|
+
return { kind: "present", status: readScalar(lines.slice(1, end), "status") };
|
|
214
|
+
}
|
|
215
|
+
function readScalar(lines, key) {
|
|
216
|
+
for (const line of lines) {
|
|
217
|
+
const m = FRONTMATTER_ENTRY.exec(line);
|
|
218
|
+
if (m?.[1] !== key)
|
|
219
|
+
continue;
|
|
220
|
+
const value = (m[2] ?? "").trim().replace(/^["']|["']$/g, "");
|
|
221
|
+
return value.length > 0 ? value : undefined;
|
|
222
|
+
}
|
|
223
|
+
return undefined;
|
|
224
|
+
}
|
|
225
|
+
// ── plans ────────────────────────────────────────────────────────────────────
|
|
226
|
+
const PLAN_RE = /^(\d{3})-plan(?:-(.+))?\.md$/i;
|
|
227
|
+
async function readPlans(fs, cwd, specs, now) {
|
|
228
|
+
const files = await listMarkdown(fs, join(cwd, "docs", "plans"), PLAN_RE);
|
|
229
|
+
const byNumber = new Map(specs.map((s) => [s.number, s]));
|
|
230
|
+
const out = [];
|
|
231
|
+
for (const f of files) {
|
|
232
|
+
try {
|
|
233
|
+
const text = await fs.readText(f.path);
|
|
234
|
+
const t = parseTasks(text);
|
|
235
|
+
const p = parsePhases(text);
|
|
236
|
+
const planState = derivePlanState(parsePlanStatus(text).declared, t, p);
|
|
237
|
+
const ts = await resolveTimestamp(fs, f.path, undefined, now);
|
|
238
|
+
out.push({
|
|
239
|
+
file: relFromCwd(f.path, cwd),
|
|
240
|
+
number: f.number,
|
|
241
|
+
slug: f.slug,
|
|
242
|
+
tasks_total: t.total,
|
|
243
|
+
tasks_done: t.closed,
|
|
244
|
+
progress_pct: t.progress_pct,
|
|
245
|
+
phases_total: p.total,
|
|
246
|
+
phases_validated: p.validated,
|
|
247
|
+
plan_state: planState,
|
|
248
|
+
phases_blocked: p.blocked,
|
|
249
|
+
blocked_phases: p.items
|
|
250
|
+
.filter((phase) => phase.state === "bloqueada")
|
|
251
|
+
.map((phase) => ({ number: phase.n, name: phase.name, blocker: phase.blocker })),
|
|
252
|
+
final_validation_pending: planState === "open" && p.total > 0 && p.validated === p.total && t.closed === t.total,
|
|
253
|
+
spec: resolveSpecRelation(text, byNumber),
|
|
254
|
+
date: ts.date,
|
|
255
|
+
relative: ts.relative,
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
catch {
|
|
259
|
+
// skip unreadable plan
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return sortByNumber(out);
|
|
263
|
+
}
|
|
264
|
+
function resolveSpecRelation(text, specs) {
|
|
265
|
+
const parsed = parseSpecRelation(text);
|
|
266
|
+
if (parsed.status === "absent")
|
|
267
|
+
return { status: "unknown", reason: "no-evidence" };
|
|
268
|
+
if (parsed.status === "ambiguous") {
|
|
269
|
+
return { status: "ambiguous", numbers: parsed.numbers, evidence: parsed.evidence };
|
|
270
|
+
}
|
|
271
|
+
const spec = specs.get(parsed.number);
|
|
272
|
+
// The plan names a spec that is not in the workspace: evidence exists but
|
|
273
|
+
// proves nothing here, and inventing a match by slug is exactly the guess
|
|
274
|
+
// this resolution exists to remove.
|
|
275
|
+
if (spec === undefined)
|
|
276
|
+
return { status: "unknown", reason: "spec-not-found" };
|
|
277
|
+
return {
|
|
278
|
+
status: "resolved",
|
|
279
|
+
number: parsed.number,
|
|
280
|
+
file: spec.file,
|
|
281
|
+
evidence: parsed.evidence,
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* The three axes reconciled into one closure state. The rules, in order:
|
|
286
|
+
*
|
|
287
|
+
* - a plan that declares nothing, or declares `open`, IS open — including the
|
|
288
|
+
* case where every box is ticked and every phase is validated: that plan is
|
|
289
|
+
* waiting on its final validation, not finished (`final_validation_pending`);
|
|
290
|
+
* - a plan that declares `done` is `done` only when the counters agree — every
|
|
291
|
+
* task closed and, under the phase contract, every phase validated;
|
|
292
|
+
* - any other combination is `inconsistent`: the document says one thing and
|
|
293
|
+
* shows another, and nothing but a human repairs that.
|
|
294
|
+
*
|
|
295
|
+
* A plan with no phase marks predates the contract (`phases_total: 0`) and is
|
|
296
|
+
* judged by its checkboxes alone — it never acquires fictitious phases, and
|
|
297
|
+
* `done` on such a plan stays legitimate when its boxes are all ticked.
|
|
298
|
+
*/
|
|
299
|
+
function derivePlanState(declared, tasks, phases) {
|
|
300
|
+
if (declared === "unknown")
|
|
301
|
+
return "inconsistent";
|
|
302
|
+
if (declared !== "done")
|
|
303
|
+
return "open";
|
|
304
|
+
if (tasks.closed !== tasks.total)
|
|
305
|
+
return "inconsistent";
|
|
306
|
+
// Legacy contract (`legacy-tasks`): no phase marks, so the checkboxes decide.
|
|
307
|
+
if (phases.total === 0)
|
|
308
|
+
return "done";
|
|
309
|
+
return phases.validated === phases.total ? "done" : "inconsistent";
|
|
310
|
+
}
|
|
311
|
+
// ── sessions ─────────────────────────────────────────────────────────────────
|
|
312
|
+
const LINKED_DOC_RE = /docs\/(?:specs|plans)\/\d{3}-(?:spec|plan)[^\s`)"']*\.md/;
|
|
313
|
+
async function readSessions(fs, env, paths, now) {
|
|
314
|
+
let list;
|
|
315
|
+
try {
|
|
316
|
+
list = await new SessionsService(fs, env, paths).list({ state: "all", verbose: true });
|
|
317
|
+
}
|
|
318
|
+
catch {
|
|
319
|
+
return [];
|
|
320
|
+
}
|
|
321
|
+
const out = [];
|
|
322
|
+
for (const s of list.sessions) {
|
|
323
|
+
const primary = (await findArtifact(s.path, "session", fs)) ?? s.path;
|
|
324
|
+
const ts = await resolveTimestamp(fs, primary, s.date, now);
|
|
325
|
+
const checkpoint = await findArtifact(s.path, "checkpoint", fs);
|
|
326
|
+
out.push({
|
|
327
|
+
code: s.code,
|
|
328
|
+
folder: s.folder,
|
|
329
|
+
path: s.path,
|
|
330
|
+
type: s.type ?? null,
|
|
331
|
+
summary: s.summary ?? s.folder,
|
|
332
|
+
state: s.state === "closed" ? "closed" : "active",
|
|
333
|
+
has_checkpoint: checkpoint !== null && checkpoint !== undefined,
|
|
334
|
+
linked_doc: await readLinkedDoc(fs, primary),
|
|
335
|
+
date: ts.date,
|
|
336
|
+
relative: ts.relative,
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
return out;
|
|
340
|
+
}
|
|
341
|
+
/** The spec/plan a session's `## Origin` points at — `null` when it points at none. */
|
|
342
|
+
async function readLinkedDoc(fs, sessionFile) {
|
|
343
|
+
try {
|
|
344
|
+
const origin = parseMdSectionBilingual(await fs.readText(sessionFile), "Origin");
|
|
345
|
+
return origin === undefined ? null : (LINKED_DOC_RE.exec(origin)?.[0] ?? null);
|
|
346
|
+
}
|
|
347
|
+
catch {
|
|
348
|
+
return null;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
// ── discarded ────────────────────────────────────────────────────────────────
|
|
352
|
+
async function readDiscarded(fs, sessions, cwd, now) {
|
|
353
|
+
const out = [];
|
|
354
|
+
for (const s of sessions) {
|
|
355
|
+
await collectDiscarded(fs, s, "backlog", "Deferred", "deferred", cwd, now, out);
|
|
356
|
+
await collectDiscarded(fs, s, "checkpoint", "Excluded", "excluded", cwd, now, out);
|
|
357
|
+
}
|
|
358
|
+
return out;
|
|
359
|
+
}
|
|
360
|
+
async function collectDiscarded(fs, session, artifact, heading, kind, cwd, now, out) {
|
|
361
|
+
try {
|
|
362
|
+
const path = await findArtifact(session.path, artifact, fs);
|
|
363
|
+
if (!path)
|
|
364
|
+
return;
|
|
365
|
+
const items = listItems(parseMdSectionLoose(await fs.readText(path), heading));
|
|
366
|
+
if (items.length === 0)
|
|
367
|
+
return;
|
|
368
|
+
const ts = await resolveTimestamp(fs, path, undefined, now);
|
|
369
|
+
for (const text of items) {
|
|
370
|
+
out.push({
|
|
371
|
+
source: session.code ?? session.folder,
|
|
372
|
+
source_path: relFromCwd(session.path, cwd),
|
|
373
|
+
kind,
|
|
374
|
+
text,
|
|
375
|
+
date: ts.date,
|
|
376
|
+
relative: ts.relative,
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
catch {
|
|
381
|
+
// skip unreadable artifact
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
async function listMarkdown(fs, dir, re) {
|
|
385
|
+
if (!(await safeExists(fs, dir)))
|
|
386
|
+
return [];
|
|
387
|
+
let entries;
|
|
388
|
+
try {
|
|
389
|
+
entries = await fs.list(dir);
|
|
390
|
+
}
|
|
391
|
+
catch {
|
|
392
|
+
return [];
|
|
393
|
+
}
|
|
394
|
+
const out = [];
|
|
395
|
+
for (const e of entries) {
|
|
396
|
+
if (e.type !== "file")
|
|
397
|
+
continue;
|
|
398
|
+
const m = re.exec(e.name);
|
|
399
|
+
if (!m?.[1])
|
|
400
|
+
continue;
|
|
401
|
+
out.push({ path: e.path, number: m[1], slug: m[2] ?? "" });
|
|
402
|
+
}
|
|
403
|
+
return out;
|
|
404
|
+
}
|
|
405
|
+
/** Drop legacy `NNN-spec-refined.md` when another file shares its number. */
|
|
406
|
+
function dedupeRefined(files) {
|
|
407
|
+
const byNumber = new Map();
|
|
408
|
+
for (const f of files) {
|
|
409
|
+
const group = byNumber.get(f.number) ?? [];
|
|
410
|
+
group.push(f);
|
|
411
|
+
byNumber.set(f.number, group);
|
|
412
|
+
}
|
|
413
|
+
const out = [];
|
|
414
|
+
for (const group of byNumber.values()) {
|
|
415
|
+
const isRefined = (f) => /(^|-)refined$/i.test(f.slug);
|
|
416
|
+
const nonRefined = group.filter((f) => !isRefined(f));
|
|
417
|
+
const chosen = nonRefined.length > 0 ? nonRefined : group;
|
|
418
|
+
chosen.sort((a, b) => a.path.localeCompare(b.path));
|
|
419
|
+
const first = chosen[0];
|
|
420
|
+
if (first)
|
|
421
|
+
out.push(first);
|
|
422
|
+
}
|
|
423
|
+
return out;
|
|
424
|
+
}
|
|
425
|
+
function sortByNumber(items) {
|
|
426
|
+
return items.sort((a, b) => a.number.localeCompare(b.number) || a.file.localeCompare(b.file));
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* Best-available timestamp for `relative`/`date`: full-precision fs mtime if the
|
|
430
|
+
* path stats, else a date-only fallback projected to local noon, else `now`.
|
|
431
|
+
*/
|
|
432
|
+
async function resolveTimestamp(fs, path, fallbackDateOnly, now) {
|
|
433
|
+
let mtime = null;
|
|
434
|
+
try {
|
|
435
|
+
mtime = (await fs.stat(path)).mtime;
|
|
436
|
+
}
|
|
437
|
+
catch {
|
|
438
|
+
mtime = null;
|
|
439
|
+
}
|
|
440
|
+
const when = mtime ?? dateOnlyToNoon(fallbackDateOnly) ?? now;
|
|
441
|
+
return { date: localDateIso(when), relative: humanizeRelativeEs(when, now) };
|
|
442
|
+
}
|
|
443
|
+
function dateOnlyToNoon(dateStr) {
|
|
444
|
+
if (!dateStr)
|
|
445
|
+
return null;
|
|
446
|
+
const m = /^(\d{4})-(\d{2})-(\d{2})/.exec(dateStr);
|
|
447
|
+
if (!m)
|
|
448
|
+
return null;
|
|
449
|
+
return new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3]), 12, 0, 0);
|
|
450
|
+
}
|
|
451
|
+
async function safeExists(fs, path) {
|
|
452
|
+
try {
|
|
453
|
+
return await fs.exists(path);
|
|
454
|
+
}
|
|
455
|
+
catch {
|
|
456
|
+
return false;
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
function relFromCwd(path, cwd) {
|
|
460
|
+
// path.relative handles the win32 case a raw string-prefix strip missed: join()
|
|
461
|
+
// yields backslash paths while the old prefix appended a forward slash, so the
|
|
462
|
+
// strip never matched and status showed absolute paths. Normalize to forward
|
|
463
|
+
// slashes so the displayed path reads the same on every OS.
|
|
464
|
+
return relative(cwd, path).split("\\").join("/");
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* Like `parseMdSection` but tolerant of the template heading annotations
|
|
468
|
+
* (`## Excluded (list):`, `## Deferred (text):`) — ignores a trailing
|
|
469
|
+
* `(...)` / `:`; needed for legacy artifacts that still carry the suffix.
|
|
470
|
+
*/
|
|
471
|
+
const parseMdSectionLoose = (text, heading) => parseMdSection(text, heading, normalizeHeading);
|
|
472
|
+
function normalizeHeading(raw) {
|
|
473
|
+
return raw
|
|
474
|
+
.trim()
|
|
475
|
+
.toLowerCase()
|
|
476
|
+
.replace(/\s*\([^)]*\)\s*:?\s*$/, "")
|
|
477
|
+
.replace(/:\s*$/, "")
|
|
478
|
+
.trim();
|
|
479
|
+
}
|
|
480
|
+
/** List-item lines of a section, dropping the `List of …` template placeholder. */
|
|
481
|
+
function listItems(section) {
|
|
482
|
+
if (!section)
|
|
483
|
+
return [];
|
|
484
|
+
const out = [];
|
|
485
|
+
for (const raw of section.split("\n")) {
|
|
486
|
+
const m = /^\s*[-*]\s+(.+?)\s*$/.exec(raw);
|
|
487
|
+
if (!m?.[1])
|
|
488
|
+
continue;
|
|
489
|
+
const text = m[1].trim();
|
|
490
|
+
if (text.length === 0)
|
|
491
|
+
continue;
|
|
492
|
+
if (/^list of\b/i.test(text))
|
|
493
|
+
continue; // template placeholder
|
|
494
|
+
out.push(text);
|
|
495
|
+
}
|
|
496
|
+
return out;
|
|
497
|
+
}
|
|
498
|
+
function countOpenQuestions(text) {
|
|
499
|
+
const sec = parseMdSectionLoose(text, "Open questions");
|
|
500
|
+
if (!sec)
|
|
501
|
+
return 0;
|
|
502
|
+
const first = (firstNonEmptyLine(sec) ?? "").toLowerCase();
|
|
503
|
+
if (first.length === 0)
|
|
504
|
+
return 0;
|
|
505
|
+
if (/^[-*]?\s*(none|ninguna|ninguno|n\/a|—|-)\.?$/.test(first))
|
|
506
|
+
return 0;
|
|
507
|
+
const bullets = sec.split("\n").filter((l) => /^\s*[-*]\s+\S/.test(l)).length;
|
|
508
|
+
return bullets > 0 ? bullets : 1;
|
|
509
|
+
}
|
|
510
|
+
//# sourceMappingURL=workline-index-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workline-index-service.js","sourceRoot":"","sources":["../../src/application/workline-index-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
import { runCheckpointRead } from "../../application/checkpoint-service.js";
|
|
2
|
-
import {
|
|
2
|
+
import { readContextId } from "../context-id.js";
|
|
3
|
+
import { failSessionResolution } from "../render.js";
|
|
3
4
|
export const checkpointReadCommand = {
|
|
4
5
|
name: "checkpoint-read",
|
|
5
|
-
describe: "Read CHECKPOINT.md of the
|
|
6
|
+
describe: "Read CHECKPOINT.md of the conversation's session (or --code). " +
|
|
6
7
|
"Usage: aw checkpoint-read [--code <session>].",
|
|
7
8
|
async execute(args, ctx) {
|
|
8
9
|
const code = args.values.get("code");
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
const contextId = readContextId(ctx.env);
|
|
11
|
+
const data = await runCheckpointRead(ctx.fs, ctx.paths, {
|
|
12
|
+
...(code !== undefined ? { code } : {}),
|
|
13
|
+
...(contextId !== undefined ? { contextId } : {}),
|
|
14
|
+
});
|
|
15
|
+
if ("sessionError" in data)
|
|
16
|
+
return failSessionResolution(data.sessionError);
|
|
13
17
|
return { ok: true, data, exitCode: 0 };
|
|
14
18
|
},
|
|
15
19
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkpoint-read.js","sourceRoot":"","sources":["../../../src/cli/commands/checkpoint-read.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"checkpoint-read.js","sourceRoot":"","sources":["../../../src/cli/commands/checkpoint-read.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AAE5E,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAGrD,MAAM,CAAC,MAAM,qBAAqB,GAAe;IAC/C,IAAI,EAAE,iBAAiB;IACvB,QAAQ,EACN,gEAAgE;QAChE,+CAA+C;IACjD,KAAK,CAAC,OAAO,CAAC,IAAgB,EAAE,GAAe;QAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACrC,MAAM,SAAS,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACzC,MAAM,IAAI,GAAG,MAAM,iBAAiB,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,KAAK,EAAE;YACtD,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACvC,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAClD,CAAC,CAAC;QACH,IAAI,cAAc,IAAI,IAAI;YAAE,OAAO,qBAAqB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC5E,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IACzC,CAAC;CACF,CAAC"}
|
|
@@ -1,25 +1,52 @@
|
|
|
1
1
|
import { runAutoCompactOnClose, runCheckpointWrite, } from "../../application/checkpoint-write-service.js";
|
|
2
|
+
import { readHookStdin, resolveContextId } from "../context-id.js";
|
|
3
|
+
import { fail, failSessionResolution } from "../render.js";
|
|
4
|
+
/**
|
|
5
|
+
* Common lifecycle inputs: the explicit target, the conversation id (env var or
|
|
6
|
+
* the hook payload's `session_id`, whichever the host provides), and whether the
|
|
7
|
+
* host declared it can hold its compaction. Two identity signals that contradict
|
|
8
|
+
* each other surface as a failure instead of resolving a session.
|
|
9
|
+
*/
|
|
10
|
+
async function lifecycleOptions(args, ctx) {
|
|
11
|
+
const context = resolveContextId(ctx.env, await readHookStdin());
|
|
12
|
+
if (!context.ok)
|
|
13
|
+
return { failure: fail(context.code, context.message) };
|
|
14
|
+
const code = args.values.get("code");
|
|
15
|
+
return {
|
|
16
|
+
...(code !== undefined ? { code } : {}),
|
|
17
|
+
...(context.contextId !== undefined ? { contextId: context.contextId } : {}),
|
|
18
|
+
// Never inferred: a host that cannot pause would get false blocks.
|
|
19
|
+
...(args.flags.has("--can-pause") ? { canPauseCompaction: true } : {}),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
2
22
|
export const checkpointWriteCommand = {
|
|
3
23
|
name: "checkpoint-write",
|
|
4
|
-
describe: "Write CHECKPOINT.md
|
|
5
|
-
"Usage: aw checkpoint-write [--code <session>] [--force].",
|
|
24
|
+
describe: "Write CHECKPOINT.md for the conversation's session (or --code). PreCompact hook target. " +
|
|
25
|
+
"Usage: aw checkpoint-write [--code <session>] [--force] [--can-pause].",
|
|
6
26
|
async execute(args, ctx) {
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
if (force)
|
|
27
|
+
const base = await lifecycleOptions(args, ctx);
|
|
28
|
+
if ("failure" in base)
|
|
29
|
+
return base.failure;
|
|
30
|
+
const options = { ...base };
|
|
31
|
+
if (args.flags.has("--force"))
|
|
13
32
|
options.force = true;
|
|
14
33
|
const data = await runCheckpointWrite(ctx.fs, ctx.env, ctx.git, ctx.paths, options);
|
|
34
|
+
// Pausable host: exit 2 is the host-level "hold the compaction" signal, and
|
|
35
|
+
// the envelope carries the candidates the human picks from.
|
|
36
|
+
if ("blocked" in data) {
|
|
37
|
+
return { ...failSessionResolution(data.sessionError), exitCode: 2 };
|
|
38
|
+
}
|
|
15
39
|
return { ok: true, data, exitCode: 0 };
|
|
16
40
|
},
|
|
17
41
|
};
|
|
18
42
|
export const autoCompactOnCloseCommand = {
|
|
19
43
|
name: "auto-compact-on-close",
|
|
20
|
-
describe: "SessionEnd hook target —
|
|
21
|
-
async execute(
|
|
22
|
-
const
|
|
44
|
+
describe: "SessionEnd hook target — checkpoint the conversation's session, and only that one.",
|
|
45
|
+
async execute(args, ctx) {
|
|
46
|
+
const base = await lifecycleOptions(args, ctx);
|
|
47
|
+
if ("failure" in base)
|
|
48
|
+
return base.failure;
|
|
49
|
+
const data = await runAutoCompactOnClose(ctx.fs, ctx.env, ctx.git, ctx.paths, base);
|
|
23
50
|
return { ok: true, data, exitCode: 0 };
|
|
24
51
|
},
|
|
25
52
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkpoint-write.js","sourceRoot":"","sources":["../../../src/cli/commands/checkpoint-write.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"checkpoint-write.js","sourceRoot":"","sources":["../../../src/cli/commands/checkpoint-write.ts"],"names":[],"mappings":"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"}
|