@agent-plan/core 0.2.29 → 0.3.1
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/dist/accepted-decision-guard.d.ts +94 -0
- package/dist/accepted-decision-guard.d.ts.map +1 -0
- package/dist/accepted-decision-guard.js +110 -0
- package/dist/checklist.d.ts +28 -0
- package/dist/checklist.d.ts.map +1 -1
- package/dist/checklist.js +59 -0
- package/dist/feature-delete.d.ts +62 -0
- package/dist/feature-delete.d.ts.map +1 -0
- package/dist/feature-delete.js +49 -0
- package/dist/guard-decision.d.ts +128 -0
- package/dist/guard-decision.d.ts.map +1 -0
- package/dist/guard-decision.js +269 -0
- package/dist/guard-state.d.ts +14 -0
- package/dist/guard-state.d.ts.map +1 -0
- package/dist/guard-state.js +35 -0
- package/dist/handoff-context.d.ts +130 -1
- package/dist/handoff-context.d.ts.map +1 -1
- package/dist/handoff-context.js +167 -9
- package/dist/handoff-reply.d.ts +113 -0
- package/dist/handoff-reply.d.ts.map +1 -0
- package/dist/handoff-reply.js +279 -0
- package/dist/index.d.ts +18 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -1
- package/dist/load-reply.d.ts +63 -0
- package/dist/load-reply.d.ts.map +1 -0
- package/dist/load-reply.js +64 -0
- package/dist/mutation-reply.d.ts +105 -0
- package/dist/mutation-reply.d.ts.map +1 -0
- package/dist/mutation-reply.js +203 -0
- package/dist/naming.d.ts +1 -1
- package/dist/naming.d.ts.map +1 -1
- package/dist/naming.js +1 -1
- package/dist/on-hold.d.ts +55 -0
- package/dist/on-hold.d.ts.map +1 -0
- package/dist/on-hold.js +123 -0
- package/dist/package-version.d.ts +13 -0
- package/dist/package-version.d.ts.map +1 -1
- package/dist/package-version.js +32 -0
- package/dist/pagination.d.ts +19 -0
- package/dist/pagination.d.ts.map +1 -0
- package/dist/pagination.js +15 -0
- package/dist/payload-fallback.js +1 -1
- package/dist/plan-store.d.ts +141 -8
- package/dist/plan-store.d.ts.map +1 -1
- package/dist/plan-store.js +459 -87
- package/dist/project-context-migration.d.ts +5 -0
- package/dist/project-context-migration.d.ts.map +1 -1
- package/dist/project-context-migration.js +13 -0
- package/dist/project-context.d.ts +397 -0
- package/dist/project-context.d.ts.map +1 -0
- package/dist/project-context.js +294 -0
- package/dist/recap.d.ts.map +1 -1
- package/dist/recap.js +33 -0
- package/dist/recommend-reply.d.ts +51 -0
- package/dist/recommend-reply.d.ts.map +1 -0
- package/dist/recommend-reply.js +93 -0
- package/dist/refs.d.ts +16 -0
- package/dist/refs.d.ts.map +1 -1
- package/dist/refs.js +38 -0
- package/dist/renderer.d.ts.map +1 -1
- package/dist/schema.d.ts +7 -2
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +8 -3
- package/dist/stranded-phase.d.ts +73 -0
- package/dist/stranded-phase.d.ts.map +1 -0
- package/dist/stranded-phase.js +93 -0
- package/dist/task-completion-gate.d.ts +84 -0
- package/dist/task-completion-gate.d.ts.map +1 -0
- package/dist/task-completion-gate.js +72 -0
- package/dist/task-context.d.ts +1 -0
- package/dist/task-context.d.ts.map +1 -1
- package/dist/task-context.js +42 -14
- package/dist/task-lifecycle.d.ts +12 -0
- package/dist/task-lifecycle.d.ts.map +1 -0
- package/dist/task-lifecycle.js +23 -0
- package/dist/task-order-context.d.ts +72 -0
- package/dist/task-order-context.d.ts.map +1 -0
- package/dist/task-order-context.js +82 -0
- package/dist/task-selection.d.ts +4 -1
- package/dist/task-selection.d.ts.map +1 -1
- package/dist/task-selection.js +36 -14
- package/dist/task-start-outcome.d.ts +26 -0
- package/dist/task-start-outcome.d.ts.map +1 -1
- package/dist/task-start-outcome.js +23 -0
- package/dist/text-bounds.d.ts +32 -0
- package/dist/text-bounds.d.ts.map +1 -0
- package/dist/text-bounds.js +43 -0
- package/dist/write-coordination.d.ts +2 -2
- package/dist/write-coordination.js +2 -2
- package/package.json +1 -1
- package/planner-skill.md +30 -12
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import { realpathSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
4
|
+
const FILE_WRITE_TOOLS = new Set(["edit", "write"]);
|
|
5
|
+
/** Strip fd-duplication idioms (`2>&1`, `>&2`, `1>&2`) before segmenting or
|
|
6
|
+
* matching — they duplicate a stream, not a file, are extremely common in
|
|
7
|
+
* otherwise read-only commands, and their bare `&` would otherwise be
|
|
8
|
+
* misread as a command separator by {@link bashSegments}. */
|
|
9
|
+
function stripFdDuplication(command) {
|
|
10
|
+
return command.replace(/\d*>&\d+/g, " ");
|
|
11
|
+
}
|
|
12
|
+
/** Blank out shell operators (`>`, `<`, `|`, `;`, `&`, newlines) that sit
|
|
13
|
+
* inside single or double quotes. They are literal text there — a commit
|
|
14
|
+
* message's `<name@example.com>`, a `grep "a|b"` pattern — not redirects or
|
|
15
|
+
* separators. Quoted paths keep their characters, so `> "/tmp/x"` still
|
|
16
|
+
* reads as a redirect to `/tmp/x`. */
|
|
17
|
+
function maskQuotedOperators(command) {
|
|
18
|
+
let out = "";
|
|
19
|
+
let quote = null;
|
|
20
|
+
for (let i = 0; i < command.length; i += 1) {
|
|
21
|
+
const ch = command[i];
|
|
22
|
+
if (quote === null) {
|
|
23
|
+
if (ch === "\\") {
|
|
24
|
+
out += ch + (command[i + 1] ?? "");
|
|
25
|
+
i += 1;
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
if (ch === "'" || ch === '"')
|
|
29
|
+
quote = ch;
|
|
30
|
+
out += ch;
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
if (quote === '"' && ch === "\\") {
|
|
34
|
+
out += "__";
|
|
35
|
+
i += 1;
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (ch === quote) {
|
|
39
|
+
quote = null;
|
|
40
|
+
out += ch;
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
out += /[<>|;&\n]/.test(ch) ? "_" : ch;
|
|
44
|
+
}
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
/** The command line as write-detection reads it: quoted operators masked,
|
|
48
|
+
* then fd-duplication removed. Both detection and target extraction use
|
|
49
|
+
* this, so they always see the same text. */
|
|
50
|
+
function normalizeBashCommand(command) {
|
|
51
|
+
return stripFdDuplication(maskQuotedOperators(command));
|
|
52
|
+
}
|
|
53
|
+
/** Split a Bash command line into pipe/list segments so write-detection on
|
|
54
|
+
* one segment (e.g. `sed -i` on the left of a pipe) doesn't get confused by
|
|
55
|
+
* an unrelated flag on the other side (e.g. `grep -i` on the right). Best
|
|
56
|
+
* effort only — nested subshells are not parsed. Callers must pass the
|
|
57
|
+
* command through {@link normalizeBashCommand} first, or a bare `2>&1`
|
|
58
|
+
* splits on its `&` and a quoted `|` splits a string in two. */
|
|
59
|
+
function bashSegments(command) {
|
|
60
|
+
return command
|
|
61
|
+
.split(/(?:&&|\|\||[;&|\n])+/)
|
|
62
|
+
.map((segment) => segment.trim())
|
|
63
|
+
.filter(Boolean);
|
|
64
|
+
}
|
|
65
|
+
const GIT_TREE_WRITE_RE = /\bgit\s+(?:checkout|apply|restore|stash\s+pop|reset\s+--hard)\b/;
|
|
66
|
+
const IN_PLACE_EDITOR_RE = /\b(sed|perl)\b/;
|
|
67
|
+
const IN_PLACE_FLAG_RE = /(^|\s)-\S*i(\s|$)/;
|
|
68
|
+
function isWriteShapedBashSegment(segment) {
|
|
69
|
+
if (/>{1,2}/.test(segment))
|
|
70
|
+
return true;
|
|
71
|
+
if (/\btee\b/.test(segment))
|
|
72
|
+
return true;
|
|
73
|
+
if (/\b(cp|mv)\b/.test(segment))
|
|
74
|
+
return true;
|
|
75
|
+
if (/\brm\b/.test(segment))
|
|
76
|
+
return true;
|
|
77
|
+
if (GIT_TREE_WRITE_RE.test(segment))
|
|
78
|
+
return true;
|
|
79
|
+
if (IN_PLACE_EDITOR_RE.test(segment) && IN_PLACE_FLAG_RE.test(segment))
|
|
80
|
+
return true;
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Whether a Bash command line contains a write-shaped operation: output
|
|
85
|
+
* redirection, `tee`, in-place `sed`/`perl`, a file-creating `cp`/`mv`,
|
|
86
|
+
* `rm`, or a `git` operation that rewrites tracked files. Deliberately
|
|
87
|
+
* over-inclusive: `git`, build/test runners, `ls`, `cat`, `grep`, `find`
|
|
88
|
+
* and friends must stay unmatched, but when in doubt this returns true — a
|
|
89
|
+
* false positive costs one warning to the agent, never a blocked call or a
|
|
90
|
+
* prompt, so under-matching (missing a real edit) is the worse failure.
|
|
91
|
+
*/
|
|
92
|
+
export function isWriteShapedBashCommand(command) {
|
|
93
|
+
if (!command || !command.trim())
|
|
94
|
+
return false;
|
|
95
|
+
return bashSegments(normalizeBashCommand(command)).some(isWriteShapedBashSegment);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Best-effort extraction of the file path(s) a write-shaped Bash segment
|
|
99
|
+
* targets, so a command that only touches `.planner/` or files outside the
|
|
100
|
+
* project earns no warning. This cannot see through a heredoc whose target
|
|
101
|
+
* is computed (a variable, command substitution, etc.) rather than written
|
|
102
|
+
* literally in the command line — that case still reaches the in-progress /
|
|
103
|
+
* bypass checks and can warn, rather than being silently treated as safe.
|
|
104
|
+
*
|
|
105
|
+
* A wider gap of the same kind: a command that writes through an
|
|
106
|
+
* interpreter (`python3 - <<PY` then `open(path, "w")`, `node -e`, a script
|
|
107
|
+
* invoked by name) is opaque here — nothing in the command line looks
|
|
108
|
+
* write-shaped. P105(F005)/T431 evaluated closing this and chose not to,
|
|
109
|
+
* for reasons that also rule out revisiting it the same way later:
|
|
110
|
+
* - Parsing the script body is unbounded (a path can be computed, read
|
|
111
|
+
* from argv, or built at runtime) and would trade an honest documented
|
|
112
|
+
* limit for false confidence.
|
|
113
|
+
* - A PostToolUse hook that notices tracked files changed while no task
|
|
114
|
+
* was in progress sounds like a fit (the guard's job is visibility, not
|
|
115
|
+
* prevention), but it collides with this project's own workflow: a
|
|
116
|
+
* task is left with its changes uncommitted for the orchestrator to
|
|
117
|
+
* review, so "no task in-progress, tracked files changed outside
|
|
118
|
+
* .planner/" is the routine state right after every task completes,
|
|
119
|
+
* not a signal of anything wrong. Telling that apart from a real
|
|
120
|
+
* interpreter write means diffing only the delta from one specific
|
|
121
|
+
* Bash call, which needs a session-scoped git-status baseline checked
|
|
122
|
+
* on every Bash invocation — read-only ones included, since which
|
|
123
|
+
* commands wrote can't be known in advance. That statefulness and
|
|
124
|
+
* per-call cost is worse than the gap it would close.
|
|
125
|
+
* The limit stands, documented rather than silently assumed away.
|
|
126
|
+
*/
|
|
127
|
+
export function extractBashWriteTargets(command) {
|
|
128
|
+
const targets = [];
|
|
129
|
+
for (const segment of bashSegments(normalizeBashCommand(command))) {
|
|
130
|
+
const redirect = segment.match(/>{1,2}\s*([^\s;&|>]+)/);
|
|
131
|
+
if (redirect?.[1])
|
|
132
|
+
targets.push(redirect[1]);
|
|
133
|
+
const tee = segment.match(/\btee\b\s+(?:-\S+\s+)*([^\s;&|]+)/);
|
|
134
|
+
if (tee?.[1])
|
|
135
|
+
targets.push(tee[1]);
|
|
136
|
+
if (/\b(cp|mv)\b/.test(segment)) {
|
|
137
|
+
const tokens = segment.trim().split(/\s+/).filter((token) => !token.startsWith("-"));
|
|
138
|
+
const last = tokens[tokens.length - 1];
|
|
139
|
+
if (last && !/^(cp|mv)$/.test(last))
|
|
140
|
+
targets.push(last);
|
|
141
|
+
}
|
|
142
|
+
if (/\brm\b/.test(segment)) {
|
|
143
|
+
const tokens = segment.trim().split(/\s+/).filter((token) => !token.startsWith("-") && token !== "rm");
|
|
144
|
+
targets.push(...tokens);
|
|
145
|
+
}
|
|
146
|
+
if (IN_PLACE_EDITOR_RE.test(segment) && IN_PLACE_FLAG_RE.test(segment)) {
|
|
147
|
+
const tokens = segment.trim().split(/\s+/);
|
|
148
|
+
const last = tokens[tokens.length - 1];
|
|
149
|
+
if (last && !last.startsWith("-"))
|
|
150
|
+
targets.push(last);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return targets.filter(Boolean);
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Canonicalize a path by resolving symlinks wherever the filesystem lets us,
|
|
157
|
+
* so e.g. a macOS temp dir under `/var` (itself a symlink to `/private/var`)
|
|
158
|
+
* compares equal to a path already given in its resolved form, instead of
|
|
159
|
+
* two spellings of the same directory looking like different ones. `Edit`
|
|
160
|
+
* targets an existing file, but `Write` and Bash redirects can target a path
|
|
161
|
+
* that doesn't exist yet — realpath() throws ENOENT for those, so this walks
|
|
162
|
+
* up to the nearest existing ancestor, canonicalizes that, and reattaches
|
|
163
|
+
* the missing tail. Never throws; worst case it returns `path` unchanged.
|
|
164
|
+
*/
|
|
165
|
+
function canonicalize(path) {
|
|
166
|
+
try {
|
|
167
|
+
return realpathSync(path);
|
|
168
|
+
}
|
|
169
|
+
catch {
|
|
170
|
+
const parent = dirname(path);
|
|
171
|
+
if (parent === path)
|
|
172
|
+
return path; // reached the filesystem root
|
|
173
|
+
return join(canonicalize(parent), basename(path));
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
/** Turn a path as written in a command line into one `resolve` understands:
|
|
177
|
+
* drop surrounding quotes and expand a leading `~` or `$HOME`. Anything else
|
|
178
|
+
* the shell would expand (other variables, command substitution) is left
|
|
179
|
+
* as-is, so it resolves inside the project and the agent is still warned. */
|
|
180
|
+
function shellPathToFsPath(candidate) {
|
|
181
|
+
const unquoted = candidate.replace(/^['"]|['"]$/g, "");
|
|
182
|
+
return unquoted.replace(/^(?:~|\$HOME|\$\{HOME\})(?=\/|$)/, homedir());
|
|
183
|
+
}
|
|
184
|
+
/** Whether `candidate` resolves to `root` itself or a path inside it. */
|
|
185
|
+
function isPathInside(candidate, root, cwd) {
|
|
186
|
+
const resolvedRoot = canonicalize(resolve(root));
|
|
187
|
+
const resolvedCandidate = canonicalize(resolve(cwd, shellPathToFsPath(candidate)));
|
|
188
|
+
const rel = relative(resolvedRoot, resolvedCandidate);
|
|
189
|
+
return rel === "" || (!rel.startsWith("..") && !isAbsolute(rel));
|
|
190
|
+
}
|
|
191
|
+
/** Whether `candidate` resolves to a path inside `plannerRoot` (or is it exactly). */
|
|
192
|
+
export function isPathInsidePlannerRoot(candidate, plannerRoot, cwd) {
|
|
193
|
+
return isPathInside(candidate, plannerRoot, cwd);
|
|
194
|
+
}
|
|
195
|
+
/** Whether writing `candidate` changes the project's code: it is inside the
|
|
196
|
+
* project (the directory that owns `.planner/`) and not inside `.planner/`.
|
|
197
|
+
* `/dev/null`, `~/.claude/...`, temp dirs and other repositories are not. */
|
|
198
|
+
export function isProjectCodePath(candidate, plannerRoot, cwd) {
|
|
199
|
+
return isPathInside(candidate, dirname(plannerRoot), cwd) && !isPathInside(candidate, plannerRoot, cwd);
|
|
200
|
+
}
|
|
201
|
+
/** Which paths a covered tool call would write to, before any filtering;
|
|
202
|
+
* empty when the target cannot be read from the event. */
|
|
203
|
+
function rawWriteTargets(event) {
|
|
204
|
+
const tool = event.toolName.toLowerCase();
|
|
205
|
+
if (FILE_WRITE_TOOLS.has(tool)) {
|
|
206
|
+
return { covered: true, paths: event.filePath ? [event.filePath] : [] };
|
|
207
|
+
}
|
|
208
|
+
if (tool === "notebookedit") {
|
|
209
|
+
return { covered: true, paths: event.notebookPath ? [event.notebookPath] : [] };
|
|
210
|
+
}
|
|
211
|
+
if (tool === "bash") {
|
|
212
|
+
const command = event.command ?? "";
|
|
213
|
+
if (!isWriteShapedBashCommand(command))
|
|
214
|
+
return { covered: false, paths: [] };
|
|
215
|
+
return { covered: true, paths: extractBashWriteTargets(command) };
|
|
216
|
+
}
|
|
217
|
+
return { covered: false, paths: [] };
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Whether a tool call may change the project's code, and so needs the guard
|
|
221
|
+
* to look at task state. This is the one place that rule lives; the hook's
|
|
222
|
+
* cheap early exit and {@link noTaskWarning} both read `guarded`.
|
|
223
|
+
*
|
|
224
|
+
* - Tools that never write (Read, Grep, MCP tools, read-only Bash, ...) are
|
|
225
|
+
* not guarded.
|
|
226
|
+
* - A write whose targets are all known and none is project code (inside
|
|
227
|
+
* `.planner/`, `/dev/null`, `~/.claude/...`, a temp dir, another repo) is
|
|
228
|
+
* not guarded: updating the planner or the user's own config never needs a
|
|
229
|
+
* task.
|
|
230
|
+
* - A write with at least one project-code target is guarded, with `paths`
|
|
231
|
+
* narrowed to those targets.
|
|
232
|
+
* - A write whose target is unknown (a computed heredoc, an Edit with no
|
|
233
|
+
* path) is guarded with empty `paths` — never silently allowed.
|
|
234
|
+
*/
|
|
235
|
+
export function classifyGuardedTool(event) {
|
|
236
|
+
const { covered, paths } = rawWriteTargets(event);
|
|
237
|
+
if (!covered)
|
|
238
|
+
return { guarded: false, paths: [] };
|
|
239
|
+
if (paths.length === 0)
|
|
240
|
+
return { guarded: true, paths: [] };
|
|
241
|
+
const projectPaths = paths.filter((path) => isProjectCodePath(path, event.plannerRoot, event.cwd));
|
|
242
|
+
return { guarded: projectPaths.length > 0, paths: projectPaths };
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* The warning for a tool call that changes project code while no task is in
|
|
246
|
+
* progress, or none. Never a block or a prompt: the adapter lets the call
|
|
247
|
+
* proceed either way and only passes the text to the agent. Pure apart from
|
|
248
|
+
* the cheap symlink canonicalization in {@link isPathInsidePlannerRoot}.
|
|
249
|
+
*
|
|
250
|
+
* Order mirrors the cost of finding out: anything that cannot change project
|
|
251
|
+
* code (see {@link classifyGuardedTool}) is settled from the event alone, so
|
|
252
|
+
* adapters can skip loading the plan for it.
|
|
253
|
+
*/
|
|
254
|
+
export function noTaskWarning(event, state) {
|
|
255
|
+
const classification = classifyGuardedTool(event);
|
|
256
|
+
if (!classification.guarded)
|
|
257
|
+
return {};
|
|
258
|
+
if (!state.hasPlannerDir || state.totalTasks === 0)
|
|
259
|
+
return {};
|
|
260
|
+
if (state.hasInProgressTask || state.guardBypassed)
|
|
261
|
+
return {};
|
|
262
|
+
const target = classification.paths.length > 0 ? classification.paths.join(", ") : "a project file";
|
|
263
|
+
const start = state.focusTask
|
|
264
|
+
? `start the task that covers it (/planner task start ${state.focusTask.id} — ${state.focusTask.title}, or another one)`
|
|
265
|
+
: "start the task that covers it (/planner task start <task>)";
|
|
266
|
+
return {
|
|
267
|
+
warning: `Agent Plan: no task is in progress, and this call changes project code (${target}). It was not blocked. If this is planned work, ${start} so the plan stays accurate. Planner changes never need a task.`,
|
|
268
|
+
};
|
|
269
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { PlanStore } from "./plan-store.js";
|
|
2
|
+
import type { GuardStateInput } from "./guard-decision.js";
|
|
3
|
+
export interface NoTaskGuardState extends GuardStateInput {
|
|
4
|
+
inProgressTaskIds: string[];
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Read the planner state the no-task warning needs, once, for any adapter.
|
|
8
|
+
* The suggested task is the one the plan is already pointing at: the
|
|
9
|
+
* resume file's in-progress task, then an open task in the current phase,
|
|
10
|
+
* then a paused task, then the first open task. Never throws for a missing
|
|
11
|
+
* planner; it reports `hasPlannerDir: false` instead.
|
|
12
|
+
*/
|
|
13
|
+
export declare function loadNoTaskGuardState(st: PlanStore): Promise<NoTaskGuardState>;
|
|
14
|
+
//# sourceMappingURL=guard-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guard-state.d.ts","sourceRoot":"","sources":["../src/guard-state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,MAAM,WAAW,gBAAiB,SAAQ,eAAe;IACvD,iBAAiB,EAAE,MAAM,EAAE,CAAC;CAC7B;AAID;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CAAC,EAAE,EAAE,SAAS,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA4BnF"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const CLOSED_STATUSES = new Set(["done", "canceled", "rejected"]);
|
|
2
|
+
/**
|
|
3
|
+
* Read the planner state the no-task warning needs, once, for any adapter.
|
|
4
|
+
* The suggested task is the one the plan is already pointing at: the
|
|
5
|
+
* resume file's in-progress task, then an open task in the current phase,
|
|
6
|
+
* then a paused task, then the first open task. Never throws for a missing
|
|
7
|
+
* planner; it reports `hasPlannerDir: false` instead.
|
|
8
|
+
*/
|
|
9
|
+
export async function loadNoTaskGuardState(st) {
|
|
10
|
+
const hasPlannerDir = await st.exists().catch(() => false);
|
|
11
|
+
if (!hasPlannerDir) {
|
|
12
|
+
return { hasPlannerDir, totalTasks: 0, hasInProgressTask: false, inProgressTaskIds: [], guardBypassed: false };
|
|
13
|
+
}
|
|
14
|
+
const [workspace, resume, guardBypassed] = await Promise.all([
|
|
15
|
+
st.loadAll(),
|
|
16
|
+
st.loadResume().catch(() => null),
|
|
17
|
+
st.isGuardBypassed().catch(() => false),
|
|
18
|
+
]);
|
|
19
|
+
const allTasks = workspace.phases.flatMap((phase) => phase.tasks.map((task) => ({ phase, task })));
|
|
20
|
+
const inProgressTaskIds = allTasks.filter(({ task }) => task.status === "in-progress").map(({ task }) => task.id);
|
|
21
|
+
const isOpen = (status) => !CLOSED_STATUSES.has(status);
|
|
22
|
+
const focus = (resume?.inProgressTaskIds?.[0] ? allTasks.find(({ task }) => task.id === resume.inProgressTaskIds[0]) : undefined)
|
|
23
|
+
?? (resume?.currentPhaseId ? allTasks.find(({ phase, task }) => phase.id === resume.currentPhaseId && isOpen(task.status)) : undefined)
|
|
24
|
+
?? allTasks.find(({ task }) => task.pauseSnapshot)
|
|
25
|
+
?? allTasks.find(({ task }) => task.status === "planned" || task.status === "blocked" || task.status === "waiting")
|
|
26
|
+
?? allTasks.find(({ task }) => isOpen(task.status));
|
|
27
|
+
return {
|
|
28
|
+
hasPlannerDir,
|
|
29
|
+
totalTasks: allTasks.length,
|
|
30
|
+
hasInProgressTask: inProgressTaskIds.length > 0,
|
|
31
|
+
inProgressTaskIds,
|
|
32
|
+
guardBypassed,
|
|
33
|
+
...(focus ? { focusTask: { id: focus.task.id, title: focus.task.title } } : {}),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
@@ -124,12 +124,45 @@ export declare const HANDOFF_COLD_START_INVENTORY_CATEGORIES: readonly [{
|
|
|
124
124
|
export declare const HANDOFF_CANONICAL_SECTIONS: readonly ["Current focus", "Current and partial state", "Preservation constraints", "Supporting documents", "Blockers and risks", "How to resume"];
|
|
125
125
|
export type HandoffCompletenessCategory = typeof HANDOFF_COMPLETENESS_CATEGORIES[number]["id"];
|
|
126
126
|
export type HandoffColdStartInventoryCategory = typeof HANDOFF_COLD_START_INVENTORY_CATEGORIES[number]["id"];
|
|
127
|
-
export type HandoffContractErrorCode = "HANDOFF_PREFLIGHT_REQUIRED" | "HANDOFF_REASON_REQUIRED" | "HANDOFF_CANONICAL_SECTIONS_REQUIRED" | "HANDOFF_COMPLETENESS_AUDIT_REQUIRED" | "HANDOFF_COLD_START_INVENTORY_REQUIRED" | "HANDOFF_COLD_START_INVENTORY_UNCOVERED" | "HANDOFF_CONTENT_LIMIT_EXCEEDED" | "HANDOFF_SUPPORTING_DOCUMENT_INVALID" | "HANDOFF_PERSISTENCE_VERIFICATION_FAILED" | "HANDOFF_READBACK_VERIFICATION_REQUIRED" | "HANDOFF_READBACK_GAPS_FOUND";
|
|
127
|
+
export type HandoffContractErrorCode = "HANDOFF_PREFLIGHT_REQUIRED" | "HANDOFF_REASON_REQUIRED" | "HANDOFF_CANONICAL_SECTIONS_REQUIRED" | "HANDOFF_COMPLETENESS_AUDIT_REQUIRED" | "HANDOFF_COLD_START_INVENTORY_REQUIRED" | "HANDOFF_COLD_START_INVENTORY_UNCOVERED" | "HANDOFF_CONTENT_LIMIT_EXCEEDED" | "HANDOFF_SUPPORTING_DOCUMENT_INVALID" | "HANDOFF_PERSISTENCE_VERIFICATION_FAILED" | "HANDOFF_READBACK_VERIFICATION_REQUIRED" | "HANDOFF_READBACK_GAPS_FOUND" | "HANDOFF_RETAINED_CONTENT_NOT_FOUND" | "HANDOFF_SECTION_RECONCILIATION_REQUIRED";
|
|
128
128
|
export declare class HandoffContractError extends Error {
|
|
129
129
|
readonly code: HandoffContractErrorCode;
|
|
130
130
|
readonly details: Record<string, unknown>;
|
|
131
131
|
constructor(code: HandoffContractErrorCode, message: string, details?: Record<string, unknown>);
|
|
132
132
|
}
|
|
133
|
+
/** Single source of truth for the supportingDocuments recovery statement.
|
|
134
|
+
* Rendered in prepare output (before drafting) and attached to every
|
|
135
|
+
* agent-supplied-manifest failure of HANDOFF_SUPPORTING_DOCUMENT_INVALID
|
|
136
|
+
* (as details.recovery) so both adapters can render it without duplicating
|
|
137
|
+
* the wording. */
|
|
138
|
+
export declare const HANDOFF_SUPPORTING_DOCUMENTS_GUIDANCE = "supportingDocuments is optional and usually unnecessary: content above the target length is externalized automatically into .planner/docs/. Drop the field and retry unless you are linking a document you created yourself.";
|
|
139
|
+
/** Build a HANDOFF_SUPPORTING_DOCUMENT_INVALID error for a defect in an
|
|
140
|
+
* agent-supplied manifest entry, always carrying the droppable-field
|
|
141
|
+
* recovery statement. Do not use this for planner-owned failures (e.g. the
|
|
142
|
+
* auto-externalized document's own path) — those are not something dropping
|
|
143
|
+
* the agent's field would fix. */
|
|
144
|
+
export declare function supportingDocumentInvalidError(message: string, details?: Record<string, unknown>): HandoffContractError;
|
|
145
|
+
/** Build a HANDOFF_RETAINED_CONTENT_NOT_FOUND error: `content` was omitted
|
|
146
|
+
* from a handoff_write call and PlanStore has no body retained for this
|
|
147
|
+
* phase + expectedHandoffUpdatedAt token (see PlanStore.retainHandoffDraft /
|
|
148
|
+
* getRetainedHandoffDraft). Reasons: no write against this token has ever
|
|
149
|
+
* failed, the retained draft aged out, the phase went terminal and its
|
|
150
|
+
* drafts were discarded, or the token itself is wrong/stale. Content is
|
|
151
|
+
* always required on the first write attempt for a token; it becomes
|
|
152
|
+
* optional only on a retry that reuses a retained one. */
|
|
153
|
+
export declare function retainedHandoffContentNotFoundError(phaseId: string, expectedHandoffUpdatedAt: string): HandoffContractError;
|
|
154
|
+
/** One prior section's fate, supplied by the author when validateHandoffSectionReconciliation
|
|
155
|
+
* names it as unaccounted for. `section` must match a heading named in the
|
|
156
|
+
* error's `unaccountedSections`; `disposition` is a short, substantive
|
|
157
|
+
* statement of what happened to it — dropped deliberately, superseded by
|
|
158
|
+
* newer content, or folded into a different section (including a rename).
|
|
159
|
+
* See P104(F005)/T416: this is the evidence that replaces the unchecked
|
|
160
|
+
* `reconciledExistingHandoff` boolean for the sections most likely to be
|
|
161
|
+
* silently lost. */
|
|
162
|
+
export interface HandoffSectionDispositionInput {
|
|
163
|
+
section: string;
|
|
164
|
+
disposition: string;
|
|
165
|
+
}
|
|
133
166
|
export interface HandoffCompletenessAuditInput {
|
|
134
167
|
version: number;
|
|
135
168
|
entries: HandoffCompletenessEntry[];
|
|
@@ -152,6 +185,64 @@ export interface HandoffContentExternalization {
|
|
|
152
185
|
extendedContent: string;
|
|
153
186
|
supportingDocument?: HandoffSupportingDocumentInput;
|
|
154
187
|
}
|
|
188
|
+
/** One document that a previous handoff refresh moved out of the inline
|
|
189
|
+
* capsule because it exceeded TARGET_HANDOFF_CONTENT_CHARS. Populated by
|
|
190
|
+
* PlanStore.preparePhaseHandoff (which alone has filesystem access); pure
|
|
191
|
+
* code here only shapes the type and the recognition/heading helpers below.
|
|
192
|
+
* `headings` and `missing` are always meaningful even when `content` is
|
|
193
|
+
* omitted for budget reasons, so a caller who cannot inline the body can
|
|
194
|
+
* still name what it contained (see handoff-reply.ts). */
|
|
195
|
+
export interface HandoffExternalizedDocumentAudit {
|
|
196
|
+
path: string;
|
|
197
|
+
description: string;
|
|
198
|
+
/** Level-2 (`##`) headings found in the document, in order. Present even
|
|
199
|
+
* when `content` is null, so the omission names what the document held. */
|
|
200
|
+
headings: string[];
|
|
201
|
+
/** Full document body, or null when it could not be read back from disk
|
|
202
|
+
* (deleted, moved, or unreadable). Bounding this for transport is the
|
|
203
|
+
* reply builder's job (handoff-reply.ts), not this audit's. */
|
|
204
|
+
content: string | null;
|
|
205
|
+
contentLength: number;
|
|
206
|
+
missing: boolean;
|
|
207
|
+
}
|
|
208
|
+
/** The exact description externalizeOversizedHandoffContent stamps on the
|
|
209
|
+
* supporting-document entry it generates for an auto-externalized document.
|
|
210
|
+
* The single source of truth for recognizing one later: handoff_prepare
|
|
211
|
+
* matches on this instead of the timestamped file-naming convention, so
|
|
212
|
+
* detection and generation cannot drift apart. A document a human or agent
|
|
213
|
+
* linked deliberately (a different description) is already named in the
|
|
214
|
+
* persisted capsule's own "Supporting documents" bullet and is out of scope
|
|
215
|
+
* here — only content the tooling itself moved out without being asked. */
|
|
216
|
+
export declare const HANDOFF_AUTO_EXTERNALIZED_DOCUMENT_DESCRIPTION = "Full submitted handoff detail externalized automatically; required for cold resume and reconciliation.";
|
|
217
|
+
export declare function isAutoExternalizedHandoffDocument(document: {
|
|
218
|
+
description: string;
|
|
219
|
+
}): boolean;
|
|
220
|
+
/** Level-2 (`##`) headings of a handoff document, in order. Used to name
|
|
221
|
+
* what an externalized document contains when its content cannot be
|
|
222
|
+
* inlined (budget, or the file is missing) and as a table of contents
|
|
223
|
+
* alongside content that is inlined. */
|
|
224
|
+
export declare function extractHandoffSectionHeadings(content: string): string[];
|
|
225
|
+
/**
|
|
226
|
+
* Make reconciliation evidenced rather than asserted (P104(F005)/T416).
|
|
227
|
+
*
|
|
228
|
+
* Narrow by design: this compares `##` heading text only, never section
|
|
229
|
+
* content or a fixed category list — it is not a return to the 16-section
|
|
230
|
+
* scaffold and 14-category cold-start inventory P100(F021)/T396 removed for
|
|
231
|
+
* making authoring verbose and failing late. A prior capsule with no
|
|
232
|
+
* headings (or a new submission with none) simply has nothing to name here;
|
|
233
|
+
* the check degrades to a no-op rather than blocking the write.
|
|
234
|
+
*
|
|
235
|
+
* A prior section vanishes from the new content in three ways an author
|
|
236
|
+
* might legitimately intend: dropped because it no longer matters,
|
|
237
|
+
* superseded by newer content, or folded into a different section (a rename
|
|
238
|
+
* reads the same way — the old heading is gone, the content lives under a
|
|
239
|
+
* new one). This function does not try to tell those apart; it only
|
|
240
|
+
* requires the author to say which happened, per named section, before the
|
|
241
|
+
* write proceeds. A deliberate full rewrite where every prior section is
|
|
242
|
+
* obsolete is handled the same way: every heading is named, and the author
|
|
243
|
+
* writes one disposition per heading.
|
|
244
|
+
*/
|
|
245
|
+
export declare function validateHandoffSectionReconciliation(priorSectionHeadings: string[], newContent: string, dispositions: HandoffSectionDispositionInput[] | undefined): void;
|
|
155
246
|
export interface HandoffTaskContextUpdate {
|
|
156
247
|
taskId: string;
|
|
157
248
|
completionSummary: string;
|
|
@@ -212,6 +303,27 @@ export interface PhaseHandoffAudit {
|
|
|
212
303
|
}>;
|
|
213
304
|
existingCompletenessAudit: HandoffCompletenessAudit | null;
|
|
214
305
|
phaseWorkMap: PhaseWorkMap;
|
|
306
|
+
/** Read before drafting: supportingDocuments is optional and rarely needed. */
|
|
307
|
+
supportingDocumentsGuidance: string;
|
|
308
|
+
/** Documents the existing active handoff's own auto-externalization moved
|
|
309
|
+
* out of the inline capsule (see HANDOFF_AUTO_EXTERNALIZED_DOCUMENT_DESCRIPTION).
|
|
310
|
+
* Empty when there is no active handoff or nothing was ever externalized
|
|
311
|
+
* from it. auditPhaseHandoff itself never populates this (it is pure and
|
|
312
|
+
* has no filesystem access) — PlanStore.preparePhaseHandoff fills it in
|
|
313
|
+
* after reading each document back from .planner/docs/. */
|
|
314
|
+
externalizedHandoffDocuments: HandoffExternalizedDocumentAudit[];
|
|
315
|
+
/** `##` headings of the full prior capsule the next write will supersede:
|
|
316
|
+
* the active handoff's own headings plus, per P104(F005)/T415, the
|
|
317
|
+
* headings of every document its own auto-externalization moved out —
|
|
318
|
+
* never the elided copy, so a heading that survives only in the
|
|
319
|
+
* externalized file is still named. Empty when there is no active
|
|
320
|
+
* handoff to reconcile against (first write, or one already archived by
|
|
321
|
+
* handoff_clear). auditPhaseHandoff itself only derives this from the
|
|
322
|
+
* compact capsule text (no filesystem access); PlanStore.preparePhaseHandoff
|
|
323
|
+
* and PlanStore.refreshPhaseHandoff both overlay the externalized
|
|
324
|
+
* documents' own headings after reading them back. See
|
|
325
|
+
* validateHandoffSectionReconciliation, which consumes this list. */
|
|
326
|
+
priorSectionHeadings: string[];
|
|
215
327
|
}
|
|
216
328
|
export interface RefreshPhaseHandoffInput {
|
|
217
329
|
/** Structured, human-supplied explanation; rendered by the planner. */
|
|
@@ -219,9 +331,26 @@ export interface RefreshPhaseHandoffInput {
|
|
|
219
331
|
content: string;
|
|
220
332
|
expectedHandoffUpdatedAt: string;
|
|
221
333
|
reconciledExistingHandoff: boolean;
|
|
334
|
+
/** The full prior capsule's `##` headings (see PhaseHandoffAudit.priorSectionHeadings),
|
|
335
|
+
* as PlanStore derived them from the live phase this write is targeting —
|
|
336
|
+
* never a stale copy captured at prepare time, so a handoff archived
|
|
337
|
+
* between prepare and write (phase.handoff now "") correctly yields no
|
|
338
|
+
* sections to reconcile instead of demanding dispositions for content
|
|
339
|
+
* that is no longer live. Populated by PlanStore; absent only in direct
|
|
340
|
+
* unit calls to applyHandoffContextSync/validateHandoffContextSync that
|
|
341
|
+
* do not exercise this check. */
|
|
342
|
+
priorSectionHeadings?: string[];
|
|
343
|
+
/** Per-section account for each entry in priorSectionHeadings that has no
|
|
344
|
+
* counterpart heading in the submitted content. See
|
|
345
|
+
* validateHandoffSectionReconciliation. */
|
|
346
|
+
sectionDispositions?: HandoffSectionDispositionInput[];
|
|
222
347
|
completenessAudit?: HandoffCompletenessAuditInput;
|
|
223
348
|
coldStartInventory?: HandoffColdStartInventoryInput;
|
|
224
349
|
supportingDocuments?: HandoffSupportingDocumentInput[];
|
|
350
|
+
/** The body exactly as the agent submitted it, before auto-externalization
|
|
351
|
+
* rewrote `content`. Set by PlanStore only when a rewrite happened, so the
|
|
352
|
+
* agent's own document links are still judged against what the agent wrote. */
|
|
353
|
+
submittedContent?: string;
|
|
225
354
|
/** Populated and verified by PlanStore before pure domain application. */
|
|
226
355
|
verifiedSupportingDocuments?: HandoffSupportingDocument[];
|
|
227
356
|
/** Content is kept in-memory only for cold-start coverage validation. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handoff-context.d.ts","sourceRoot":"","sources":["../src/handoff-context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,OAAO,EACP,wBAAwB,EACxB,wBAAwB,EACxB,8BAA8B,EAC9B,yBAAyB,EACzB,KAAK,EACL,IAAI,EACL,MAAM,aAAa,CAAC;AACrB,OAAO,EAAqB,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"handoff-context.d.ts","sourceRoot":"","sources":["../src/handoff-context.ts"],"names":[],"mappings":"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"}
|