@sema-agent/core 7.38.0 → 7.38.2
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 +51 -0
- package/dist/brain/tool-call-repair.js +1 -1
- package/dist/core/engine-notice.d.ts +4 -3
- package/dist/core/runner/prepare-artifact.d.ts +3 -2
- package/dist/core/runner/prepare-hands-readface.d.ts +4 -3
- package/dist/core/runner/prepare-hands-readface.js +1 -0
- package/dist/core/runner/prepare-turn-wiring.d.ts +2 -2
- package/dist/core/store-contracts/read-back-shape-contract.d.ts +5 -0
- package/dist/stores/file/fs-atomic.d.ts +23 -10
- package/dist/stores/file/fs-atomic.js +51 -25
- package/dist/tools/fs/fs-shared.d.ts +2 -1
- package/dist/tools/fs/fs-shared.js +1 -1
- package/dist/tools/fs/index.d.ts +13 -6
- package/dist/tools/fs/index.js +12 -4
- package/dist/tools/fs/read-deny-home.d.ts +98 -45
- package/dist/tools/fs/read-deny-home.js +294 -117
- package/dist/tools/fs/read-deny.d.ts +2 -2
- package/dist/tools/fs/safety.d.ts +2 -0
- package/dist/tools/fs/safety.js +1 -1
- package/dist/tools/fs/search.d.ts +4 -3
- package/dist/tools/fs/search.js +3 -3
- package/dist/tools/fs/shell-read-check.d.ts +9 -0
- package/dist/tools/fs/shell-read-check.js +3 -2
- package/dist/tools/fs/shell-read-establish.d.ts +3 -0
- package/dist/tools/fs/shell-read-establish.js +1 -1
- package/dist/tools/fs/shell-read-identity.d.ts +4 -3
- package/dist/tools/fs/shell-read-identity.js +2 -2
- package/package.json +1 -1
- package/wire-changes/core@7.38.1.json +56 -0
- package/wire-changes/core@7.38.2.json +26 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type HomeViewSource } from "./read-deny-home.js";
|
|
1
2
|
import type { AssertAllKeysHandled } from "../../core/ask-origin.js";
|
|
2
3
|
import type { ExecutionEnv } from "../../internal/harness-types.js";
|
|
3
4
|
import { protectivePathTargetOf, type ToolCallLike } from "../../core/tool-registry.js";
|
|
@@ -449,6 +450,7 @@ export type RootsSeat = readonly string[] | (() => readonly string[] | undefined
|
|
|
449
450
|
*/
|
|
450
451
|
export declare function resolveKey(env: ExecutionEnv, rootCanonical: string, path: string, signal?: AbortSignal, baseCwd?: string, additionalRoots?: RootsSeat, exactFileReadExemption?: (canonicalKey: string) => boolean, readDeny?: {
|
|
451
452
|
readonly face?: "write";
|
|
453
|
+
readonly homeViews?: HomeViewSource;
|
|
452
454
|
matchTarget(canonicalKey: string, lexicalView?: string, opts?: {
|
|
453
455
|
readonly aliasResolved?: boolean;
|
|
454
456
|
}): {
|
package/dist/tools/fs/safety.js
CHANGED
|
@@ -469,7 +469,7 @@ export async function resolveKey(env, rootCanonical, path, signal, baseCwd, addi
|
|
|
469
469
|
const judged = { aliasResolved: canon.aliasResolved === true };
|
|
470
470
|
let hit = readDeny.matchTarget(key, lexicalViewOf(path, baseCwd ?? rootCanonical), judged);
|
|
471
471
|
if (hit === null) {
|
|
472
|
-
const homeView = await homeViewsOf(env, signal).of(key);
|
|
472
|
+
const homeView = await homeViewsOf(env, readDeny, signal).of(key);
|
|
473
473
|
if (homeView !== undefined)
|
|
474
474
|
hit = readDeny.matchTarget(key, homeView, judged);
|
|
475
475
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ExecutionEnv } from "../../internal/harness-types.js";
|
|
2
|
+
import { type HomeViewsCarrier } from "./read-deny-home.js";
|
|
2
3
|
/** The JS scanner's own output ceiling, in bytes of emitted content rows. Pinned to the
|
|
3
4
|
* ripgrep leg's figure ({@link MAX_EXEC_OUTPUT_BYTES}, the exec pipe's rolling-tail bound) so the two
|
|
4
5
|
* legs cannot disagree about how much one search may return; see the collection site in {@link jsGrep}
|
|
@@ -130,7 +131,7 @@ export declare function walk(env: ExecutionEnv, root: string, start: string, ign
|
|
|
130
131
|
matchPath(path: string): {
|
|
131
132
|
pattern: string;
|
|
132
133
|
} | null;
|
|
133
|
-
}): Promise<WalkResult>;
|
|
134
|
+
} & HomeViewsCarrier): Promise<WalkResult>;
|
|
134
135
|
/** The JS-leg withholding disclosure: an empty result must stay distinguishable from
|
|
135
136
|
* searched-and-empty, so this note rides EVERY output shape when something was pruned. Distinct from
|
|
136
137
|
* {@link walkCaveat}: pruning is deliberate withholding, not incompleteness.
|
|
@@ -157,8 +158,8 @@ export interface ReadDenyWithheld {
|
|
|
157
158
|
count?: number;
|
|
158
159
|
patterns?: readonly string[];
|
|
159
160
|
}
|
|
160
|
-
/** The deny judge seam every search leg shares (structural subset of ReadDenyMatcher). */
|
|
161
|
-
export interface ReadDenyJudge {
|
|
161
|
+
/** The deny judge seam every search leg shares (structural subset of ReadDenyMatcher), with its placement's home views. */
|
|
162
|
+
export interface ReadDenyJudge extends HomeViewsCarrier {
|
|
162
163
|
matchPath(path: string): {
|
|
163
164
|
pattern: string;
|
|
164
165
|
} | null;
|
package/dist/tools/fs/search.js
CHANGED
|
@@ -228,7 +228,7 @@ export async function walk(env, root, start, ignore, signal, deny) {
|
|
|
228
228
|
let aborted = false;
|
|
229
229
|
let denyPruned = 0;
|
|
230
230
|
const denyPatterns = [];
|
|
231
|
-
const views = deny !== undefined ? homeViewsOf(env, signal) : undefined;
|
|
231
|
+
const views = deny !== undefined ? homeViewsOf(env, deny, signal) : undefined;
|
|
232
232
|
const denyHit = async (path, leaf) => {
|
|
233
233
|
let hit = deny?.matchPath(path);
|
|
234
234
|
if (!hit && views !== undefined) {
|
|
@@ -1156,7 +1156,7 @@ function rgRecordAbsolute(base) {
|
|
|
1156
1156
|
return (p) => (base === undefined || family === undefined || isAbsoluteForFamily(family, p) ? p : joinForFamily(family, base, p.replace(/^\.[\\/]/, "")));
|
|
1157
1157
|
}
|
|
1158
1158
|
async function rgOutputDenyTripwireAt(env, stdout, mode, deny, opts, signal) {
|
|
1159
|
-
const views = homeViewsOf(env, signal);
|
|
1159
|
+
const views = homeViewsOf(env, deny, signal);
|
|
1160
1160
|
const absolute = rgRecordAbsolute(opts.base);
|
|
1161
1161
|
const placed = new Map();
|
|
1162
1162
|
for (const record of parseRgRecords(stdout, mode, opts.dropIncompleteTail === true)) {
|
|
@@ -1343,7 +1343,7 @@ export async function runGrepDetailed(env, root, p, signal, deny) {
|
|
|
1343
1343
|
return false;
|
|
1344
1344
|
if (deny.unexcludableUnder(scope))
|
|
1345
1345
|
return true;
|
|
1346
|
-
const view = await homeViewsOf(env, signal).of(scope);
|
|
1346
|
+
const view = await homeViewsOf(env, deny, signal).of(scope);
|
|
1347
1347
|
return view !== undefined && deny.unexcludableUnder(view);
|
|
1348
1348
|
};
|
|
1349
1349
|
if (!(await unexcludableUnder()) && (await detectRipgrep(env)))
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
import type { ExecutionEnv } from "../../internal/harness-types.js";
|
|
21
21
|
import { violationDetails } from "./safety.js";
|
|
22
22
|
import { type ShellReadPlan } from "./shell-read-plan.js";
|
|
23
|
+
import { type HomeViewSource } from "./read-deny-home.js";
|
|
23
24
|
import { type EstablishedRead, type ShellReadBoundary, type ShellReadDisposition, type ShellReadFinding, type ShellReadSeat } from "./shell-read-judge.js";
|
|
24
25
|
import type { ReadRootGrantCandidate } from "../../core/tool-spec.js";
|
|
25
26
|
import type { ToolCallLike } from "../../core/tool-registry.js";
|
|
@@ -145,6 +146,9 @@ export interface ShellReadStationOptions {
|
|
|
145
146
|
/** `true` ⇔ every root `boundaryOf` returns is already a canonical identity (the Runner's): the station never
|
|
146
147
|
* re-resolves one, so a root swapped for a link after it was declared or granted cannot bring in the link's target. */
|
|
147
148
|
readonly rootsCanonical?: boolean;
|
|
149
|
+
/** The home views of the placement the boundary's deny seats were compiled at (read-deny-home.ts) — the Runner's. Absent,
|
|
150
|
+
* the declared home alone. */
|
|
151
|
+
readonly homeViews?: HomeViewSource;
|
|
148
152
|
}
|
|
149
153
|
/** What a consumer hands {@link judgeShellRead}: the command as written, the environment whose filesystem
|
|
150
154
|
* answers where its words land (symlinks resolved, patterns expanded — a `NodeExecutionEnv` over a real
|
|
@@ -191,6 +195,11 @@ export interface ShellReadJudgment {
|
|
|
191
195
|
* LAXER where only a filesystem sees the escape (an in-root symlink pointing out vouches) and answers a
|
|
192
196
|
* pattern on its spelling alone, so the two diverge in both directions.
|
|
193
197
|
*
|
|
198
|
+
* A read target is also judged at its HOME VIEW (a path spelled through a firmlink or a bind mount of a home, respelled
|
|
199
|
+
* at the home): this judgment is its own placement — the views read the environment's declared home and the account
|
|
200
|
+
* home the account database answers once, for this call (`readDenyHomesOf`'s homes); the account home's probes wait at
|
|
201
|
+
* most a short bound of their own.
|
|
202
|
+
*
|
|
194
203
|
* It carries NO deadline. Bounding an environment-facing wait and substituting a fail-closed verdict is the
|
|
195
204
|
* gate FOLD's policy on the gate's one deadline seat; the station has never held one on either entry, and a
|
|
196
205
|
* second default here would decide the same number twice and turn a slow-but-correct filesystem's true
|
|
@@ -6,6 +6,7 @@ import { NOT_AUTO_ALLOWED, programPositionRefusalSentence, readProgramPosition }
|
|
|
6
6
|
import { bashClassifyDefaultAllow } from "./bash-readonly-classifier.js";
|
|
7
7
|
import { planShellReads } from "./shell-read-plan.js";
|
|
8
8
|
import { createShellReadEstablisher, establishShellReadsLexically } from "./shell-read-establish.js";
|
|
9
|
+
import { declaredReadDenyHomes, homeViewsAt } from "./read-deny-home.js";
|
|
9
10
|
import { programArgs, spellsOption } from "./shell-read-write-targets.js";
|
|
10
11
|
import { allFindings, decideShellRead, denyRowAtOrBelow, foldShellReadFindings, judgeEstablishedPlan, readRootGrantCandidateOf, } from "./shell-read-judge.js";
|
|
11
12
|
import { seatOf } from "../../core/tool-name-readings.js";
|
|
@@ -326,7 +327,7 @@ async function runShellReadStation(tool, command, declared, seat, readers, estab
|
|
|
326
327
|
}
|
|
327
328
|
export async function judgeShellRead(input) {
|
|
328
329
|
const readers = input.readers ?? new Set(bashClassifyDefaultAllow());
|
|
329
|
-
const run = await runShellReadStation(input.tool ?? "Bash", input.command, input.boundary, input.seat, readers, createShellReadEstablisher(input.env, input.boundary.roots), input.env, input.signal);
|
|
330
|
+
const run = await runShellReadStation(input.tool ?? "Bash", input.command, input.boundary, input.seat, readers, createShellReadEstablisher(input.env, input.boundary.roots, { homeViews: homeViewsAt(input.env, declaredReadDenyHomes(input.env)) }), input.env, input.signal);
|
|
330
331
|
const offer = normalizeReadRootCandidate(run.verdict.readRootCandidate);
|
|
331
332
|
return {
|
|
332
333
|
plan: run.plan,
|
|
@@ -349,7 +350,7 @@ export function createShellReadStation(opts) {
|
|
|
349
350
|
const key = roots.join("\0");
|
|
350
351
|
let e = establishers.get(key);
|
|
351
352
|
if (e === undefined) {
|
|
352
|
-
e = createShellReadEstablisher(opts.env, roots, { rootsCanonical: opts.rootsCanonical === true });
|
|
353
|
+
e = createShellReadEstablisher(opts.env, roots, { rootsCanonical: opts.rootsCanonical === true, ...(opts.homeViews !== undefined ? { homeViews: opts.homeViews } : {}) });
|
|
353
354
|
establishers.set(key, e);
|
|
354
355
|
}
|
|
355
356
|
return e;
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
import type { ExecutionEnv } from "../../internal/harness-types.js";
|
|
41
41
|
import type { ShellReadPlan, ShellReadSegment } from "./shell-read-plan.js";
|
|
42
42
|
import type { EstablishedRead, ShellReadBoundary } from "./shell-read-judge.js";
|
|
43
|
+
import type { HomeViewSource } from "./read-deny-home.js";
|
|
43
44
|
/**
|
|
44
45
|
* How many directories one glob operand (or one traversal root) may enumerate, and how many names it may
|
|
45
46
|
* match, before the leg gives up and answers `unestablishable`.
|
|
@@ -82,7 +83,9 @@ export declare function establishShellReadsLexically(plan: ShellReadPlan, bounda
|
|
|
82
83
|
* The filesystem-resolving establisher for one environment and one root set. `readRoots` are the roots
|
|
83
84
|
* as declared (canonical by contract); they are resolved once more per instance because the comparison is
|
|
84
85
|
* against `realpath` output on both sides — an aliased root would otherwise refuse every read under itself.
|
|
86
|
+
* `homeViews`: the home views of the placement the deny seats were compiled at (read-deny-home.ts); absent, the declared home's.
|
|
85
87
|
*/
|
|
86
88
|
export declare function createShellReadEstablisher(env: ExecutionEnv, readRoots: readonly string[], opts?: {
|
|
87
89
|
readonly rootsCanonical?: boolean;
|
|
90
|
+
readonly homeViews?: HomeViewSource;
|
|
88
91
|
}): ShellReadEstablisher;
|
|
@@ -534,7 +534,7 @@ export function createShellReadEstablisher(env, readRoots, opts) {
|
|
|
534
534
|
if (lexicalOnly)
|
|
535
535
|
return establishShellReadsLexically(plan, boundary);
|
|
536
536
|
const roots = await canonicalRoots(signal);
|
|
537
|
-
return await withHomeViews(env, await establishPlan(plan, { ...boundary, roots }, roots, signal), signal);
|
|
537
|
+
return await withHomeViews(env, opts, await establishPlan(plan, { ...boundary, roots }, roots, signal), signal);
|
|
538
538
|
},
|
|
539
539
|
reestablish: async (previous, boundary, signal) => {
|
|
540
540
|
if (lexicalOnly)
|
|
@@ -9,12 +9,13 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import type { EstablishedPlan } from "./shell-read-establish.js";
|
|
11
11
|
import type { EstablishedRead } from "./shell-read-judge.js";
|
|
12
|
-
import { type HomeViewEnv } from "./read-deny-home.js";
|
|
12
|
+
import { type HomeViewEnv, type HomeViewsCarrier } from "./read-deny-home.js";
|
|
13
13
|
/** Every read of either establishment whose candidate's settled target set differs between the two. */
|
|
14
14
|
export declare function movedReads(previous: EstablishedPlan, again: EstablishedPlan): EstablishedRead[];
|
|
15
15
|
/**
|
|
16
16
|
* The establishment with every read that landed carrying its HOME VIEW (read-deny-home.ts) among its spellings, nested
|
|
17
17
|
* plans included: the deny judge then places a home-anchored row wherever the target IS below the home, whatever it is
|
|
18
|
-
* spelled through.
|
|
18
|
+
* spelled through. The views are `placed`'s — the home views of the placement the boundary's deny seats were compiled
|
|
19
|
+
* at. A read that did not land (lexical, unestablishable) is left as it is.
|
|
19
20
|
*/
|
|
20
|
-
export declare function withHomeViews(env: HomeViewEnv, established: EstablishedPlan, signal?: AbortSignal): Promise<EstablishedPlan>;
|
|
21
|
+
export declare function withHomeViews(env: HomeViewEnv, placed: HomeViewsCarrier | undefined, established: EstablishedPlan, signal?: AbortSignal): Promise<EstablishedPlan>;
|
|
@@ -38,8 +38,8 @@ function targetsByCandidate(e) {
|
|
|
38
38
|
function sameTargets(a, b) {
|
|
39
39
|
return a.size === b.size && [...a].every((t) => b.has(t));
|
|
40
40
|
}
|
|
41
|
-
export async function withHomeViews(env, established, signal) {
|
|
42
|
-
const views = homeViewsOf(env, signal);
|
|
41
|
+
export async function withHomeViews(env, placed, established, signal) {
|
|
42
|
+
const views = homeViewsOf(env, placed, signal);
|
|
43
43
|
const place = async (p) => {
|
|
44
44
|
const reads = new Map();
|
|
45
45
|
for (const [segment, rs] of p.reads) {
|
package/package.json
CHANGED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"repo": "core",
|
|
3
|
+
"version": "7.38.1",
|
|
4
|
+
"from": "f195abb9b3764b7d306d30ac7eee0c9ee82719f8",
|
|
5
|
+
"to": "0ee3363eac0ed4103b2598b72279b80b61f30a94",
|
|
6
|
+
"added": [],
|
|
7
|
+
"removed": [],
|
|
8
|
+
"changed": [],
|
|
9
|
+
"narrowed": [],
|
|
10
|
+
"closedSetMembers": [],
|
|
11
|
+
"closedSetsUnreadable": [],
|
|
12
|
+
"typeKeys": [],
|
|
13
|
+
"typeKeysUnreadableArms": [],
|
|
14
|
+
"typeKeysFlattenedCount": 220,
|
|
15
|
+
"declarationMoves": [],
|
|
16
|
+
"mintMoves": [],
|
|
17
|
+
"criteriaObserves": [
|
|
18
|
+
{
|
|
19
|
+
"kind": "taskEventField",
|
|
20
|
+
"name": "tool_end.errorCode",
|
|
21
|
+
"assertions": [
|
|
22
|
+
"G1.a",
|
|
23
|
+
"G1.b",
|
|
24
|
+
"G1.d",
|
|
25
|
+
"G1.e",
|
|
26
|
+
"G1.f"
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"kind": "taskEventField",
|
|
31
|
+
"name": "tool_end.output",
|
|
32
|
+
"assertions": [
|
|
33
|
+
"G1.a",
|
|
34
|
+
"G1.c",
|
|
35
|
+
"G1.d",
|
|
36
|
+
"G1.f"
|
|
37
|
+
]
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"kind": "typeMember",
|
|
41
|
+
"name": "ToolCall.id",
|
|
42
|
+
"assertions": [
|
|
43
|
+
"G2.a",
|
|
44
|
+
"G2.b"
|
|
45
|
+
]
|
|
46
|
+
}
|
|
47
|
+
],
|
|
48
|
+
"consumersHint": {
|
|
49
|
+
"cli": [],
|
|
50
|
+
"server": [],
|
|
51
|
+
"sdk": [],
|
|
52
|
+
"note": "scanned cli@64a76326 server@61d9a1d1 sdk@925ffec — a name listed is MENTIONED there today, which is evidence of consumption, not proof of it"
|
|
53
|
+
},
|
|
54
|
+
"breakingCount": 0,
|
|
55
|
+
"breakingItems": []
|
|
56
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"repo": "core",
|
|
3
|
+
"version": "7.38.2",
|
|
4
|
+
"from": "a8493dd6305fe6f8b3fea1174b56c30667f3ff1b",
|
|
5
|
+
"to": "201b3b096bc8086ff09caca61683c69acdc8bcbe",
|
|
6
|
+
"added": [],
|
|
7
|
+
"removed": [],
|
|
8
|
+
"changed": [],
|
|
9
|
+
"narrowed": [],
|
|
10
|
+
"closedSetMembers": [],
|
|
11
|
+
"closedSetsUnreadable": [],
|
|
12
|
+
"typeKeys": [],
|
|
13
|
+
"typeKeysUnreadableArms": [],
|
|
14
|
+
"typeKeysFlattenedCount": 220,
|
|
15
|
+
"declarationMoves": [],
|
|
16
|
+
"mintMoves": [],
|
|
17
|
+
"criteriaObserves": [],
|
|
18
|
+
"consumersHint": {
|
|
19
|
+
"cli": [],
|
|
20
|
+
"server": [],
|
|
21
|
+
"sdk": [],
|
|
22
|
+
"note": "scanned cli@64a76326 server@61d9a1d1 sdk@925ffec — a name listed is MENTIONED there today, which is evidence of consumption, not proof of it"
|
|
23
|
+
},
|
|
24
|
+
"breakingCount": 0,
|
|
25
|
+
"breakingItems": []
|
|
26
|
+
}
|