@sema-agent/core 5.38.0 → 5.39.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 +84 -0
- package/dist/agents/send-message-tool.d.ts +8 -0
- package/dist/agents/send-message-tool.js +8 -0
- package/dist/agents/teacher.js +9 -3
- package/dist/agents/verify.js +9 -3
- package/dist/core/hooks.d.ts +23 -0
- package/dist/core/hooks.js +45 -4
- package/dist/core/mailbox-store.d.ts +39 -0
- package/dist/core/mailbox-store.js +9 -0
- package/dist/core/permission-rule-consent.d.ts +27 -4
- package/dist/core/permission-rule-consent.js +29 -4
- package/dist/core/permission-rule-model.d.ts +7 -1
- package/dist/core/runner/prepare-task.js +11 -3
- package/dist/core/sensitive-path-policy.js +3 -3
- package/dist/core/store-contracts/mailbox-store-contract.d.ts +29 -1
- package/dist/core/store-contracts/mailbox-store-contract.js +78 -0
- package/dist/core/types.d.ts +21 -0
- package/dist/core/write-protect.d.ts +93 -0
- package/dist/core/write-protect.js +194 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +3 -2
- package/dist/orchestration/governance-baseline-validity.d.ts +44 -0
- package/dist/orchestration/governance-baseline-validity.js +55 -0
- package/dist/orchestration/run-workflow-tool.js +33 -8
- package/dist/orchestration/workflow-script-runner.js +9 -4
- package/dist/tools/fs/read-deny.d.ts +15 -5
- package/dist/tools/fs/read-deny.js +33 -12
- package/dist/tools/fs/safety.d.ts +4 -1
- package/dist/tools/fs/safety.js +4 -2
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +13 -1
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import { governanceBaselineProblem } from "./governance-baseline-validity.js";
|
|
1
2
|
export function isSelfOrchestrationActive(spec, deps) {
|
|
2
3
|
return spec.selfOrchestration === true && workflowsCapability(deps);
|
|
3
4
|
}
|
|
4
5
|
export function workflowsCapability(deps) {
|
|
5
|
-
return
|
|
6
|
-
|
|
6
|
+
return deps.workflowScriptRunner?.safeForUntrustedScripts === true && hasUsableGovernanceBaseline(deps);
|
|
7
|
+
}
|
|
8
|
+
function hasUsableGovernanceBaseline(deps) {
|
|
9
|
+
return governanceBaselineProblem(deps.workflowGovernanceBaseline) === null;
|
|
7
10
|
}
|
|
8
11
|
export function selfOrchestrationFailClosedReason(spec, deps) {
|
|
9
12
|
if (spec.selfOrchestration !== true)
|
|
@@ -14,8 +17,10 @@ export function selfOrchestrationFailClosedReason(spec, deps) {
|
|
|
14
17
|
if (deps.workflowScriptRunner?.safeForUntrustedScripts !== true) {
|
|
15
18
|
missing.push("a hard WorkflowScriptRunner (RunnerDeps.workflowScriptRunner.safeForUntrustedScripts === true)");
|
|
16
19
|
}
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
const problem = governanceBaselineProblem(deps.workflowGovernanceBaseline);
|
|
21
|
+
if (problem !== null) {
|
|
22
|
+
missing.push(`a usable governance baseline (RunnerDeps.workflowGovernanceBaseline.${problem.where === "workflowGovernanceBaseline" ? "" : `${problem.where} `}` +
|
|
23
|
+
`is ${problem.found})`);
|
|
19
24
|
}
|
|
20
25
|
return (`self-orchestration (TaskSpec.selfOrchestration) requires ${missing.join(" and ")}; it is DISABLED for ` +
|
|
21
26
|
`this task (fail-closed — the run_workflow tool is not mounted and the orchestration prompt is not injected).`);
|
|
@@ -40,10 +40,18 @@ export interface ReadDenyMatcher {
|
|
|
40
40
|
/** Normalized entries (built-ins first, then additions; exact duplicates folded). The disclosure /
|
|
41
41
|
* persistence face. */
|
|
42
42
|
readonly entries: readonly NormalizedReadDenyEntry[];
|
|
43
|
-
/** Judge ONE path view (segment-window semantics). Returns the first matching entry, or null.
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
/** Judge ONE path view (segment-window semantics). Returns the first matching entry, or null.
|
|
44
|
+
* `aliasResolved` = the key's MINTER reports the real filesystem already collapsed any win32
|
|
45
|
+
* component alias in it (canonicalizeTarget's realpath arm); unset ⇒ both readings are judged,
|
|
46
|
+
* which is the fail-closed default. */
|
|
47
|
+
matchPath(path: string, opts?: {
|
|
48
|
+
readonly aliasResolved?: boolean;
|
|
49
|
+
}): ReadDenyHit | null;
|
|
50
|
+
/** §3.3 target judgment: canonical view + lexical view; EITHER hit decides. `aliasResolved`
|
|
51
|
+
* applies to the CANONICAL arm only — the lexical view is an unresolved spelling. */
|
|
52
|
+
matchTarget(canonicalKey: string, lexicalView?: string, opts?: {
|
|
53
|
+
readonly aliasResolved?: boolean;
|
|
54
|
+
}): ReadDenyHit | null;
|
|
47
55
|
/** Traversal exclusions for the rg legs: `!`-polarity glob pairs — `!**\/<p>` plus `!**\/<p>/…`
|
|
48
56
|
* (the entry itself and its descendants). */
|
|
49
57
|
readonly rgExclusionGlobs: readonly ReadDenyRgGlob[];
|
|
@@ -145,7 +153,9 @@ export declare function compileSegmentPattern(raw: string, fold: "none" | "ascii
|
|
|
145
153
|
* BOTH separator families — win32 canonical keys are backslash-form. Returns the matched raw pattern
|
|
146
154
|
* or null.
|
|
147
155
|
*/
|
|
148
|
-
export declare function matchSegmentPatterns(path: string, compiled: readonly CompiledSegmentPattern[]
|
|
156
|
+
export declare function matchSegmentPatterns(path: string, compiled: readonly CompiledSegmentPattern[], opts?: {
|
|
157
|
+
readonly aliasResolved?: boolean;
|
|
158
|
+
}): string | null;
|
|
149
159
|
/**
|
|
150
160
|
* codex r3 — the PURE validation/canonicality predicate over a PERSISTED deny entry (checkpoint v9
|
|
151
161
|
* face section), for the resume pre-CAS ladder: it must refuse BEFORE the approval CAS everything
|
|
@@ -91,15 +91,36 @@ export function compileSegmentPattern(raw, fold) {
|
|
|
91
91
|
});
|
|
92
92
|
return { raw, segments, foldAscii: fold === "ascii" };
|
|
93
93
|
}
|
|
94
|
-
export function matchSegmentPatterns(path, compiled) {
|
|
95
|
-
const
|
|
96
|
-
|
|
94
|
+
export function matchSegmentPatterns(path, compiled, opts) {
|
|
95
|
+
const literalSegs = path.split(/[\\/]/).filter(Boolean);
|
|
96
|
+
const win32Segs = [];
|
|
97
|
+
for (const raw of literalSegs) {
|
|
98
|
+
const dot = /^\.{1,2}$/.test(raw) ? raw : raw.replace(/ +$/, "");
|
|
99
|
+
if (dot === ".")
|
|
100
|
+
continue;
|
|
101
|
+
if (dot === "..") {
|
|
102
|
+
const last = win32Segs[win32Segs.length - 1];
|
|
103
|
+
if (win32Segs.length > 0 && last !== "..")
|
|
104
|
+
win32Segs.pop();
|
|
105
|
+
else
|
|
106
|
+
win32Segs.push("..");
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
const stripped = raw.replace(/[. ]+$/, "");
|
|
110
|
+
win32Segs.push(stripped.length > 0 ? stripped : raw);
|
|
111
|
+
}
|
|
112
|
+
const sameView = opts?.aliasResolved === true ||
|
|
113
|
+
(win32Segs.length === literalSegs.length && win32Segs.every((s, i) => s === literalSegs[i]));
|
|
114
|
+
const views = sameView ? [literalSegs] : [literalSegs, win32Segs];
|
|
115
|
+
const lowered = new Map();
|
|
97
116
|
for (const pat of compiled) {
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
117
|
+
for (const view of views) {
|
|
118
|
+
const segs = pat.foldAscii ? (lowered.get(view) ?? lowered.set(view, view.map(asciiLower)).get(view)) : view;
|
|
119
|
+
const n = pat.segments.length;
|
|
120
|
+
for (let i = 0; i + n <= segs.length; i++) {
|
|
121
|
+
if (pat.segments.every((re, j) => re.test(segs[i + j] ?? "")))
|
|
122
|
+
return pat.raw;
|
|
123
|
+
}
|
|
103
124
|
}
|
|
104
125
|
}
|
|
105
126
|
return null;
|
|
@@ -171,15 +192,15 @@ export function compileReadDeny(additions = [], layer = "additions", builtin) {
|
|
|
171
192
|
rgExclusionGlobs.push({ flag, glob: `!**/${g}` }, { flag, glob: `!**/${g}/**` });
|
|
172
193
|
rgProbeGlobs.push({ flag, glob: `**/${g}` }, { flag, glob: `**/${g}/**` });
|
|
173
194
|
}
|
|
174
|
-
const matchPath = (path) => {
|
|
175
|
-
const hit = matchSegmentPatterns(path, compiled);
|
|
195
|
+
const matchPath = (path, opts) => {
|
|
196
|
+
const hit = matchSegmentPatterns(path, compiled, opts);
|
|
176
197
|
return hit === null ? null : { pattern: hit };
|
|
177
198
|
};
|
|
178
199
|
return {
|
|
179
200
|
entries: normalized,
|
|
180
201
|
matchPath,
|
|
181
|
-
matchTarget(canonicalKey, lexicalView) {
|
|
182
|
-
const canonical = matchPath(canonicalKey);
|
|
202
|
+
matchTarget(canonicalKey, lexicalView, opts) {
|
|
203
|
+
const canonical = matchPath(canonicalKey, opts);
|
|
183
204
|
if (canonical !== null)
|
|
184
205
|
return { ...canonical, matchedView: canonicalKey };
|
|
185
206
|
if (lexicalView !== undefined) {
|
|
@@ -268,7 +268,9 @@ export declare function lexicalViewOf(spelled: string, base: string): string;
|
|
|
268
268
|
* `executionEnv` — see design/44 §5.)
|
|
269
269
|
*/
|
|
270
270
|
export declare function resolveKey(env: ExecutionEnv, rootCanonical: string, path: string, signal?: AbortSignal, baseCwd?: string, additionalRootsCanonical?: readonly string[], exactFileReadExemption?: (canonicalKey: string) => boolean, readDeny?: {
|
|
271
|
-
matchTarget(canonicalKey: string, lexicalView?: string
|
|
271
|
+
matchTarget(canonicalKey: string, lexicalView?: string, opts?: {
|
|
272
|
+
readonly aliasResolved?: boolean;
|
|
273
|
+
}): {
|
|
272
274
|
pattern: string;
|
|
273
275
|
matchedView?: string;
|
|
274
276
|
} | null;
|
|
@@ -291,6 +293,7 @@ export declare function resolveKey(env: ExecutionEnv, rootCanonical: string, pat
|
|
|
291
293
|
export declare function canonicalizeTarget(env: ExecutionEnv, path: string, signal?: AbortSignal, baseCwd?: string): Promise<{
|
|
292
294
|
ok: true;
|
|
293
295
|
key: string;
|
|
296
|
+
aliasResolved?: true;
|
|
294
297
|
} | {
|
|
295
298
|
ok: false;
|
|
296
299
|
message: string;
|
package/dist/tools/fs/safety.js
CHANGED
|
@@ -339,7 +339,9 @@ export async function resolveKey(env, rootCanonical, path, signal, baseCwd, addi
|
|
|
339
339
|
return { ok: false, violation: { code: "invalid", message: `path "${path}" is a blocked device/special file (reading it can hang the process); refused.` } };
|
|
340
340
|
}
|
|
341
341
|
if (readDeny !== undefined) {
|
|
342
|
-
const hit = readDeny.matchTarget(key, lexicalViewOf(path, baseCwd ?? rootCanonical)
|
|
342
|
+
const hit = readDeny.matchTarget(key, lexicalViewOf(path, baseCwd ?? rootCanonical), {
|
|
343
|
+
aliasResolved: canon.aliasResolved === true,
|
|
344
|
+
});
|
|
343
345
|
if (hit !== null) {
|
|
344
346
|
const lexicalHit = hit.matchedView !== undefined && hit.matchedView !== key;
|
|
345
347
|
const judged = lexicalHit
|
|
@@ -419,7 +421,7 @@ export async function canonicalizeTarget(env, path, signal, baseCwd) {
|
|
|
419
421
|
}
|
|
420
422
|
const canon = await env.canonicalPath(abs, signal);
|
|
421
423
|
if (canon.ok)
|
|
422
|
-
return { ok: true, key: canon.value };
|
|
424
|
+
return { ok: true, key: canon.value, aliasResolved: true };
|
|
423
425
|
const info = await env.fileInfo(abs, signal);
|
|
424
426
|
if (!info.ok) {
|
|
425
427
|
return { ok: false, message: `cannot determine whether "${path}" is a symlink: ${info.error.message}`, unresolvedSymlink: true };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
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
|
-
"count":
|
|
3
|
+
"count": 1597,
|
|
4
4
|
"exports": {
|
|
5
5
|
"A2ATaskState": "type",
|
|
6
6
|
"A2ATaskStateReversal": "type",
|
|
@@ -408,6 +408,7 @@
|
|
|
408
408
|
"LspToolOptions": "interface",
|
|
409
409
|
"LspTransport": "interface",
|
|
410
410
|
"MAILBOX_CONTRACT_SCOPE": "variable",
|
|
411
|
+
"MAILBOX_TOMBSTONED_RECIPIENT_CODE": "variable",
|
|
411
412
|
"MASS_DELETION_FUSE_RATIO": "variable",
|
|
412
413
|
"MAX_ACTOR_FIELD_CHARS": "variable",
|
|
413
414
|
"MAX_EDIT_BYTES": "variable",
|
|
@@ -445,6 +446,8 @@
|
|
|
445
446
|
"MailboxLease": "interface",
|
|
446
447
|
"MailboxMessage": "interface",
|
|
447
448
|
"MailboxStore": "interface",
|
|
449
|
+
"MailboxStoreError": "class",
|
|
450
|
+
"MailboxTombstonedRecipientContractHooks": "interface",
|
|
448
451
|
"ManagedRetentionCapability": "interface",
|
|
449
452
|
"ManifestDurability": "type",
|
|
450
453
|
"MaterializedA2a": "interface",
|
|
@@ -1028,6 +1031,7 @@
|
|
|
1028
1031
|
"WORKFLOW_SUBAGENT_PROMPT": "variable",
|
|
1029
1032
|
"WORKFLOW_SUBAGENT_PROMPT_SCHEMA": "variable",
|
|
1030
1033
|
"WORKTREE_PARENT": "variable",
|
|
1034
|
+
"WRITE_PROTECTED_DEFAULT_TABLE": "variable",
|
|
1031
1035
|
"WebFetchConfig": "interface",
|
|
1032
1036
|
"WebSearchConfig": "interface",
|
|
1033
1037
|
"WiringFacts": "interface",
|
|
@@ -1077,6 +1081,11 @@
|
|
|
1077
1081
|
"WorktreeSessionRef": "interface",
|
|
1078
1082
|
"WorktreeToolsOptions": "interface",
|
|
1079
1083
|
"WritablePermissionRuleStore": "interface",
|
|
1084
|
+
"WriteProtectedEntry": "type",
|
|
1085
|
+
"WriteProtectedHit": "interface",
|
|
1086
|
+
"WriteProtectedKind": "type",
|
|
1087
|
+
"WriteProtectedRow": "interface",
|
|
1088
|
+
"WriteProtectionMatcher": "interface",
|
|
1080
1089
|
"ackAdoptionConfig": "function",
|
|
1081
1090
|
"acquireCcLock": "function",
|
|
1082
1091
|
"addDotsOf": "function",
|
|
@@ -1158,6 +1167,7 @@
|
|
|
1158
1167
|
"collectBelowFrontier": "function",
|
|
1159
1168
|
"combinePolicies": "function",
|
|
1160
1169
|
"compileReadDeny": "function",
|
|
1170
|
+
"compileWriteProtection": "function",
|
|
1161
1171
|
"complianceCallDenial": "function",
|
|
1162
1172
|
"compose": "function",
|
|
1163
1173
|
"composeConstitution": "function",
|
|
@@ -1362,6 +1372,7 @@
|
|
|
1362
1372
|
"mailboxAckOwnershipContract": "function",
|
|
1363
1373
|
"mailboxBundledOnlyContract": "function",
|
|
1364
1374
|
"mailboxStoreContract": "function",
|
|
1375
|
+
"mailboxTombstonedRecipientContract": "function",
|
|
1365
1376
|
"markTruncated": "function",
|
|
1366
1377
|
"materializeA2aTools": "function",
|
|
1367
1378
|
"materializeEntriesToFiles": "function",
|
|
@@ -1477,6 +1488,7 @@
|
|
|
1477
1488
|
"resolveTaskLimits": "function",
|
|
1478
1489
|
"resolveTaskModel": "function",
|
|
1479
1490
|
"resolveUsageWindows": "function",
|
|
1491
|
+
"resolveWriteProtectedTable": "function",
|
|
1480
1492
|
"restoreFrozenPaths": "function",
|
|
1481
1493
|
"resumeWithVerification": "function",
|
|
1482
1494
|
"retiredWorkflowNameAliases": "function",
|