@sema-agent/core 7.31.0 → 7.32.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/CHANGELOG.md +106 -0
- package/dist/agents/inherited-tool-pool.d.ts +28 -0
- package/dist/agents/inherited-tool-pool.js +15 -0
- package/dist/agents/list-agents-tool.d.ts +7 -0
- package/dist/agents/list-agents-tool.js +9 -2
- package/dist/agents/peer-session-drain.d.ts +2 -0
- package/dist/agents/peer-session-drain.js +1 -0
- package/dist/agents/send-message-tool.d.ts +17 -0
- package/dist/agents/send-message-tool.js +11 -4
- package/dist/agents/subagent.d.ts +10 -1
- package/dist/agents/subagent.js +24 -8
- package/dist/core/ask-origin.d.ts +15 -6
- package/dist/core/ask-origin.js +15 -9
- package/dist/core/background-shell.d.ts +45 -0
- package/dist/core/background-shell.js +13 -0
- package/dist/core/checkpoint-store.d.ts +5 -0
- package/dist/core/checkpoint-store.js +3 -2
- package/dist/core/engine-notice.d.ts +9 -0
- package/dist/core/gate-lanes.js +1 -1
- package/dist/core/governance-codes.d.ts +1 -1
- package/dist/core/governance-codes.js +5 -0
- package/dist/core/hooks.d.ts +2 -0
- package/dist/core/memory-engine/engine.d.ts +10 -1
- package/dist/core/memory-engine/engine.js +30 -6
- package/dist/core/memory-engine/file-backend.d.ts +15 -0
- package/dist/core/memory-engine/file-backend.js +53 -2
- package/dist/core/memory-engine/layout.d.ts +29 -4
- package/dist/core/memory-engine/layout.js +24 -4
- package/dist/core/read-root-grant-screen.d.ts +23 -0
- package/dist/core/read-root-grant-screen.js +17 -0
- package/dist/core/runner/contracts.d.ts +1 -1
- package/dist/core/runner/prepare-artifact.d.ts +12 -7
- package/dist/core/runner/prepare-artifact.js +10 -8
- package/dist/core/runner/prepare-ask-lane.d.ts +3 -0
- package/dist/core/runner/prepare-ask-lane.js +5 -1
- package/dist/core/runner/prepare-boundary-parks.js +5 -5
- package/dist/core/runner/prepare-delegation-surface.d.ts +18 -0
- package/dist/core/runner/prepare-delegation-surface.js +6 -25
- package/dist/core/runner/prepare-hands-readface.d.ts +12 -89
- package/dist/core/runner/prepare-hands-readface.js +14 -48
- package/dist/core/runner/prepare-inherited-gate.d.ts +3 -1
- package/dist/core/runner/prepare-inherited-gate.js +2 -1
- package/dist/core/runner/prepare-park-ask.js +6 -4
- package/dist/core/runner/prepare-policy-chain.js +4 -0
- package/dist/core/runner/prepare-task.js +5 -3
- package/dist/core/runner/read-root-grant.d.ts +66 -0
- package/dist/core/runner/read-root-grant.js +77 -0
- package/dist/core/runner/run-notification-lane.d.ts +1 -1
- package/dist/core/runner/run-settle-and-teardown.js +3 -9
- package/dist/core/runner/runtask.js +1 -1
- package/dist/core/runner/send-message-continuation.d.ts +45 -0
- package/dist/core/runner/send-message-continuation.js +27 -0
- package/dist/core/runner/session-read-file-states.d.ts +91 -0
- package/dist/core/runner/session-read-file-states.js +43 -0
- package/dist/core/secret-env.d.ts +1 -1
- package/dist/core/secret-env.js +7 -2
- package/dist/core/store-contracts/checkpoint-store-contract.d.ts +2 -0
- package/dist/core/store-contracts/checkpoint-store-contract.js +19 -0
- package/dist/core/task-registry-monitor.js +3 -0
- package/dist/core/task-registry-shared.d.ts +16 -3
- package/dist/core/task-registry.d.ts +65 -29
- package/dist/core/task-registry.js +78 -28
- package/dist/core/task-spec.d.ts +5 -3
- package/dist/core/tool-policy.d.ts +23 -0
- package/dist/core/tool-policy.js +15 -4
- package/dist/core/tool-spec.d.ts +2 -0
- package/dist/engine/execution-env/node-execution-env.d.ts +13 -3
- package/dist/engine/execution-env/node-execution-env.js +26 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.js +2 -1
- package/dist/scenarios/full-body.d.ts +5 -2
- package/dist/scenarios/full-body.js +14 -7
- package/dist/tools/fs/fs-bash-background-text.d.ts +16 -0
- package/dist/tools/fs/fs-bash-background-text.js +22 -0
- package/dist/tools/fs/fs-bash.d.ts +6 -0
- package/dist/tools/fs/fs-bash.js +9 -27
- package/dist/tools/fs/fs-read.d.ts +2 -2
- package/dist/tools/fs/fs-search-tools.d.ts +3 -2
- package/dist/tools/fs/index.d.ts +8 -1
- package/dist/tools/fs/index.js +2 -3
- package/dist/tools/fs/repo-map.d.ts +2 -1
- package/dist/tools/fs/safety.d.ts +3 -1
- package/dist/tools/fs/safety.js +2 -1
- package/dist/tools/fs/shell-read-check.d.ts +3 -0
- package/dist/tools/fs/shell-read-check.js +1 -1
- package/dist/tools/fs/shell-read-establish.d.ts +3 -1
- package/dist/tools/fs/shell-read-establish.js +2 -2
- package/dist/tools/fs/shell-read-plan.d.ts +2 -2
- package/dist/tools/fs/shell-read-plan.js +15 -10
- package/dist/tools/fs/shell-read-word.d.ts +5 -4
- package/dist/tools/fs/shell-read-word.js +3 -2
- package/dist/tools/monitor.d.ts +5 -4
- package/dist/tools/monitor.js +5 -4
- package/dist/tools/todo.d.ts +3 -3
- package/dist/tools/todo.js +5 -4
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +13 -1
- package/wire-changes/core@7.31.1.json +189 -0
- package/wire-changes/core@7.32.0.json +850 -0
|
@@ -145,14 +145,14 @@ export function establishShellReadsLexically(plan, boundary) {
|
|
|
145
145
|
}
|
|
146
146
|
return { plan, reads, nested, roots: boundary.roots };
|
|
147
147
|
}
|
|
148
|
-
export function createShellReadEstablisher(env, readRoots) {
|
|
148
|
+
export function createShellReadEstablisher(env, readRoots, opts) {
|
|
149
149
|
const lexicalOnly = boundaryIsTheSandbox(env);
|
|
150
150
|
const resolverIsAuthoritative = canonicalPathIsAuthoritative(env);
|
|
151
151
|
const family = pathFamilyOf({ root: readRoots[0] ?? "/" });
|
|
152
152
|
const SEP = family === "posix" ? /\// : /[\\/]/;
|
|
153
153
|
const TRAILING_SEP = family === "posix" ? /\/+$/ : /[\\/]+$/;
|
|
154
154
|
const joinUnder = (dir, name) => `${dir.replace(TRAILING_SEP, "")}/${name}`;
|
|
155
|
-
let rootsOnce;
|
|
155
|
+
let rootsOnce = opts?.rootsCanonical === true ? Promise.resolve(readRoots) : undefined;
|
|
156
156
|
const canonicalRoots = async (signal) => {
|
|
157
157
|
rootsOnce ??= (async () => {
|
|
158
158
|
const out = [];
|
|
@@ -62,8 +62,8 @@ export interface ReadCandidate {
|
|
|
62
62
|
* A deny row is a floor, so the judge resolves the spelling against these for deny rows ONLY — never to
|
|
63
63
|
* establish a read. `cd sub && cd $'\x2e' && cat <deny row under sub>` (bash: `cd .`) is refused through it. */
|
|
64
64
|
readonly floorBases?: readonly string[];
|
|
65
|
-
/** A home word the plan does not place (the text may rebind `HOME`,
|
|
66
|
-
*
|
|
65
|
+
/** A home word the plan does not place (the text may rebind `HOME`, it sits in a value, or it is a literal tilde the
|
|
66
|
+
* program may expand itself): spelled with the DECLARED home. The judge reads it for deny rows ONLY. */
|
|
67
67
|
readonly floorSpelled?: string;
|
|
68
68
|
/** A deny-floor shadow of a `floorSpelled` spelling, established as a read and judged for deny rows only. */
|
|
69
69
|
readonly denyOnly?: true;
|
|
@@ -193,7 +193,7 @@ function segmentFacts(segment, p, decl, home, nestedPlan) {
|
|
|
193
193
|
unresolvedRaw.add(w.raw);
|
|
194
194
|
}
|
|
195
195
|
const homeWithheld = home === undefined && decl.homeDir !== undefined;
|
|
196
|
-
const floor = (c) => { const f = c.expands === "unresolvable" && decl.homeDir !== undefined ? spelledWithHome(c.spelled, c.raw, decl.homeDir) : undefined; return f === undefined ? c : { ...c, floorSpelled: f }; };
|
|
196
|
+
const floor = (c) => { const f = (c.expands === "unresolvable" || c.spelled.startsWith("./~")) && decl.homeDir !== undefined ? spelledWithHome(c.spelled, c.raw, decl.homeDir) : undefined; return f === undefined ? c : { ...c, floorSpelled: f }; };
|
|
197
197
|
const unsettle = (c) => floor((unresolvedRaw.has(c.raw) || (homeWithheld && c.spelled.startsWith("~"))) && c.expands !== "unresolvable" ? { ...c, expands: "unresolvable" } : c);
|
|
198
198
|
const move = facts.baseMove;
|
|
199
199
|
return {
|
|
@@ -268,9 +268,8 @@ function segmentFactsRead(segment, p, decl, home, nestedPlan) {
|
|
|
268
268
|
const basename = program?.basename;
|
|
269
269
|
const listed = basename !== undefined && (decl.readers.has(basename) || basename === "cd");
|
|
270
270
|
const verb = program === undefined ? undefined : { name: program.name, basename: program.basename, listed };
|
|
271
|
-
const envOpens = basename !== undefined && !NO_PATH_OPERAND_COMMANDS.has(basename);
|
|
272
271
|
for (const k of pos.assignments)
|
|
273
|
-
pushAssignment(reads, toks[k].word, "env_assignment"
|
|
272
|
+
pushAssignment(reads, toks[k].word, "env_assignment");
|
|
274
273
|
for (const l of pos.launchers) {
|
|
275
274
|
const r = toks[l.index];
|
|
276
275
|
if (isPathShapedToken(r.folded))
|
|
@@ -313,7 +312,7 @@ function segmentFactsRead(segment, p, decl, home, nestedPlan) {
|
|
|
313
312
|
continue;
|
|
314
313
|
}
|
|
315
314
|
if (r.word.assignment !== undefined) {
|
|
316
|
-
pushAssignment(reads, r.word, "env_assignment"
|
|
315
|
+
pushAssignment(reads, r.word, "env_assignment");
|
|
317
316
|
continue;
|
|
318
317
|
}
|
|
319
318
|
reads.push(bare(r, "unlisted_word"));
|
|
@@ -462,7 +461,7 @@ function dedupe(reads) {
|
|
|
462
461
|
const seen = new Set();
|
|
463
462
|
const out = [];
|
|
464
463
|
for (const c of reads) {
|
|
465
|
-
const key = `${c.provenance}\u0000${c.spelled}\u0000${c.expands}\u0000${c.denyOnly === true}`;
|
|
464
|
+
const key = `${c.provenance}\u0000${c.spelled}\u0000${c.expands}\u0000${c.raw}\u0000${c.denyOnly === true}`;
|
|
466
465
|
if (seen.has(key))
|
|
467
466
|
continue;
|
|
468
467
|
seen.add(key);
|
|
@@ -488,7 +487,7 @@ function redirectFact(r, home) {
|
|
|
488
487
|
return { op: r.op, direction: "in" };
|
|
489
488
|
return { op: r.op, direction: "out", target: bare(readsOf([r.target], home)[0], "write_redirect_target") };
|
|
490
489
|
}
|
|
491
|
-
function pushAssignment(reads, w, provenance
|
|
490
|
+
function pushAssignment(reads, w, provenance) {
|
|
492
491
|
const a = w.assignment;
|
|
493
492
|
if (a === undefined)
|
|
494
493
|
return;
|
|
@@ -498,13 +497,19 @@ function pushAssignment(reads, w, provenance, opensValue = true) {
|
|
|
498
497
|
const named = a.value.folded === "" || (a.op === "+=" ? expandsTilde : !settled) ? undefined : value;
|
|
499
498
|
if (a.value.folded === "" && settled)
|
|
500
499
|
return;
|
|
501
|
-
const v = { spelled:
|
|
500
|
+
const v = { spelled: value, raw: a.bare ? a.value.raw : w.raw, provenance };
|
|
502
501
|
const unsettled = provenance !== "env_assignment" ? { ...v, expands: "unresolvable" } : v.spelled.startsWith("~") && !v.spelled.includes(":") ? { ...v, expands: expandsOf(a.value) } : undefined;
|
|
503
|
-
if (!settled &&
|
|
502
|
+
if (!settled && unsettled !== undefined)
|
|
504
503
|
reads.push(unsettled);
|
|
505
504
|
const substitutes = a.value.expansions.some((p) => p.expansion?.kind === "command" || p.expansion?.kind === "process" || p.expansion?.kind === "arithmetic");
|
|
506
505
|
if (named !== undefined && !substitutes)
|
|
507
506
|
reads.push({ spelled: named, raw: w.raw, provenance, expands: expandsOf(w) });
|
|
507
|
+
if (a.value.folded.includes(":"))
|
|
508
|
+
for (const m of a.value.folded.split(":"))
|
|
509
|
+
if (m !== "") {
|
|
510
|
+
const r = readOfText(m);
|
|
511
|
+
reads.push({ spelled: r.folded, raw: r.raw, provenance, expands: r.expands, denyOnly: true });
|
|
512
|
+
}
|
|
508
513
|
if (a.form === "compound")
|
|
509
514
|
for (const e of compoundArrayElements(a.value))
|
|
510
515
|
reads.push({ spelled: e.folded, raw: e.raw, provenance, expands: e.expands, ...(e.denyOnly === true ? { denyOnly: true } : {}) });
|
|
@@ -527,7 +532,7 @@ function unlistedWords(reads, toks, from, launcherIndices, provenance, program)
|
|
|
527
532
|
expanding.add(j);
|
|
528
533
|
reads.push(bare(toks[j], j === argvStart ? "program_path" : provenance));
|
|
529
534
|
if (j < argvStart)
|
|
530
|
-
pushAssignment(reads, toks[j].word, "env_assignment"
|
|
535
|
+
pushAssignment(reads, toks[j].word, "env_assignment");
|
|
531
536
|
else if (j > argvStart && !declaredNotPaths)
|
|
532
537
|
pushAssignment(reads, toks[j].word, provenance);
|
|
533
538
|
}
|
|
@@ -605,7 +610,7 @@ function unlistedWords(reads, toks, from, launcherIndices, provenance, program)
|
|
|
605
610
|
}
|
|
606
611
|
reads.push(bare(r, j === argvStart ? "program_path" : provenance));
|
|
607
612
|
if (j < argvStart)
|
|
608
|
-
pushAssignment(reads, r.word, "env_assignment"
|
|
613
|
+
pushAssignment(reads, r.word, "env_assignment");
|
|
609
614
|
else if (!declaredNotPaths)
|
|
610
615
|
pushAssignment(reads, r.word, provenance);
|
|
611
616
|
}
|
|
@@ -25,10 +25,11 @@ export declare function readsOf(words: readonly LexedWord[], home: string | unde
|
|
|
25
25
|
export declare const rewritten: (r: Read) => boolean;
|
|
26
26
|
/** The reading of a text that came out of a word (a sed script's file operand): one shell word, or unresolvable. */
|
|
27
27
|
export declare function readOfText(text: string): Read;
|
|
28
|
-
/** A home-rooted candidate spelled with `home`: a leading `~` / `~/`
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* the
|
|
28
|
+
/** A home-rooted candidate spelled with `home`: a leading `~` / `~/` — the shell's expansion, or the literal-tilde
|
|
29
|
+
* spelling `./~` of one it leaves alone (quoted, escaped, after an option's `=`), which the program it reaches may
|
|
30
|
+
* expand itself — or a `$HOME` / `${HOME}` word as {@link homeExpansionOf} reads it, read off the VALUE's pieces when
|
|
31
|
+
* the word is assignment-shaped (`A="$HOME/x"`, `dd if="$HOME/x"`: the candidate is the value, quotes kept);
|
|
32
|
+
* `undefined` for any other (`~user`, a word that is no home word). */
|
|
32
33
|
export declare function spelledWithHome(spelled: string, raw: string, home: string): string | undefined;
|
|
33
34
|
/** A function definition's head names nothing that runs here and is dropped from a segment's tokens, in place:
|
|
34
35
|
* `NAME ( )` (an identifier), and `function NAME [( )]` — a bare `function` at command position, a name of any
|
|
@@ -20,8 +20,9 @@ export function readOfText(text) {
|
|
|
20
20
|
return { word, raw: text, folded: text, expands: expandsOf(word) };
|
|
21
21
|
}
|
|
22
22
|
export function spelledWithHome(spelled, raw, home) {
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
const tilde = spelled.startsWith("./~") ? spelled.slice(2) : spelled;
|
|
24
|
+
if (tilde.startsWith("~"))
|
|
25
|
+
return /^~(?:\/|$)/.test(tilde) ? `${home}${tilde.slice(1)}` : undefined;
|
|
25
26
|
if (!raw.includes("HOME"))
|
|
26
27
|
return undefined;
|
|
27
28
|
const w = readOfText(raw).word;
|
package/dist/tools/monitor.d.ts
CHANGED
|
@@ -73,10 +73,11 @@ export interface MonitorToolOptions {
|
|
|
73
73
|
* spawns a shell command too, so what it runs is what the station judged, re-established before the watch
|
|
74
74
|
* spawns. Absent ⇒ no station judged this mount; nothing is re-established. */
|
|
75
75
|
shellReadAdmission?: ShellReadAdmission;
|
|
76
|
-
/** RB-465-b (HRD-PTL-3 残件): spec-level retain (`TaskSpec.retainBackgroundProcesses`) — the
|
|
77
|
-
* retain
|
|
78
|
-
*
|
|
79
|
-
*
|
|
76
|
+
/** RB-465-b (HRD-PTL-3 残件): spec-level retain (`TaskSpec.retainBackgroundProcesses`) — the task lane of
|
|
77
|
+
* THE retain predicate (`retainsBackgroundProcesses`), OR-composed with the env capability. Read twice,
|
|
78
|
+
* by the same predicate: the persistent-watch receipt's wording, and the row's `retained` mark at
|
|
79
|
+
* registration (so the session reap and the exit-boundary hard face judge the row the way the receipt
|
|
80
|
+
* described it). */
|
|
80
81
|
retainBackgroundProcesses?: boolean;
|
|
81
82
|
/** The task root in the SAME canonical spelling `createBashTool` is built with, so a dead-cwd self-heal
|
|
82
83
|
* lands both tools on one directory. Absent ⇒ the diagnosis says it has no reset target, rather than
|
package/dist/tools/monitor.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Type } from "typebox";
|
|
2
2
|
import { defineTool, errorResult } from "../core/tools.js";
|
|
3
|
-
import { hasBackgroundShell } from "../core/background-shell.js";
|
|
3
|
+
import { envDeclaresRetain, hasBackgroundShell, retainsBackgroundProcesses } from "../core/background-shell.js";
|
|
4
4
|
import { MONITOR_DEFAULT_TIMEOUT_MS, MONITOR_MAX_TIMEOUT_MS, } from "../core/task-registry.js";
|
|
5
5
|
import { toolFace } from "../core/tool-catalog-entries.js";
|
|
6
6
|
import { isDeadCwd, diagnoseDeadCwd } from "./fs/dead-cwd.js";
|
|
@@ -101,6 +101,7 @@ export function createMonitorTool(env, opts) {
|
|
|
101
101
|
persistent: isPersistent,
|
|
102
102
|
...(sessionScoped ? { sessionScoped: true } : {}),
|
|
103
103
|
...(isPersistent ? {} : { timeoutMs }),
|
|
104
|
+
...(opts.retainBackgroundProcesses !== undefined ? { retainBackgroundProcesses: opts.retainBackgroundProcesses } : {}),
|
|
104
105
|
...(onNotify !== undefined ? { onEvent: (n) => onNotify(n, { priority: "next" }) } : {}),
|
|
105
106
|
...(opts.timers !== undefined ? { timers: opts.timers } : {}),
|
|
106
107
|
...(opts.batchWindowMs !== undefined ? { batchWindowMs: opts.batchWindowMs } : {}),
|
|
@@ -135,12 +136,12 @@ export function createMonitorTool(env, opts) {
|
|
|
135
136
|
const persistentBudget = bgTimeout !== undefined
|
|
136
137
|
? `the execution environment's background time budget ends the watch after ${bgTimeout}s`
|
|
137
138
|
: `the execution environment's background time budget still applies`;
|
|
138
|
-
const retainedByEnv = env
|
|
139
|
+
const retainedByEnv = envDeclaresRetain(env);
|
|
139
140
|
const retainedBySpec = opts.retainBackgroundProcesses === true;
|
|
140
|
-
const retained = retainedByEnv
|
|
141
|
+
const retained = retainsBackgroundProcesses({ env: retainedByEnv, task: retainedBySpec });
|
|
141
142
|
const persistentAnchor = sessionScoped
|
|
142
143
|
? retained
|
|
143
|
-
? ". This run retains background processes (environment capability or task spec), so
|
|
144
|
+
? ". This run retains background processes (environment capability or task spec), so the watch is retained and " +
|
|
144
145
|
"survives the session's release: only your TaskStop, the command's own exit, or that budget end it."
|
|
145
146
|
: "; it runs until then, until you stop it, or until the session ends."
|
|
146
147
|
: retained
|
package/dist/tools/todo.d.ts
CHANGED
|
@@ -2,9 +2,9 @@ import type { ToolSpec } from "../core/types.js";
|
|
|
2
2
|
/**
|
|
3
3
|
* design/102 (K-8 CC full-body) — TodoWrite parity (CONTEXT leg). A private, in-task plan the model rewrites to
|
|
4
4
|
* track multi-step work. State lives in this factory's closure — FRESH per task (each `assembleCodeTools` call
|
|
5
|
-
* makes its own)
|
|
5
|
+
* makes its own), one list per calling session (`ctx.sessionId`; upstream keys it by agent, so an Agent child sharing
|
|
6
|
+
* the instance never replaces the leader's plan); nothing durable, no deps, no egress. `effect:"idempotent"` because
|
|
6
7
|
* re-sending the whole list is repeat-safe. Distinct from `present_plan` (that SUSPENDS for human review); this is
|
|
7
|
-
* the model's own scratch
|
|
8
|
-
* mounted default-on, so it stays INERT for non-full-body runs. (A later slice may project the list to the wire.)
|
|
8
|
+
* the model's own scratch, a RAW {@link ToolSpec} pushed via `spec.tools` — NOT mounted default-on (INERT elsewhere).
|
|
9
9
|
*/
|
|
10
10
|
export declare function createTodoWriteTool(): ToolSpec;
|
package/dist/tools/todo.js
CHANGED
|
@@ -2,7 +2,7 @@ import { Type } from "typebox";
|
|
|
2
2
|
import { errorResult } from "../core/tools.js";
|
|
3
3
|
import { toolFace } from "../core/tool-catalog-entries.js";
|
|
4
4
|
export function createTodoWriteTool() {
|
|
5
|
-
|
|
5
|
+
const lists = new Map();
|
|
6
6
|
return {
|
|
7
7
|
name: "TodoWrite",
|
|
8
8
|
...toolFace("todo-write"),
|
|
@@ -81,9 +81,10 @@ export function createTodoWriteTool() {
|
|
|
81
81
|
activeForm: Type.String({ minLength: 1, description: "Present-continuous form shown while in progress (e.g. \"Running the tests\")." }),
|
|
82
82
|
})),
|
|
83
83
|
}),
|
|
84
|
-
execute: (args) => {
|
|
84
|
+
execute: (args, ctx) => {
|
|
85
|
+
const key = ctx?.sessionId ?? "";
|
|
85
86
|
const shape = (t) => ({ content: t.content, status: t.status, activeForm: t.activeForm });
|
|
86
|
-
const oldTodos =
|
|
87
|
+
const oldTodos = (lists.get(key) ?? []).map(shape);
|
|
87
88
|
const written = args.todos;
|
|
88
89
|
for (let i = 0; i < written.length; i++) {
|
|
89
90
|
const activeForm = written[i].activeForm;
|
|
@@ -96,7 +97,7 @@ export function createTodoWriteTool() {
|
|
|
96
97
|
}
|
|
97
98
|
}
|
|
98
99
|
const allDone = written.every((t) => t.status === "completed");
|
|
99
|
-
|
|
100
|
+
lists.set(key, allDone ? [] : written);
|
|
100
101
|
const newTodos = written.map(shape);
|
|
101
102
|
const open = written.filter((t) => t.status !== "completed").length;
|
|
102
103
|
return {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_comment": "design/87 L3 — frozen public export surface of src/index.ts (name -> kind). DO NOT edit by hand to silence a red test. A removed/changed entry = a SemVer-BREAKING change; bump MAJOR and update this fixture in the SAME commit (design/87 §4.2 / §5.2). Regenerate via REGEN in test/export-surface.test.ts.",
|
|
3
3
|
"_tierComment": "#435 v1 — machine-readable layering of the public surface: stable = demonstrated by README.md / src/examples; internal = an `Internal`-marked name or a runner/engine deep-subtree declaration (the model seam src/engine/llm is excluded — it is the BYOM contract, not an engine internal); advanced = a supported export the front door does not walk you through. THIS IS AN INITIAL HEURISTIC, derived mechanically and expected to be refined ticket by ticket: no human reviewed these 1700+ entries one by one, and nothing here claims otherwise. Known bias: a short or English-word export name (ok, err, Result, Usage) can match ordinary prose in README.md and land `stable` on a coincidence. Every export MUST carry a tier — a new export with no row fails the gate in export-surface.test.ts.",
|
|
4
|
-
"count":
|
|
4
|
+
"count": 2484,
|
|
5
5
|
"exports": {
|
|
6
6
|
"A2ATaskState": "type",
|
|
7
7
|
"A2ATaskStateReversal": "type",
|
|
@@ -177,10 +177,12 @@
|
|
|
177
177
|
"BackgroundAgentStoreError": "class",
|
|
178
178
|
"BackgroundAgentUsage": "interface",
|
|
179
179
|
"BackgroundChildEvent": "interface",
|
|
180
|
+
"BackgroundHardKillOutcome": "type",
|
|
180
181
|
"BackgroundPoll": "interface",
|
|
181
182
|
"BackgroundShellCapability": "interface",
|
|
182
183
|
"BackgroundShellError": "class",
|
|
183
184
|
"BackgroundShellErrorCode": "type",
|
|
185
|
+
"BackgroundShellHardKillReceipt": "interface",
|
|
184
186
|
"BackgroundShellId": "type",
|
|
185
187
|
"BackgroundShellStatus": "type",
|
|
186
188
|
"BackgroundSpawnOptions": "type",
|
|
@@ -905,6 +907,7 @@
|
|
|
905
907
|
"PERMISSION_MODE_CLASSES": "variable",
|
|
906
908
|
"PERMISSION_RULE_SYNC_PATH": "variable",
|
|
907
909
|
"PERMISSION_RULE_WRITER": "variable",
|
|
910
|
+
"PERSISTED_RULE_MANDATES": "variable",
|
|
908
911
|
"PLAN_SYSTEM_PROMPT": "variable",
|
|
909
912
|
"PLAN_WHEN_TO_USE": "variable",
|
|
910
913
|
"PREFIX_INPUT_CLASSIFICATION": "variable",
|
|
@@ -1013,6 +1016,7 @@
|
|
|
1013
1016
|
"PersistedRuleCoverage": "interface",
|
|
1014
1017
|
"PersistedRuleHit": "interface",
|
|
1015
1018
|
"PersistedRuleHitRule": "interface",
|
|
1019
|
+
"PersistedRuleMandate": "type",
|
|
1016
1020
|
"PersistedRuleMatch": "type",
|
|
1017
1021
|
"PersistedRuleTool": "type",
|
|
1018
1022
|
"PersistedRuleUnreadable": "interface",
|
|
@@ -1131,6 +1135,7 @@
|
|
|
1131
1135
|
"ReadOnlyFlagArity": "type",
|
|
1132
1136
|
"ReadOnlyShellVerdict": "type",
|
|
1133
1137
|
"ReadRootGrantCandidate": "interface",
|
|
1138
|
+
"ReadRootGrantScreen": "type",
|
|
1134
1139
|
"RealApprovalGateBit": "interface",
|
|
1135
1140
|
"ReasoningFormat": "type",
|
|
1136
1141
|
"ReasoningIntensity": "type",
|
|
@@ -2056,6 +2061,7 @@
|
|
|
2056
2061
|
"isPeerSessionId": "function",
|
|
2057
2062
|
"isPeerSessionProcessAlive": "function",
|
|
2058
2063
|
"isPermissionModeClass": "function",
|
|
2064
|
+
"isPersistedRuleMandate": "function",
|
|
2059
2065
|
"isPersonalScope": "function",
|
|
2060
2066
|
"isProcessLive": "function",
|
|
2061
2067
|
"isProtectedWrite": "function",
|
|
@@ -2657,10 +2663,12 @@
|
|
|
2657
2663
|
"BackgroundAgentStoreError": "advanced",
|
|
2658
2664
|
"BackgroundAgentUsage": "advanced",
|
|
2659
2665
|
"BackgroundChildEvent": "advanced",
|
|
2666
|
+
"BackgroundHardKillOutcome": "advanced",
|
|
2660
2667
|
"BackgroundPoll": "advanced",
|
|
2661
2668
|
"BackgroundShellCapability": "advanced",
|
|
2662
2669
|
"BackgroundShellError": "advanced",
|
|
2663
2670
|
"BackgroundShellErrorCode": "advanced",
|
|
2671
|
+
"BackgroundShellHardKillReceipt": "advanced",
|
|
2664
2672
|
"BackgroundShellId": "advanced",
|
|
2665
2673
|
"BackgroundShellStatus": "advanced",
|
|
2666
2674
|
"BackgroundSpawnOptions": "advanced",
|
|
@@ -3385,6 +3393,7 @@
|
|
|
3385
3393
|
"PERMISSION_MODE_CLASSES": "advanced",
|
|
3386
3394
|
"PERMISSION_RULE_SYNC_PATH": "advanced",
|
|
3387
3395
|
"PERMISSION_RULE_WRITER": "advanced",
|
|
3396
|
+
"PERSISTED_RULE_MANDATES": "advanced",
|
|
3388
3397
|
"PLAN_SYSTEM_PROMPT": "advanced",
|
|
3389
3398
|
"PLAN_WHEN_TO_USE": "advanced",
|
|
3390
3399
|
"PREFIX_INPUT_CLASSIFICATION": "advanced",
|
|
@@ -3493,6 +3502,7 @@
|
|
|
3493
3502
|
"PersistedRuleCoverage": "advanced",
|
|
3494
3503
|
"PersistedRuleHit": "advanced",
|
|
3495
3504
|
"PersistedRuleHitRule": "advanced",
|
|
3505
|
+
"PersistedRuleMandate": "advanced",
|
|
3496
3506
|
"PersistedRuleMatch": "advanced",
|
|
3497
3507
|
"PersistedRuleTool": "advanced",
|
|
3498
3508
|
"PersistedRuleUnreadable": "advanced",
|
|
@@ -3611,6 +3621,7 @@
|
|
|
3611
3621
|
"ReadOnlyFlagArity": "advanced",
|
|
3612
3622
|
"ReadOnlyShellVerdict": "advanced",
|
|
3613
3623
|
"ReadRootGrantCandidate": "advanced",
|
|
3624
|
+
"ReadRootGrantScreen": "advanced",
|
|
3614
3625
|
"RealApprovalGateBit": "advanced",
|
|
3615
3626
|
"ReasoningFormat": "advanced",
|
|
3616
3627
|
"ReasoningIntensity": "advanced",
|
|
@@ -4536,6 +4547,7 @@
|
|
|
4536
4547
|
"isPeerSessionId": "advanced",
|
|
4537
4548
|
"isPeerSessionProcessAlive": "advanced",
|
|
4538
4549
|
"isPermissionModeClass": "advanced",
|
|
4550
|
+
"isPersistedRuleMandate": "advanced",
|
|
4539
4551
|
"isPersonalScope": "advanced",
|
|
4540
4552
|
"isProcessLive": "advanced",
|
|
4541
4553
|
"isProtectedWrite": "advanced",
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
{
|
|
2
|
+
"repo": "core",
|
|
3
|
+
"version": "7.31.1",
|
|
4
|
+
"from": "289b2d1998a3e890f6a8659ffc4397074ddd720a",
|
|
5
|
+
"to": "v7.31.1",
|
|
6
|
+
"added": [],
|
|
7
|
+
"removed": [],
|
|
8
|
+
"changed": [],
|
|
9
|
+
"narrowed": [
|
|
10
|
+
{
|
|
11
|
+
"id": "F1",
|
|
12
|
+
"source": "behaviorFlips.summary",
|
|
13
|
+
"text": "NARROWING (#1094, memory store; +1 error code `memory.target_outside_store`, registered in `NON_GOVERNANCE_MEMORY_CODES`; +0 exports, +0 wire keys): an act at a memory store path is judged by where it LANDS, not by how it is spelled. One verdict — the target's DIRECTORY, resolved through every link on its existing prefix, must be the store root's physical form or inside it (the final component is not judged: the backend's `rm` removes a link standing there and `rename` replaces it, the engine's in-place writes refuse it with `ELOOP` — none follows it) — gates `FileMemoryEngineBackend.applyPatches` (per op at staging, the whole batch at the commit point, per op at each act), erasure (`MemoryEngine.eraseMemoryEntries`: commit point and act), journal replay (the whole journal before its first act, each op again at its act), and the engine's own writes at store paths: the copy-out projection, the harvest's missing-file restore, the read-only layer restore and the `MEMORY.md` index writes. The backend takes its root's physical form when it opens the store and re-checks it at the head of every face; the engine takes its memory dir's physical form at its first mount and a later mount that resolves elsewhere is refused. Separately, the engine's in-place write refuses a file with more than one name (a hard link), before anything is truncated. A refused `applyPatches` / erasure throws a plain `Error` whose `.code` is the new code — before the commit marker nothing is written and no journal is left, after it the journal is kept and replays once the path resolves inside again; a refused mount throws the code; a refused restore or index write is not performed and is reported on `HarvestReport.warnings` (or `incident.detail`) with the code, a hard-link refusal names the file. WHO IS HURT: a deployment whose store holds a directory link under its root, or a hard-linked memory file — the act that used to follow it is refused until it is removed. Known limits KL-1094-a … i."
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"id": "F2",
|
|
17
|
+
"source": "behaviorFlips.summary",
|
|
18
|
+
"text": "NARROWING (#1099, spawned-environment scrub; `SecretEnvFindingKind` +1 member `namespace-rule`, confidence `medium`; +0 exports, +0 wire keys): inside the host shell's `SEMA_` namespace, and only there, a credential word as ANY `_`-separated segment makes the name a credential (`SEMA_NAMESPACE_SECRET_RE`, over the one `CREDENTIAL_WORD` alternation the suffix rule reads, the count-word reading of `TOKENS` included) — so `SEMA_MODEL_KEY_<ENTRY>`, `SEMA_WEBSEARCH_KEY_<PROVIDER>` and `SEMA_REGISTRY_TOKEN_FILE` no longer reach a tool's child shell or a language server, and the one `config.secret_env_scrubbed` notice lists them in `detail.names`. The rule is consulted after the two exact-name lists and the suffix rule, so no existing finding changes kind, and every name outside `SEMA_` keeps its v7.31.0 verdict and kind. WHO IS HURT: a `SEMA_` name with a credential-word segment that a child needed (`SEMA_REGISTRY_TOKEN_FILE`, `SEMA_LLM_KEY_DB`, six `SEMA_CODE_*` knobs a nested `sema` reads); an `inheritEnv` allowlist, `shellEnv` / a per-exec env and a host-supplied LSP `env` still pass a name verbatim."
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"id": "F3",
|
|
22
|
+
"source": "behaviorFlips.summary",
|
|
23
|
+
"text": "NARROWING (#1100, shell read boundary; tightening only — no verdict loosens against 7.31.0; +0 exports, +0 wire keys; supersedes #1004's no-opener ruling for tilde values): three rules on one mechanism, the declared-home deny floor. (1) The opener condition leaves the assignment-value reading: an environment value with a leading tilde is placed against the declared home whether or not a program opens it, so `F=~/<deny row>; cat \"$F\"` meets the deny judge exactly as its `$HOME` and literal spellings already did. (2) A LITERAL tilde (quoted, escaped, after an option's `=`) — a relative `./~…` path to bash, but a program such as npm expands it itself — also carries its declared-home spelling as a deny-only view: refused on a deny row, never a containment question. (3) Each member of a `:` list meets the deny rows (a tilde member placed against the home); the whole value is still no containment candidate. Where no deny row is hit nothing changes. WHO IS HURT: a text whose value or literal-tilde operand names a deny row under the declared home and is never read that way is refused, as its `$HOME` and literal spellings already were (KL-1100a / KL-1100b)."
|
|
24
|
+
}
|
|
25
|
+
],
|
|
26
|
+
"closedSetMembers": [
|
|
27
|
+
{
|
|
28
|
+
"set": "SecretEnvFindingKind",
|
|
29
|
+
"at": [
|
|
30
|
+
"src/core/secret-env.ts:181"
|
|
31
|
+
],
|
|
32
|
+
"newSet": false,
|
|
33
|
+
"added": [
|
|
34
|
+
"namespace-rule"
|
|
35
|
+
],
|
|
36
|
+
"removed": [],
|
|
37
|
+
"breaking": false,
|
|
38
|
+
"criteriaCovered": false
|
|
39
|
+
}
|
|
40
|
+
],
|
|
41
|
+
"closedSetsUnreadable": [],
|
|
42
|
+
"typeKeys": [],
|
|
43
|
+
"typeKeysUnreadableArms": [],
|
|
44
|
+
"typeKeysFlattenedCount": 216,
|
|
45
|
+
"declarationMoves": [],
|
|
46
|
+
"mintMoves": [],
|
|
47
|
+
"criteriaObserves": [
|
|
48
|
+
{
|
|
49
|
+
"kind": "engineNoticeCode",
|
|
50
|
+
"name": "config.secret_env_scrubbed",
|
|
51
|
+
"assertions": [
|
|
52
|
+
"G2.a"
|
|
53
|
+
]
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"kind": "typeMember",
|
|
57
|
+
"name": "AskRequest.mandated",
|
|
58
|
+
"assertions": [
|
|
59
|
+
"G3.a",
|
|
60
|
+
"G3.b"
|
|
61
|
+
]
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"kind": "typeMember",
|
|
65
|
+
"name": "EngineNotice.detail",
|
|
66
|
+
"assertions": [
|
|
67
|
+
"G2.a"
|
|
68
|
+
]
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"kind": "typeMember",
|
|
72
|
+
"name": "FileMemoryEngineBackend.applyPatches",
|
|
73
|
+
"assertions": [
|
|
74
|
+
"G1.a"
|
|
75
|
+
]
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"kind": "typeMember",
|
|
79
|
+
"name": "HarvestReport.incident",
|
|
80
|
+
"assertions": [
|
|
81
|
+
"G1.a"
|
|
82
|
+
]
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"kind": "typeMember",
|
|
86
|
+
"name": "HarvestReport.ok",
|
|
87
|
+
"assertions": [
|
|
88
|
+
"G1.b"
|
|
89
|
+
]
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"kind": "typeMember",
|
|
93
|
+
"name": "HarvestReport.restored",
|
|
94
|
+
"assertions": [
|
|
95
|
+
"G1.a",
|
|
96
|
+
"G1.b"
|
|
97
|
+
]
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"kind": "typeMember",
|
|
101
|
+
"name": "HarvestReport.warnings",
|
|
102
|
+
"assertions": [
|
|
103
|
+
"G1.a"
|
|
104
|
+
]
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"kind": "typeMember",
|
|
108
|
+
"name": "MemoryEngine.eraseMemoryEntries",
|
|
109
|
+
"assertions": [
|
|
110
|
+
"G1.a"
|
|
111
|
+
]
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"kind": "typeMember",
|
|
115
|
+
"name": "MemoryEngine.materialize",
|
|
116
|
+
"assertions": [
|
|
117
|
+
"G1.a"
|
|
118
|
+
]
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"kind": "typeMember",
|
|
122
|
+
"name": "MemoryErasureAttestation.status",
|
|
123
|
+
"assertions": [
|
|
124
|
+
"G1.b"
|
|
125
|
+
]
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"kind": "typeMember",
|
|
129
|
+
"name": "PatchReport.applied",
|
|
130
|
+
"assertions": [
|
|
131
|
+
"G1.b"
|
|
132
|
+
]
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"kind": "typeMember",
|
|
136
|
+
"name": "SecretEnvFinding.confidence",
|
|
137
|
+
"assertions": [
|
|
138
|
+
"G2.a"
|
|
139
|
+
]
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
"kind": "typeMember",
|
|
143
|
+
"name": "SecretEnvFinding.key",
|
|
144
|
+
"assertions": [
|
|
145
|
+
"G2.b"
|
|
146
|
+
]
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"kind": "typeMember",
|
|
150
|
+
"name": "SecretEnvFinding.kind",
|
|
151
|
+
"assertions": [
|
|
152
|
+
"G2.a",
|
|
153
|
+
"G2.b"
|
|
154
|
+
]
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
"kind": "typeMember",
|
|
158
|
+
"name": "ShellReadVerdict.disposition",
|
|
159
|
+
"assertions": [
|
|
160
|
+
"G3.a",
|
|
161
|
+
"G3.b"
|
|
162
|
+
]
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"kind": "typeMember",
|
|
166
|
+
"name": "ShellReadVerdict.finding",
|
|
167
|
+
"assertions": [
|
|
168
|
+
"G3.a",
|
|
169
|
+
"G3.b"
|
|
170
|
+
]
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
"kind": "typeMember",
|
|
174
|
+
"name": "ShellReadVerdict.readRootCandidate",
|
|
175
|
+
"assertions": [
|
|
176
|
+
"G3.b"
|
|
177
|
+
]
|
|
178
|
+
}
|
|
179
|
+
],
|
|
180
|
+
"consumersHint": {
|
|
181
|
+
"cli": [],
|
|
182
|
+
"server": [],
|
|
183
|
+
"sdk": [],
|
|
184
|
+
"note": "scanned cli@4e593722 server@c60beebe sdk@a9440f2 — a name listed is MENTIONED there today, which is evidence of consumption, not proof of it. Ledger files (**/docs/core-consumption/**, **/docs/wire-consumption/**, **/*LEDGER*.json) are not evidence of use — server: 1 name(s) matched ONLY in bookkeeping files and were set aside (SecretEnvFindingKind)"
|
|
185
|
+
},
|
|
186
|
+
"breakingCount": 0,
|
|
187
|
+
"breakingItems": [],
|
|
188
|
+
"toResolvedAt": "c7c5484e2ab1b4abcba1297de62424e71306e66c"
|
|
189
|
+
}
|