@sema-agent/core 7.30.1 → 7.31.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/CHANGELOG.md +284 -0
- package/dist/agents/cross-session-judge.d.ts +4 -12
- package/dist/agents/cross-session-judge.js +4 -11
- package/dist/agents/peer-session-drain.js +0 -5
- package/dist/agents/send-message-tool.js +1 -0
- package/dist/agents/subagent.d.ts +1 -0
- package/dist/agents/subagent.js +1 -0
- package/dist/core/ask-origin.d.ts +6 -0
- package/dist/core/ask-origin.js +10 -0
- package/dist/core/checkpoint-store.d.ts +14 -0
- package/dist/core/checkpoint-store.js +1 -0
- package/dist/core/engine-notice.d.ts +4 -0
- package/dist/core/governance-codes.d.ts +1 -1
- package/dist/core/governance-codes.js +4 -0
- package/dist/core/memory-engine/data-plane.d.ts +3 -1
- package/dist/core/memory-engine/data-plane.js +1 -1
- package/dist/core/memory-engine/delegation-settlement.d.ts +44 -3
- package/dist/core/memory-engine/delegation-settlement.js +38 -3
- package/dist/core/memory-engine/engine.d.ts +133 -27
- package/dist/core/memory-engine/engine.js +452 -151
- package/dist/core/memory-engine/entry-scan.d.ts +23 -0
- package/dist/core/memory-engine/entry-scan.js +55 -0
- package/dist/core/memory-engine/file-backend.d.ts +31 -23
- package/dist/core/memory-engine/file-backend.js +174 -100
- package/dist/core/memory-engine/layer-observations.d.ts +109 -0
- package/dist/core/memory-engine/layer-observations.js +148 -0
- package/dist/core/memory-engine/layout.d.ts +40 -4
- package/dist/core/memory-engine/layout.js +43 -7
- package/dist/core/memory-engine/types.d.ts +26 -2
- package/dist/core/parent-spec-seat.d.ts +4 -1
- package/dist/core/parent-spec-seat.js +2 -0
- package/dist/core/park-selfcheck.js +1 -0
- package/dist/core/runner/announce-once-ledger.d.ts +26 -0
- package/dist/core/runner/announce-once-ledger.js +37 -0
- package/dist/core/runner/contracts.d.ts +22 -5
- package/dist/core/runner/denial-limit-arms.d.ts +2 -2
- package/dist/core/runner/prepare-acquire-reconcile.d.ts +0 -4
- package/dist/core/runner/prepare-acquire-reconcile.js +1 -3
- package/dist/core/runner/prepare-file-history.d.ts +13 -15
- package/dist/core/runner/prepare-file-history.js +57 -43
- package/dist/core/runner/prepare-hands-readface.d.ts +2 -2
- package/dist/core/runner/prepare-listings.d.ts +3 -1
- package/dist/core/runner/prepare-listings.js +2 -2
- package/dist/core/runner/prepare-memory.js +16 -5
- package/dist/core/runner/prepare-park-ask.js +27 -16
- package/dist/core/runner/prepare-prompt-inputs.d.ts +8 -1
- package/dist/core/runner/prepare-prompt-inputs.js +5 -3
- package/dist/core/runner/prepare-task.js +7 -5
- package/dist/core/runner/prepare-wiring-manifest.d.ts +1 -0
- package/dist/core/runner/prepare-wiring-manifest.js +2 -1
- package/dist/core/runner/run-attachment-seats.js +1 -1
- package/dist/core/runner/run-leg.js +61 -52
- package/dist/core/runner/run-settle-and-teardown.js +4 -0
- package/dist/core/runner/run-turn-boundary.js +6 -6
- package/dist/core/runner/turn-attachments.d.ts +6 -6
- package/dist/core/runner-deps.d.ts +3 -1
- package/dist/core/secret-env.d.ts +12 -1
- package/dist/core/secret-env.js +27 -2
- package/dist/core/store-contracts/checkpoint-store-contract.d.ts +2 -0
- package/dist/core/store-contracts/checkpoint-store-contract.js +22 -0
- package/dist/core/task-result.d.ts +1 -1
- package/dist/core/task-spec.d.ts +17 -8
- package/dist/core/tool-spec.d.ts +1 -1
- package/dist/core/wiring-manifest.d.ts +10 -0
- package/dist/core/wiring-manifest.js +7 -1
- package/dist/engine/execution-env/node-execution-env.d.ts +6 -0
- package/dist/engine/execution-env/node-execution-env.js +15 -17
- package/dist/engine/harness/agent-harness.js +7 -5
- package/dist/engine/lsp/node-lsp-manager.d.ts +4 -0
- package/dist/engine/lsp/node-lsp-manager.js +10 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- 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/package.json +1 -1
- package/test/export-surface.snapshot.json +7 -1
- package/wire-changes/core@7.31.0.json +705 -0
- package/wire-changes/core@7.31.1.json +189 -0
package/dist/core/task-spec.d.ts
CHANGED
|
@@ -213,12 +213,12 @@ export interface TaskSpec {
|
|
|
213
213
|
* that could support this without a second root is a recorded design candidate, not built.)
|
|
214
214
|
*
|
|
215
215
|
* File-history interaction (design/381): with {@link restoreFiles}, the `"before"` file anchor is the
|
|
216
|
-
* target's OWN entry id
|
|
217
|
-
*
|
|
218
|
-
*
|
|
219
|
-
*
|
|
220
|
-
*
|
|
221
|
-
*
|
|
216
|
+
* target's OWN entry id — history boundaries are keyed by a turn's initial entry and mean "file state
|
|
217
|
+
* when that turn began", so B(target) IS the before-state. A target with no boundary of its own (a
|
|
218
|
+
* steer / follow-up entry, a turn that recorded no history, a mixed-epoch session) refuses at prepare
|
|
219
|
+
* (`rewind_snapshot.unresolvable`) with the files untouched: an earlier boundary would also revert edits
|
|
220
|
+
* the conversation keeps, so the anchor never falls back to an ancestor and never crosses into an
|
|
221
|
+
* earlier turn.
|
|
222
222
|
* Fail-loud: setting this without {@link resumeAt}, or an unknown mode value, rejects at prepare.
|
|
223
223
|
*/
|
|
224
224
|
resumeAtMode?: "at" | "before";
|
|
@@ -311,6 +311,15 @@ export interface TaskSpec {
|
|
|
311
311
|
count?: number;
|
|
312
312
|
role?: ModelRole;
|
|
313
313
|
};
|
|
314
|
+
/**
|
|
315
|
+
* The per-run OFF SWITCH for file history (`"disabled"`, the only word; `checkpointStore`'s spelling). Omitted ⇒
|
|
316
|
+
* the deployment (`RunnerDeps.fileHistoryStore` / `fileHistoryCapture`) decides. `"disabled"` ⇒ this run makes no history-store call: no first-touch record
|
|
317
|
+
* (the edit proceeds), no turn boundary, no fork carry, no liveness advisory; a restore request ({@link restoreFiles}
|
|
318
|
+
* / {@link rewindFilesTo}) refuses `rewind.capture_disabled` (the store may be wired; the request turned it off).
|
|
319
|
+
* The manifest reports `fileHistory: "disabled"`. Children inherit it (parent spec seat; a retained child woken by
|
|
320
|
+
* such a run, for that cycle); no word turns it back on below. Any other value refuses (`rewind.invalid_spec`).
|
|
321
|
+
*/
|
|
322
|
+
fileHistory?: "disabled";
|
|
314
323
|
/**
|
|
315
324
|
* design/381 (DV-9) — the RESTORE half of file rewind: when this task uses {@link resumeAt} to branch at
|
|
316
325
|
* a prior entry, ALSO converge the working tree's **agent-edited files** (the tracked set — files this
|
|
@@ -323,8 +332,8 @@ export interface TaskSpec {
|
|
|
323
332
|
* Fail-loud: setting this without {@link resumeAt} rejects at prepare (`rewind.invalid_spec`) — a
|
|
324
333
|
* restore with no anchor is a contradiction, not a default.
|
|
325
334
|
*
|
|
326
|
-
* There is NO capture
|
|
327
|
-
* `RunnerDeps.
|
|
335
|
+
* There is NO capture request anymore: first-touch tracking is ON whenever a `RunnerDeps.fileHistoryStore`
|
|
336
|
+
* is wired, `RunnerDeps.fileHistoryCapture` is not `"off"`, and no {@link fileHistory} off switch is set (per-edited-file backups are near-zero cost — no tree walk,
|
|
328
337
|
* no size gate), which is what retired the old `rewindFiles` capture request. The retired
|
|
329
338
|
* `rewindFiles` spelling is handled at prepare: its capture sense (true, no `resumeAt`) is a
|
|
330
339
|
* tolerated no-op with a deprecation disclosure (the intent is structurally satisfied); its restore
|
package/dist/core/tool-spec.d.ts
CHANGED
|
@@ -752,7 +752,7 @@ export interface ToolExecuteContext {
|
|
|
752
752
|
parentCwd?: string;
|
|
753
753
|
/**
|
|
754
754
|
* The RUNNING task's file-history LINEAGE (Runner-filled, read-only, never a model/tool argument;
|
|
755
|
-
* present iff a `RunnerDeps.fileHistoryStore`
|
|
755
|
+
* present iff the run records file history — a `RunnerDeps.fileHistoryStore` wired, capture not `"off"`, not `"disabled"`): the history scope this run
|
|
756
756
|
* records its first-touch edits into and the TREE those records' keys are minted against — the
|
|
757
757
|
* canonical root spelling plus the env's filesystem identity (`fs`: a remote workspace's handle,
|
|
758
758
|
* `"host"` for the control-plane host's filesystem, else a per-env-instance token).
|
|
@@ -407,6 +407,14 @@ export interface WiringManifest {
|
|
|
407
407
|
autoConsolidation?: {
|
|
408
408
|
onRecommendation: true;
|
|
409
409
|
};
|
|
410
|
+
/**
|
|
411
|
+
* EFFECTIVE half only, ALWAYS present on an engine-minted effective manifest: does this leg capture file history.
|
|
412
|
+
* `"on"` — it records (store wired, neither layer declared it off, a filesystem env mounted). `"disabled"` — it does
|
|
413
|
+
* not, whichever layer or missing half made it so (`TaskSpec.fileHistory`, `RunnerDeps.fileHistoryStore: "disabled"`, `RunnerDeps.fileHistoryCapture: "off"`,
|
|
414
|
+
* no store, no filesystem env); the host knows its own deployment seat. ABSENT = an older mint or an external
|
|
415
|
+
* derivation, never a state. Out of {@link configFingerprint}: the request word is a per-task seat (`hooks` reasoning).
|
|
416
|
+
*/
|
|
417
|
+
fileHistory?: "on" | "disabled";
|
|
410
418
|
/** EFFECTIVE half only — a short, non-sensitive fingerprint (sha256 prefix over the canonical
|
|
411
419
|
* JSON of this manifest's own resolved facts; every field here is an enum/boolean/count, no
|
|
412
420
|
* secrets) so an operator can correlate legs that ran under the same resolved assembly. */
|
|
@@ -498,6 +506,8 @@ export interface WiringFacts {
|
|
|
498
506
|
/** Effective half only — `RunnerDeps.autoRunOnRecommendation === true`
|
|
499
507
|
* ({@link WiringManifest.autoConsolidation}); false ⇒ no section (byte-identical manifest). */
|
|
500
508
|
autoConsolidationOnRecommendation?: boolean;
|
|
509
|
+
/** Effective half only — the file-history phase's word ({@link WiringManifest.fileHistory}); the engine always passes it. */
|
|
510
|
+
fileHistory?: "on" | "disabled";
|
|
501
511
|
}
|
|
502
512
|
/** Named view of the deps seats the static half reads (a `Pick` of the real {@link RunnerDeps} —
|
|
503
513
|
* single-source shapes, no parallel hand-copied interface). */
|
|
@@ -84,6 +84,11 @@ function readAutoModeFact(fact) {
|
|
|
84
84
|
}
|
|
85
85
|
return { armed, reason, ...(deniedSource !== undefined ? { deniedSource } : {}) };
|
|
86
86
|
}
|
|
87
|
+
function readFileHistoryFact(word) {
|
|
88
|
+
if (word !== "on" && word !== "disabled")
|
|
89
|
+
throw new Error(`the file-history wiring fact ${JSON.stringify(word)} is not one of on|disabled`);
|
|
90
|
+
return word;
|
|
91
|
+
}
|
|
87
92
|
export function deriveWiringManifest(facts) {
|
|
88
93
|
if (facts.half === "static" && facts.leg !== undefined) {
|
|
89
94
|
throw new Error("a static wiring manifest has no leg — leg identity is an effective-half fact");
|
|
@@ -146,13 +151,14 @@ export function deriveWiringManifest(facts) {
|
|
|
146
151
|
? { readDeny: { builtinTiers: [...facts.readDenyBuiltinTiersActive] } }
|
|
147
152
|
: {}),
|
|
148
153
|
...(facts.half === "effective" && facts.autoConsolidationOnRecommendation === true ? { autoConsolidation: { onRecommendation: true } } : {}),
|
|
154
|
+
...(facts.half === "effective" && facts.fileHistory !== undefined ? { fileHistory: readFileHistoryFact(facts.fileHistory) } : {}),
|
|
149
155
|
...(facts.half === "effective" && facts.teamRole !== undefined ? { teamRole: facts.teamRole } : {}),
|
|
150
156
|
...(facts.half === "effective" && facts.peerPresence !== undefined && (facts.peerPresence.agent !== undefined || facts.peerPresence.intent !== undefined)
|
|
151
157
|
? { peerPresence: { ...(facts.peerPresence.agent !== undefined ? { agent: facts.peerPresence.agent } : {}), ...(facts.peerPresence.intent !== undefined ? { intent: facts.peerPresence.intent } : {}) } }
|
|
152
158
|
: {}),
|
|
153
159
|
};
|
|
154
160
|
if (facts.half === "effective") {
|
|
155
|
-
const { leg: _leg, mcp: _mcp, tools: _tools, lsp: _lsp, hooks: _hooks, teamRole: _teamRole, peerPresence: _peerPresence, ...assembly } = manifest;
|
|
161
|
+
const { leg: _leg, mcp: _mcp, tools: _tools, lsp: _lsp, hooks: _hooks, teamRole: _teamRole, peerPresence: _peerPresence, fileHistory: _fileHistory, ...assembly } = manifest;
|
|
156
162
|
const { provenance: _askSeat, ...askForHash } = assembly.ask;
|
|
157
163
|
const { provenance: _questionSeat, ...questionForHash } = assembly.question;
|
|
158
164
|
manifest.configFingerprint = createHash("sha256")
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type ExecResult, type ExecutionEnv, ExecutionError, type ExecutionEnvExecOptions, FileError, type FileInfo, type Result } from "../harness/types.js";
|
|
2
2
|
import { type SecretEnvFinding } from "../../core/secret-env.js";
|
|
3
|
+
import type { EngineNotice } from "../../core/engine-notice.js";
|
|
3
4
|
import type { SymlinkChain } from "../harness/types.js";
|
|
4
5
|
import type { BackgroundShellCapability, BackgroundShellId, BackgroundPoll, BackgroundSpawnOptions } from "../../core/background-shell.js";
|
|
5
6
|
import { BackgroundShellError } from "../../core/background-shell.js";
|
|
@@ -106,6 +107,7 @@ export declare class NodeExecutionEnv implements ExecutionEnv, BackgroundShellCa
|
|
|
106
107
|
private bgCounter;
|
|
107
108
|
private readonly retainBackgroundProcesses;
|
|
108
109
|
private readonly onSecretEnvScrub?;
|
|
110
|
+
private readonly onNotice?;
|
|
109
111
|
/** design/128 T1-1: lazily-created env-owned spool dir (mkdtemp under os tmp — unpredictable, never the cwd). */
|
|
110
112
|
private bgSpoolDir?;
|
|
111
113
|
readonly backgroundCapabilities: BackgroundShellCapability["backgroundCapabilities"];
|
|
@@ -135,6 +137,10 @@ export declare class NodeExecutionEnv implements ExecutionEnv, BackgroundShellCa
|
|
|
135
137
|
* "scrub" leg withholds from a shell child. Absent ⇒ a once-per-process console summary (loud
|
|
136
138
|
* enough to notice, quiet enough not to spam). Never called on the "all"/allowlist legs. */
|
|
137
139
|
onSecretEnvScrub?: (findings: readonly SecretEnvFinding[]) => void;
|
|
140
|
+
/** #1081 — the structured-notice seat for the SAME withheld-keys disclosure (`EngineNotice`,
|
|
141
|
+
* `code: "config.secret_env_scrubbed"`, `detail.names`); independent of `onSecretEnvScrub` (a raw
|
|
142
|
+
* findings collector) except: that seat wired alone stays console-silent, as before this existed. */
|
|
143
|
+
onNotice?: (notice: EngineNotice) => void;
|
|
138
144
|
});
|
|
139
145
|
get schedulerCapabilities(): SchedulerCapability["schedulerCapabilities"];
|
|
140
146
|
schedule(intent: ScheduledIntent, ctx: SchedulerContext): Promise<Result<{
|
|
@@ -7,7 +7,7 @@ import { dirname, isAbsolute, join, resolve, sep } from "node:path";
|
|
|
7
7
|
import { createInterface } from "node:readline";
|
|
8
8
|
import { ExecutionError, err, FileError, ok, toError, } from "../harness/types.js";
|
|
9
9
|
import { killProcessTree, shutdownDebug } from "./kill-tree.js";
|
|
10
|
-
import { scrubSecretEnv } from "../../core/secret-env.js";
|
|
10
|
+
import { __resetSecretEnvScrubNoticeAnnouncement, announceSecretEnvScrub, scrubSecretEnv } from "../../core/secret-env.js";
|
|
11
11
|
import { physicalPathOfAsync } from "../../core/physical-path.js";
|
|
12
12
|
import { isUncSpelling } from "../../tools/fs/safety.js";
|
|
13
13
|
import { RollingTailBuffer, markTruncated, newStreamCursorState, sliceStreamIncrement, } from "../../core/exec-output-tail.js";
|
|
@@ -197,13 +197,12 @@ export async function getShellConfig(customShellPath) {
|
|
|
197
197
|
return ok({ shell: "sh", args: ["-c"] });
|
|
198
198
|
}
|
|
199
199
|
const EXEC_FORCE_SETTLE_GRACE_MS = 3000;
|
|
200
|
-
let secretScrubConsoleAnnounced = false;
|
|
201
200
|
let secretScrubSeatDefectAnnounced = false;
|
|
202
201
|
export function __resetSecretScrubAnnouncement() {
|
|
203
|
-
secretScrubConsoleAnnounced = false;
|
|
204
202
|
secretScrubSeatDefectAnnounced = false;
|
|
203
|
+
__resetSecretEnvScrubNoticeAnnouncement();
|
|
205
204
|
}
|
|
206
|
-
function getShellEnv(inheritEnv, baseEnv, extraEnv, onScrub) {
|
|
205
|
+
function getShellEnv(inheritEnv, baseEnv, extraEnv, onScrub, onNotice) {
|
|
207
206
|
let inherited;
|
|
208
207
|
if (inheritEnv === "all") {
|
|
209
208
|
inherited = process.env;
|
|
@@ -230,20 +229,17 @@ function getShellEnv(inheritEnv, baseEnv, extraEnv, onScrub) {
|
|
|
230
229
|
catch {
|
|
231
230
|
}
|
|
232
231
|
}
|
|
233
|
-
else {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
console.warn(`onSecretEnvScrub seat holds ${onScrub === null ? "null" : typeof onScrub} — not a function; scrub findings fall back to the console summary (once per process)`);
|
|
238
|
-
}
|
|
239
|
-
catch {
|
|
240
|
-
}
|
|
232
|
+
else if (onScrub !== undefined && !secretScrubSeatDefectAnnounced) {
|
|
233
|
+
secretScrubSeatDefectAnnounced = true;
|
|
234
|
+
try {
|
|
235
|
+
console.warn(`onSecretEnvScrub seat holds ${onScrub === null ? "null" : typeof onScrub} — not a function; scrub findings fall back to the console summary (once per process)`);
|
|
241
236
|
}
|
|
242
|
-
|
|
243
|
-
secretScrubConsoleAnnounced = true;
|
|
244
|
-
console.warn(`secret_env_scrubbed: ${findings.length} env key(s) withheld from the shell child (${findings.map((f) => f.key).join(", ")}) — once per process; wire onSecretEnvScrub for per-exec telemetry`);
|
|
237
|
+
catch {
|
|
245
238
|
}
|
|
246
239
|
}
|
|
240
|
+
if (!(typeof onScrub === "function" && onNotice === undefined)) {
|
|
241
|
+
announceSecretEnvScrub(onNotice, findings);
|
|
242
|
+
}
|
|
247
243
|
}
|
|
248
244
|
}
|
|
249
245
|
return {
|
|
@@ -302,6 +298,7 @@ export class NodeExecutionEnv {
|
|
|
302
298
|
bgCounter = 0;
|
|
303
299
|
retainBackgroundProcesses;
|
|
304
300
|
onSecretEnvScrub;
|
|
301
|
+
onNotice;
|
|
305
302
|
bgSpoolDir;
|
|
306
303
|
backgroundCapabilities;
|
|
307
304
|
constructor(options) {
|
|
@@ -312,6 +309,7 @@ export class NodeExecutionEnv {
|
|
|
312
309
|
this.scheduler = options.scheduler;
|
|
313
310
|
this.retainBackgroundProcesses = options.retainBackgroundProcesses ?? false;
|
|
314
311
|
this.onSecretEnvScrub = options.onSecretEnvScrub;
|
|
312
|
+
this.onNotice = options.onNotice;
|
|
315
313
|
this.backgroundCapabilities = {
|
|
316
314
|
supported: true,
|
|
317
315
|
maxConcurrent: 8,
|
|
@@ -469,7 +467,7 @@ export class NodeExecutionEnv {
|
|
|
469
467
|
child = spawn(shellConfig.value.shell, [...shellConfig.value.args, command], {
|
|
470
468
|
cwd,
|
|
471
469
|
detached: process.platform !== "win32",
|
|
472
|
-
env: getShellEnv(this.inheritEnv, this.shellEnv, options?.env, this.onSecretEnvScrub),
|
|
470
|
+
env: getShellEnv(this.inheritEnv, this.shellEnv, options?.env, this.onSecretEnvScrub, this.onNotice),
|
|
473
471
|
stdio: execSpoolFds ? ["ignore", execSpoolFds[0], execSpoolFds[1]] : ["ignore", "pipe", "pipe"],
|
|
474
472
|
windowsHide: true,
|
|
475
473
|
});
|
|
@@ -1221,7 +1219,7 @@ export class NodeExecutionEnv {
|
|
|
1221
1219
|
child = spawn(shellConfig.value.shell, [...shellConfig.value.args, command], {
|
|
1222
1220
|
cwd: options?.cwd ? resolvePath(this.cwd, options.cwd) : this.cwd,
|
|
1223
1221
|
detached: process.platform !== "win32",
|
|
1224
|
-
env: getShellEnv(this.inheritEnv, this.shellEnv, options?.env, this.onSecretEnvScrub),
|
|
1222
|
+
env: getShellEnv(this.inheritEnv, this.shellEnv, options?.env, this.onSecretEnvScrub, this.onNotice),
|
|
1225
1223
|
stdio: spoolFds ? ["ignore", spoolFds[0], spoolFds[1]] : ["ignore", "pipe", "pipe"],
|
|
1226
1224
|
windowsHide: true,
|
|
1227
1225
|
});
|
|
@@ -858,7 +858,7 @@ export class AgentHarness {
|
|
|
858
858
|
await this.handleAgentEvent({ type: "agent_end", messages: [failureMessage] }, signal);
|
|
859
859
|
return [failureMessage];
|
|
860
860
|
}
|
|
861
|
-
async executeTurn(turnState, text, options) {
|
|
861
|
+
async executeTurn(turnState, text, options, abortController) {
|
|
862
862
|
let activeTurnState = turnState;
|
|
863
863
|
const userMessage = createUserMessage(text, options?.images, options);
|
|
864
864
|
const beforeResult = await this.emitHook({
|
|
@@ -897,12 +897,10 @@ export class AgentHarness {
|
|
|
897
897
|
}
|
|
898
898
|
return messages;
|
|
899
899
|
};
|
|
900
|
-
const abortController = new AbortController();
|
|
901
900
|
const getTurnState = () => activeTurnState;
|
|
902
901
|
const setTurnState = (nextTurnState) => {
|
|
903
902
|
activeTurnState = nextTurnState;
|
|
904
903
|
};
|
|
905
|
-
this.runAbortController = abortController;
|
|
906
904
|
const runResultPromise = (async () => {
|
|
907
905
|
try {
|
|
908
906
|
return await runAgentLoop(takePrompts, this.createContext(turnState, beforeResult?.systemPrompt), this.createLoopConfig(getTurnState, setTurnState, beforeResult?.systemPrompt), (event) => this.handleAgentEvent(event, abortController.signal), abortController.signal, this.createStreamFn(getTurnState), undefined, this.loopTrace, {
|
|
@@ -938,7 +936,7 @@ export class AgentHarness {
|
|
|
938
936
|
return mergeTruncatedOutputChain(newMessages, i);
|
|
939
937
|
}
|
|
940
938
|
}
|
|
941
|
-
if (this.stopRequested)
|
|
939
|
+
if (this.stopRequested || abortController.signal.aborted)
|
|
942
940
|
return undefined;
|
|
943
941
|
if (this.trailingBatchEndedOn !== undefined)
|
|
944
942
|
return this.trailingBatchEndedOn;
|
|
@@ -976,17 +974,21 @@ export class AgentHarness {
|
|
|
976
974
|
}
|
|
977
975
|
}
|
|
978
976
|
this.phase = "turn";
|
|
977
|
+
const abortController = new AbortController();
|
|
978
|
+
this.runAbortController = abortController;
|
|
979
979
|
const finishRunPromise = this.startRunPromise();
|
|
980
980
|
try {
|
|
981
981
|
await this.flushPendingSessionWrites();
|
|
982
982
|
const turnState = await this.createTurnState();
|
|
983
|
-
return await this.executeTurn(turnState, text, options);
|
|
983
|
+
return await this.executeTurn(turnState, text, options, abortController);
|
|
984
984
|
}
|
|
985
985
|
catch (error) {
|
|
986
986
|
this.phase = "idle";
|
|
987
987
|
throw normalizeHarnessError(error, "unknown");
|
|
988
988
|
}
|
|
989
989
|
finally {
|
|
990
|
+
if (this.runAbortController === abortController)
|
|
991
|
+
this.runAbortController = undefined;
|
|
990
992
|
finishRunPromise();
|
|
991
993
|
}
|
|
992
994
|
}
|
|
@@ -2,6 +2,7 @@ import { type SessionWarmup } from "../../core/lsp-session.js";
|
|
|
2
2
|
import { type LspChildProcess } from "./stdio-lsp-transport.js";
|
|
3
3
|
import { type LspServerManager, type LspSession, type LspReadText } from "../../core/lsp.js";
|
|
4
4
|
import type { ExecutionEnv } from "../../internal/harness-types.js";
|
|
5
|
+
import type { EngineNotice } from "../../core/engine-notice.js";
|
|
5
6
|
/**
|
|
6
7
|
* Default language → server command table (the DETERMINED supported set). Each value is a `command [args…]`
|
|
7
8
|
* whose binary must be on the host `PATH`; absent ⇒ that language degrades. Mirrors the servers service bakes
|
|
@@ -22,6 +23,9 @@ export interface NodeLspManagerOptions {
|
|
|
22
23
|
/** The language server's environment for the default spawn, verbatim. Omitted ⇒ the host environment scrubbed of
|
|
23
24
|
* credential-shaped names (`scrubSecretEnv`, a tool child's scrub). Unread when {@link spawn} is supplied. */
|
|
24
25
|
env?: Record<string, string>;
|
|
26
|
+
/** #1081 — the withheld-keys notice sink, SAME shared once-per-process latch/code as the shell-exec
|
|
27
|
+
* site's `NodeExecutionEnv.onNotice`. Absent ⇒ console only. Unread when {@link spawn} is supplied. */
|
|
28
|
+
onNotice?: (notice: EngineNotice) => void;
|
|
25
29
|
/** Read a file's CURRENT text for the session's didOpen/didChange re-sync (default = local `fs.readFile` utf8). */
|
|
26
30
|
readText?: LspReadText;
|
|
27
31
|
/** Resolve the server `cwd`/`rootUri` for a file (default = env.cwd ?? nearest project marker ?? file dir). */
|
|
@@ -9,7 +9,7 @@ import { TransportLspSession } from "../../core/lsp-session.js";
|
|
|
9
9
|
import { StdioLspTransport } from "./stdio-lsp-transport.js";
|
|
10
10
|
import { MAX_LSP_FILE_BYTES, SharedAbortScope, settleOnAbort } from "../../core/lsp.js";
|
|
11
11
|
import { asThrownError, thrownText } from "../../core/thrown-value.js";
|
|
12
|
-
import { scrubSecretEnv } from "../../core/secret-env.js";
|
|
12
|
+
import { announceSecretEnvScrub, scrubSecretEnv } from "../../core/secret-env.js";
|
|
13
13
|
export const DEFAULT_LSP_SERVERS = {
|
|
14
14
|
typescript: "typescript-language-server --stdio",
|
|
15
15
|
javascript: "typescript-language-server --stdio",
|
|
@@ -67,7 +67,7 @@ export class NodeLspManager {
|
|
|
67
67
|
disposed = false;
|
|
68
68
|
constructor(opts = {}) {
|
|
69
69
|
this.servers = { ...DEFAULT_LSP_SERVERS, ...opts.servers };
|
|
70
|
-
this.spawnFn = opts.spawn ?? (opts.env
|
|
70
|
+
this.spawnFn = opts.spawn ?? lspSpawnWithEnv(opts.env, opts.onNotice);
|
|
71
71
|
this.readTextFn = opts.readText ?? defaultLspReadText;
|
|
72
72
|
this.resolveRootFn = opts.resolveRoot ?? defaultResolveRoot;
|
|
73
73
|
this.log = opts.log ?? (() => { });
|
|
@@ -330,10 +330,16 @@ export function lspSpawnOptions(cwd) {
|
|
|
330
330
|
: { cwd, stdio: ["pipe", "pipe", "ignore"] };
|
|
331
331
|
}
|
|
332
332
|
export const defaultLspSpawn = (command, args, cwd, signal) => lspSpawnWithEnv(undefined)(command, args, cwd, signal);
|
|
333
|
-
const lspSpawnWithEnv = (env) => (command, args, cwd, signal) => new Promise((resolve, reject) => {
|
|
333
|
+
const lspSpawnWithEnv = (env, onNotice) => (command, args, cwd, signal) => new Promise((resolve, reject) => {
|
|
334
334
|
let child;
|
|
335
335
|
try {
|
|
336
|
-
|
|
336
|
+
let scrubbedEnv = env;
|
|
337
|
+
if (scrubbedEnv == null) {
|
|
338
|
+
const findings = [];
|
|
339
|
+
scrubbedEnv = scrubSecretEnv(process.env, findings);
|
|
340
|
+
announceSecretEnvScrub(onNotice, findings);
|
|
341
|
+
}
|
|
342
|
+
child = spawn(command, args, { ...lspSpawnOptions(cwd), env: scrubbedEnv });
|
|
337
343
|
}
|
|
338
344
|
catch (e) {
|
|
339
345
|
return reject(asThrownError(e));
|
package/dist/index.d.ts
CHANGED
|
@@ -229,7 +229,7 @@ export { AdoptionError, assertAdoptionBootGate, readRootAdoptionFile, writeRootA
|
|
|
229
229
|
export { adoptLocalDataRoot, ackAdoptionConfig, witnessAdoptionConfig, listAdoptionQuarantine, readAdoptionStatus, type AdoptionStatus, type AdoptLocalDataRootOptions, type AdoptLocalDataRootResult, type AdoptionCarriageLeg, type AdoptionCarriageLegContext, type AdoptionConfigWitnessReceipt, } from "./stores/file/adoption/adopt.js";
|
|
230
230
|
export { formatHookFeedback, runToolGate, createHookEnvCapabilities, createPreToolUseConstraintPolicy, type PersistedRuleHit, type PersistedRuleHitRule, type PersistedRuleUnreadable, type PersistedRuleCoverage, type PersistedRuleAnswer, normalizePersistedRuleHit, type Hooks, type HookToolContext, type HookInvocationIdentity, type UserPromptSubmitContext, type PostToolBatchContext, type HookEnvCapabilities, type HookToolOutput, type PreToolUseResult, type PostToolUseResult, type UserPromptSubmitResult, type HookToolFailure, type PostToolUseFailureResult, type PostToolBatchCall, type PostToolBatchResult, type PreCompactContext, type PreCompactResult, type PostCompactContext, type StopFailureContext, type PermissionDeniedPayload, } from "./core/hooks.js";
|
|
231
231
|
export { HOOK_FAMILIES, HOOKS_INVALID_CODE, type HookFamily, type WiringManifestHookEntry } from "./core/hook-seats.js";
|
|
232
|
-
export { InMemoryMemoryStore, composeMemoryBlock, composeLayeredMemoryBlock, normalizeMemorySpec, type NormalizedMemorySpec, type MemorySpecInput, supportsConsolidation, supportsPeriodicConsolidation, firstSentence, expandLexicalTerms, lexicalSearchMatch, type Embedder, classifyPromotable, enforcePromotableWriteGate, guardedMemoryStore, MemoryGateError, MemoryProjectionError, detectSecret, enforceSecretWriteGate, enforceStructuredNoteSecretGate, type UtilityGate, type MemoryStore, type MemoryVectorMode, type ScoredMemory, type MemoryNoteHeader, type MemoryNoteRecord, type MemoryNoteType, type StructuredNoteInput, } from "./core/memory.js";
|
|
232
|
+
export { InMemoryMemoryStore, composeMemoryBlock, composeLayeredMemoryBlock, normalizeMemorySpec, type NormalizedMemorySpec, type MemorySpecInput, supportsConsolidation, supportsPeriodicConsolidation, firstSentence, expandLexicalTerms, lexicalSearchMatch, type Embedder, classifyPromotable, enforcePromotableWriteGate, guardedMemoryStore, MemoryGateError, MemoryProjectionError, detectSecret, enforceSecretWriteGate, enforceStructuredNoteSecretGate, type UtilityGate, type MemoryStore, type MemoryVectorMode, type ScoredMemory, type MemoryNoteHeader, type MemoryNoteRecord, type MemoryNoteType, type StructuredNoteInput, MEMORY_PROJECT_KEY_ABSENT_REASONS, type MemoryProjectKeyAbsentReason, type MemoryProjectKey, } from "./core/memory.js";
|
|
233
233
|
export { MemoryEngine, FileMemoryEngineBackend, memoryBackendContract, assertMemoryBackendSearchEquivalence, type MemoryBackendContractHooks, buildMemoryInstruction, writableRootOf, truncateIndex, scanEntryFiles, deriveRepoKey, deriveRepoMemoryDir, deriveControlPlaneDir, deriveRepoControlPlaneDir, resolveMemoryEngineRoot, scopeDirName, ControlPlaneCorruptError, parseEntryFile, serializeEntryFile, computeEntryRev, entryFromFile, MEMORY_ORIGIN_CAUSES, committedOriginOf, originEquals, consolidationExposedFrontmatter, ambiguousOriginRepresentation, type OriginClearanceRow, type OriginClearanceEvent, type OriginClearanceShadow, committedDistilledOf, distilledEquals, type MemoryEntryDistilled, type MemoryEntryDistilledInput, CONSOLIDATION_DEFAULTS, ConsolidationRefusedError, MEMORY_SEARCH_SUPERSEDED_TAG, consolidationTypeEligible, deriveSupersededSet, memorySupersededNote, readIntentCredentials, supersessionFuseCeiling, deriveShadowedSet, memoryConsolidationRecommendedNotice, memoryConsolidationCommittedNotice, memoryConsolidationConflictNotice, memoryConsolidationIncompleteNotice, memoryConsolidationRefusedNotice, memoryConsolidationWithheldNotice, type ConsolidationGateRead, type ConsolidationGateRow, type ConsolidationIntent, type ConsolidationIntentCredentialRow, type ConsolidationLeaseSeat, type ConsolidationProductProposal, type ConsolidationProposal, type MemoryConsolidationOptions, type ConsolidationCommitReceipt, type ConsolidationReconcileReport, type ConsolidationResolveReceipt, type ConsolidationPlanSummary, type ConsolidationPlanFoldEvidence, type SessionMemoryStatus, DISTILLER_DEFAULT_MAX_INPUTS_PER_PRODUCT, LLM_DISTILLER_CONTRACT, LLM_DISTILLER_CONTRACT_DL2, LLM_DISTILLER_CONTRACT_DL3, LLM_DISTILLER_CONTRACTS, MEMORY_DISTILLER_CONTRACT_V1, contractGroupingDiff, driveConsolidationToFixpoint, isAliasModelId, llmPlanDistiller, mintExposurePartitionedPlan, mintLlmConsolidationPlan, MEMORY_DISTILLER_PURITY_CONTRACT_V1, detectCleanArmVerbatimLeak, type CleanArmLeakFinding, type CleanArmLeakVerdict, type MemoryDistillerPurityContract, openAiCompatChatSeat, parseJsonAnswer, planParseRepairs, sanitizeLlmGroups, scheduleUnderFuse, type ConsolidationDistillFn, type ConsolidationDriveCycleRow, type ConsolidationDriveEngine, type ConsolidationDriveResult, type ConsolidationFoldState, type DistillerCandidate, type DistillerChatAnswer, type DistillerChatFn, type DistillerChatRequest, type FuseSchedule, type LlmConsolidationPlan, type LlmConsolidationPlanArm, type LlmConsolidationPlanProduct, type LlmDistillerContract, type MintLlmConsolidationPlanResult, type PlanParseRepairs, type SanitizedLlmGroups, CONSOLIDATION_DRIVER_PLANS_DIR, CONSOLIDATION_DRIVER_RUNS_FILE, CONSOLIDATION_RUN_STOP_REASONS, archiveDistillerPlan, readConsolidationDriverRun, runMemoryConsolidationDriver, type ConsolidationDriverEngine, type ConsolidationDriverRunRow, type ConsolidationRunReceipt, type ConsolidationRunStopReason, type RunMemoryConsolidationOptions, isInstructionEntry, type MemoryEntryOrigin, type MemoryOriginCause, MEMORY_INSTRUCTION_TEMPLATE, MEMORY_RECALL_DISCIPLINE, MEMORY_PREFERENCE_DISCIPLINE, MEMORY_READONLY_NOTICE, MEMORY_CAPTURE_OPTOUT_NOTICE, memoryCaptureOptedOutNotice, memoryCaptureOptOutUnpersistedNotice, SESSION_CAPTURE_OPTOUT_DIR, markSessionCaptureOptOut, readSessionCaptureOptOut, listSessionCaptureOptOut, fileSessionCaptureRecordStore, type SessionCaptureOptOutRecord, type SessionCaptureOptOutMarkOutcome, type SessionCaptureRecordStore, readV2HeaderHints, type V2HeaderHints, LINEAGE_FILE, CHALLENGES_FILE, CHALLENGED_HISTORY_FILE, CHALLENGE_LEDGER_MAX_EVENTS, rebuildStrictControlPlaneLedger, type ControlPlaneRebuildReceipt, type StrictControlPlaneLedger, type ChallengeAssignment, type ChallengeEvent, type ChallengedHistoryRow, type LineagePendingTxn, type LineagePromotion, MEMORY_INDEX_FILENAME, MEMORY_INDEX_MAX_LINES, MEMORY_INDEX_MAX_BYTES, MEMORY_SEARCH_TOOL_NAME, MEMORY_GET_TOOL_NAME, MEMORY_INDEX_TOOL_NAME, MEMORY_ENGINE_TOOL_NAMES, type MemorySearchDetails, type MemorySearchHit, type CleanMemorySearchHit, type ExposedMemorySearchHit, MEMORY_EXPOSURE_BANNER, MEMORY_EXPOSURE_HANDLE_TAG, memoryExposureIndexRow, type MemoryGetDetails, type MemoryIndexDetails, type MemoryIndexRow, type CleanMemoryIndexRow, type ExposedMemoryIndexRow, STUB_ARCHIVED_LINE, DEFAULT_MAX_MEMORY_FILES, DEFAULT_MAX_ENTRY_DEPTH, DEFAULT_HARVEST_DEADLINE_MS, DEFAULT_HARVEST_FILE_BUDGET, MASS_DELETION_FUSE_RATIO, scanMemoryWrite, scanMemoryFileName, scanRemediation, MEMORY_FILENAME_SEGMENT_RE, renderAnnouncements, enqueueMemoryAnnouncement, drainMemoryAnnouncements, peekMemoryAnnouncements, bumpScanFuse, scanFuseCount, clearScanFuse, ANNOUNCEMENTS_FILE, MEMORY_ANNOUNCEMENTS_MAX, SCAN_FUSE_FILE, SCAN_FUSE_THRESHOLD, type MemoryAnnouncement, type ScanFinding, type MemoryEngineOptions, type MemoryInjection, type EntryProvenanceAccount, type TransferEvidence, type CommittedBinding, type CommittedEntrySnapshot, type CommittedScopeSnapshots, type EntryCustodyReport, erasureSelectHash, type EraseMemoryEntriesInput, type ErasureSelect, type ErasedBinding, type MemoryErasureAttestation, computeMemoryBundleHash, type MemoryExportBundle, type MemoryImportReport, type MemoryExportSnapshot, type MemoryBundleImportPlan, type BundleChallengeRow, type BundleLineageRow, type BundlePollutedSession, type MemoryBackend, type MemoryEntry, type MemoryEntryFrontmatter, type MemoryEntryHeader, type MemoryScopeEnumeration, type ScoredMemoryEntry, type NotePatch, type PatchReport, type MaterializedFile, type MemorySessionHandle, type HarvestReport, type HarvestRejection, type HarvestRejectionCode, type ParsedEntryFile, type ScannedEntryFile, SCOPE_SEGMENT_MAX_ENCODED, PROJECT_MARKER_PATH, encodeScopeSegment, decodeScopeSegment, parseScopeKey, formatUserScope, formatOrgScope, formatProjScope, formatUserProjScope, isPersonalScope, assertScopeContractPlacement, formatProjectMarker, parseProjectMarker, resolveProjectId, PROJECT_ID_REGEX, type ParsedScopeKey, migrateScope, type MigrateScopeReport, materializeEntriesToFiles, harvestFilesToPatches, projectionsToWriteBack, screenInboundEntries, REMOTE_HARVEST_PER_FILE_BYTES, REMOTE_MASS_DELETION_FUSE_RATIO, type RemoteMemoryFile, type RemoteMemoryBaseline, type RemoteMaterialization, type RemoteHarvestResult, type InboundEntryFinding, deriveProjectMemoryDir, deriveProjectControlDir, recordProjectIdHint, lookupProjectIdHint, PROJECT_ID_HINTS_FILE, reconcileMemoryEntries, nextSyncBaseline, mergeRecallHits, type MemorySyncCursor, type MemorySyncConflict, type MemorySyncPlan, type RecallSource, syncMemoryScope, type MemorySyncTransport, type MemorySyncRequestBody, type MemorySyncResponseBody, type MemorySyncClientConflict, type SyncMemoryScopeOptions, type MemorySyncClientResult, } from "./core/memory-engine/index.js";
|
|
234
234
|
export { SHARED_MEMORY_READ_CAP_BYTES, SHARED_MEMORY_LIST_PAGE_SIZE, SharedMemoryStoreError, type SharedMemoryStoreProvider, type SharedMemoryStoreReader, type SharedMemoryPagedList, type SharedMemoryStoreInfo, type SharedMemoryDocumentEntry, type SharedMemorySnapshot, type SharedMemoryRequestContext, type MemoryListDetails, type MemoryReadDetails, } from "./core/shared-memory/types.js";
|
|
235
235
|
export { sharedMemoryStoreContract, type SharedMemoryFixture, type SharedMemoryStoreContractHooks, } from "./core/shared-memory/contract.js";
|
package/dist/index.js
CHANGED
|
@@ -179,7 +179,7 @@ export { AdoptionError, assertAdoptionBootGate, readRootAdoptionFile, writeRootA
|
|
|
179
179
|
export { adoptLocalDataRoot, ackAdoptionConfig, witnessAdoptionConfig, listAdoptionQuarantine, readAdoptionStatus, } from "./stores/file/adoption/adopt.js";
|
|
180
180
|
export { formatHookFeedback, runToolGate, createHookEnvCapabilities, createPreToolUseConstraintPolicy, normalizePersistedRuleHit, } from "./core/hooks.js";
|
|
181
181
|
export { HOOK_FAMILIES, HOOKS_INVALID_CODE } from "./core/hook-seats.js";
|
|
182
|
-
export { InMemoryMemoryStore, composeMemoryBlock, composeLayeredMemoryBlock, normalizeMemorySpec, supportsConsolidation, supportsPeriodicConsolidation, firstSentence, expandLexicalTerms, lexicalSearchMatch, classifyPromotable, enforcePromotableWriteGate, guardedMemoryStore, MemoryGateError, MemoryProjectionError, detectSecret, enforceSecretWriteGate, enforceStructuredNoteSecretGate, } from "./core/memory.js";
|
|
182
|
+
export { InMemoryMemoryStore, composeMemoryBlock, composeLayeredMemoryBlock, normalizeMemorySpec, supportsConsolidation, supportsPeriodicConsolidation, firstSentence, expandLexicalTerms, lexicalSearchMatch, classifyPromotable, enforcePromotableWriteGate, guardedMemoryStore, MemoryGateError, MemoryProjectionError, detectSecret, enforceSecretWriteGate, enforceStructuredNoteSecretGate, MEMORY_PROJECT_KEY_ABSENT_REASONS, } from "./core/memory.js";
|
|
183
183
|
export { MemoryEngine, FileMemoryEngineBackend, memoryBackendContract, assertMemoryBackendSearchEquivalence, buildMemoryInstruction, writableRootOf, truncateIndex, scanEntryFiles, deriveRepoKey, deriveRepoMemoryDir, deriveControlPlaneDir, deriveRepoControlPlaneDir, resolveMemoryEngineRoot, scopeDirName, ControlPlaneCorruptError, parseEntryFile, serializeEntryFile, computeEntryRev, entryFromFile, MEMORY_ORIGIN_CAUSES, committedOriginOf, originEquals, consolidationExposedFrontmatter, ambiguousOriginRepresentation, committedDistilledOf, distilledEquals, CONSOLIDATION_DEFAULTS, ConsolidationRefusedError, MEMORY_SEARCH_SUPERSEDED_TAG, consolidationTypeEligible, deriveSupersededSet, memorySupersededNote, readIntentCredentials, supersessionFuseCeiling, deriveShadowedSet, memoryConsolidationRecommendedNotice, memoryConsolidationCommittedNotice, memoryConsolidationConflictNotice, memoryConsolidationIncompleteNotice, memoryConsolidationRefusedNotice, memoryConsolidationWithheldNotice, DISTILLER_DEFAULT_MAX_INPUTS_PER_PRODUCT, LLM_DISTILLER_CONTRACT, LLM_DISTILLER_CONTRACT_DL2, LLM_DISTILLER_CONTRACT_DL3, LLM_DISTILLER_CONTRACTS, MEMORY_DISTILLER_CONTRACT_V1, contractGroupingDiff, driveConsolidationToFixpoint, isAliasModelId, llmPlanDistiller, mintExposurePartitionedPlan, mintLlmConsolidationPlan, MEMORY_DISTILLER_PURITY_CONTRACT_V1, detectCleanArmVerbatimLeak, openAiCompatChatSeat, parseJsonAnswer, planParseRepairs, sanitizeLlmGroups, scheduleUnderFuse, CONSOLIDATION_DRIVER_PLANS_DIR, CONSOLIDATION_DRIVER_RUNS_FILE, CONSOLIDATION_RUN_STOP_REASONS, archiveDistillerPlan, readConsolidationDriverRun, runMemoryConsolidationDriver, isInstructionEntry, MEMORY_INSTRUCTION_TEMPLATE, MEMORY_RECALL_DISCIPLINE, MEMORY_PREFERENCE_DISCIPLINE, MEMORY_READONLY_NOTICE, MEMORY_CAPTURE_OPTOUT_NOTICE, memoryCaptureOptedOutNotice, memoryCaptureOptOutUnpersistedNotice, SESSION_CAPTURE_OPTOUT_DIR, markSessionCaptureOptOut, readSessionCaptureOptOut, listSessionCaptureOptOut, fileSessionCaptureRecordStore, readV2HeaderHints, LINEAGE_FILE, CHALLENGES_FILE, CHALLENGED_HISTORY_FILE, CHALLENGE_LEDGER_MAX_EVENTS, rebuildStrictControlPlaneLedger, MEMORY_INDEX_FILENAME, MEMORY_INDEX_MAX_LINES, MEMORY_INDEX_MAX_BYTES, MEMORY_SEARCH_TOOL_NAME, MEMORY_GET_TOOL_NAME, MEMORY_INDEX_TOOL_NAME, MEMORY_ENGINE_TOOL_NAMES, MEMORY_EXPOSURE_BANNER, MEMORY_EXPOSURE_HANDLE_TAG, memoryExposureIndexRow, STUB_ARCHIVED_LINE, DEFAULT_MAX_MEMORY_FILES, DEFAULT_MAX_ENTRY_DEPTH, DEFAULT_HARVEST_DEADLINE_MS, DEFAULT_HARVEST_FILE_BUDGET, MASS_DELETION_FUSE_RATIO, scanMemoryWrite, scanMemoryFileName, scanRemediation, MEMORY_FILENAME_SEGMENT_RE, renderAnnouncements, enqueueMemoryAnnouncement, drainMemoryAnnouncements, peekMemoryAnnouncements, bumpScanFuse, scanFuseCount, clearScanFuse, ANNOUNCEMENTS_FILE, MEMORY_ANNOUNCEMENTS_MAX, SCAN_FUSE_FILE, SCAN_FUSE_THRESHOLD, erasureSelectHash, computeMemoryBundleHash, SCOPE_SEGMENT_MAX_ENCODED, PROJECT_MARKER_PATH, encodeScopeSegment, decodeScopeSegment, parseScopeKey, formatUserScope, formatOrgScope, formatProjScope, formatUserProjScope, isPersonalScope, assertScopeContractPlacement, formatProjectMarker, parseProjectMarker, resolveProjectId, PROJECT_ID_REGEX, migrateScope, materializeEntriesToFiles, harvestFilesToPatches, projectionsToWriteBack, screenInboundEntries, REMOTE_HARVEST_PER_FILE_BYTES, REMOTE_MASS_DELETION_FUSE_RATIO, deriveProjectMemoryDir, deriveProjectControlDir, recordProjectIdHint, lookupProjectIdHint, PROJECT_ID_HINTS_FILE, reconcileMemoryEntries, nextSyncBaseline, mergeRecallHits, syncMemoryScope, } from "./core/memory-engine/index.js";
|
|
184
184
|
export { SHARED_MEMORY_READ_CAP_BYTES, SHARED_MEMORY_LIST_PAGE_SIZE, SharedMemoryStoreError, } from "./core/shared-memory/types.js";
|
|
185
185
|
export { sharedMemoryStoreContract, } from "./core/shared-memory/contract.js";
|
|
@@ -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/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": 2478,
|
|
5
5
|
"exports": {
|
|
6
6
|
"A2ATaskState": "type",
|
|
7
7
|
"A2ATaskStateReversal": "type",
|
|
@@ -688,6 +688,7 @@
|
|
|
688
688
|
"MEMORY_INSTRUCTION_TEMPLATE": "variable",
|
|
689
689
|
"MEMORY_ORIGIN_CAUSES": "variable",
|
|
690
690
|
"MEMORY_PREFERENCE_DISCIPLINE": "variable",
|
|
691
|
+
"MEMORY_PROJECT_KEY_ABSENT_REASONS": "variable",
|
|
691
692
|
"MEMORY_READONLY_NOTICE": "variable",
|
|
692
693
|
"MEMORY_RECALL_DISCIPLINE": "variable",
|
|
693
694
|
"MEMORY_SAFETY": "variable",
|
|
@@ -769,6 +770,8 @@
|
|
|
769
770
|
"MemoryNoteRecord": "interface",
|
|
770
771
|
"MemoryNoteType": "type",
|
|
771
772
|
"MemoryOriginCause": "type",
|
|
773
|
+
"MemoryProjectKey": "type",
|
|
774
|
+
"MemoryProjectKeyAbsentReason": "type",
|
|
772
775
|
"MemoryProjectionError": "class",
|
|
773
776
|
"MemoryPromptArtifactStore": "class",
|
|
774
777
|
"MemoryPromptSourceStateStore": "class",
|
|
@@ -3165,6 +3168,7 @@
|
|
|
3165
3168
|
"MEMORY_INSTRUCTION_TEMPLATE": "advanced",
|
|
3166
3169
|
"MEMORY_ORIGIN_CAUSES": "advanced",
|
|
3167
3170
|
"MEMORY_PREFERENCE_DISCIPLINE": "advanced",
|
|
3171
|
+
"MEMORY_PROJECT_KEY_ABSENT_REASONS": "advanced",
|
|
3168
3172
|
"MEMORY_READONLY_NOTICE": "advanced",
|
|
3169
3173
|
"MEMORY_RECALL_DISCIPLINE": "advanced",
|
|
3170
3174
|
"MEMORY_SAFETY": "advanced",
|
|
@@ -3246,6 +3250,8 @@
|
|
|
3246
3250
|
"MemoryNoteRecord": "stable",
|
|
3247
3251
|
"MemoryNoteType": "advanced",
|
|
3248
3252
|
"MemoryOriginCause": "advanced",
|
|
3253
|
+
"MemoryProjectKey": "advanced",
|
|
3254
|
+
"MemoryProjectKeyAbsentReason": "advanced",
|
|
3249
3255
|
"MemoryProjectionError": "advanced",
|
|
3250
3256
|
"MemoryPromptArtifactStore": "advanced",
|
|
3251
3257
|
"MemoryPromptSourceStateStore": "advanced",
|