@sema-agent/core 7.49.3 → 7.49.5
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 +18 -0
- package/dist/agents/peer-directory.d.ts +8 -3
- package/dist/agents/peer-directory.js +5 -3
- package/dist/core/arg-summary.js +2 -1
- package/dist/core/credential-vocabulary.js +1 -1
- package/dist/core/gate-fold.js +7 -3
- package/dist/core/permission-rule-model.js +5 -5
- package/dist/core/posix-mode-face.d.ts +10 -0
- package/dist/core/posix-mode-face.js +3 -0
- package/dist/core/read-only-shell.d.ts +8 -1
- package/dist/core/read-only-shell.js +19 -4
- package/dist/engine/execution-env/node-execution-env.js +2 -1
- package/dist/stores/file/permission-rule-store.d.ts +13 -1
- package/dist/stores/file/permission-rule-store.js +40 -21
- package/dist/tools/fs/bash-readonly-classifier.js +12 -29
- package/dist/tools/fs/program-read-model.d.ts +15 -0
- package/dist/tools/fs/program-read-model.js +24 -0
- package/dist/tools/fs/program-read-model.rows.js +15 -12
- package/dist/tools/fs/shell-read-check.js +3 -3
- package/dist/tools/fs/shell-read-device.d.ts +92 -0
- package/dist/tools/fs/shell-read-device.js +109 -0
- package/dist/tools/fs/shell-read-establish.js +2 -1
- package/dist/tools/fs/shell-read-judge.js +4 -3
- package/dist/tools/fs/shell-read-plan.d.ts +5 -0
- package/dist/tools/fs/shell-read-plan.js +9 -6
- package/dist/tools/fs/shell-read-write-targets.d.ts +14 -0
- package/dist/tools/fs/shell-read-write-targets.js +63 -12
- package/package.json +1 -1
- package/wire-changes/core@7.49.4.json +69 -0
- package/wire-changes/core@7.49.5.json +104 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { denyFloorShadowsOf } from "./shell-read-judge.js";
|
|
2
|
+
import { GENERATOR_DEVICES, OPENED_PROVENANCES, passesUnasked, standardDeviceUnrebound } from "./shell-read-device.js";
|
|
2
3
|
import { renamed } from "./shell-read-word.js";
|
|
3
|
-
import { implementationsOf, programRow, selectedOptions, writeReadings } from "./program-read-model.js";
|
|
4
|
+
import { byteBoundIsSmall, implementationsOf, programRow, readArgRoles, selectedOptions, subcommandOf, writeReadings } from "./program-read-model.js";
|
|
4
5
|
import { programBasename, readProgramPosition } from "./bash-program-position.js";
|
|
5
6
|
export function programArgs(segment) {
|
|
6
7
|
const words = segment.argv.map((w) => ({ raw: w.raw, spelled: w.folded }));
|
|
@@ -11,6 +12,25 @@ export function sedBackupNames(name, suffix) {
|
|
|
11
12
|
const appended = `${name}${suffix}`;
|
|
12
13
|
return suffix.includes("*") ? [suffix.replace(/\*/g, () => name), appended] : [appended];
|
|
13
14
|
}
|
|
15
|
+
export const anyOptionWord = (words) => words.some((w) => w.startsWith("-"));
|
|
16
|
+
function writesThrough(roles, row, words) {
|
|
17
|
+
const args = words.map((w) => w.spelled);
|
|
18
|
+
if (roles.length === 0 || readArgRoles(row, args).some((e) => e.kind === "option" && e.reading === "speculative"))
|
|
19
|
+
return false;
|
|
20
|
+
return roles.every((role) => role.through === true || (role.through === "plain" && !anyOptionWord(args)));
|
|
21
|
+
}
|
|
22
|
+
export function writesOnlyStandardDevices(program, args, line) {
|
|
23
|
+
const row = programRow(program);
|
|
24
|
+
if (row === undefined)
|
|
25
|
+
return false;
|
|
26
|
+
const words = args.map((a) => ({ raw: a, spelled: a }));
|
|
27
|
+
const readings = writeReadings(row, [...args]);
|
|
28
|
+
return (readings.length > 0 &&
|
|
29
|
+
readings.every((r) => {
|
|
30
|
+
const written = r.written.filter((w) => w.role.writtenAt?.length !== 0);
|
|
31
|
+
return !r.unexplained && written.length > 0 && writesThrough(written.map((w) => w.role), row, words) && written.every((w) => standardDeviceUnrebound(w.value ?? args[w.at], line, []));
|
|
32
|
+
}));
|
|
33
|
+
}
|
|
14
34
|
const WORD_PROVENANCES = new Set(["operand", "unlisted_word", "option_value"]);
|
|
15
35
|
function writeOwnersOf(segment) {
|
|
16
36
|
const pos = readProgramPosition(segment.argv);
|
|
@@ -30,18 +50,19 @@ function writeOwnersOf(segment) {
|
|
|
30
50
|
function writeTargetsOf(segment) {
|
|
31
51
|
const out = [];
|
|
32
52
|
const writeOnly = new Set();
|
|
33
|
-
const write = (c, seats, written, child, onlyIfExists) => void out.push({ candidate: { ...c, face: "write" }, ...(seats !== undefined ? { seats } : {}), ...(written !== undefined ? { written } : {}), ...(child === true ? { child } : {}), ...(onlyIfExists !== undefined ? { onlyIfExists } : {}) });
|
|
53
|
+
const write = (c, seats, written, child, onlyIfExists, through) => void out.push({ candidate: { ...c, face: "write", ...(through === true ? { through } : {}) }, ...(seats !== undefined ? { seats } : {}), ...(written !== undefined ? { written } : {}), ...(child === true ? { child } : {}), ...(onlyIfExists !== undefined ? { onlyIfExists } : {}) });
|
|
34
54
|
for (const r of segment.redirects)
|
|
35
55
|
if (r.direction === "out" && r.target !== undefined)
|
|
36
|
-
write(r.target);
|
|
56
|
+
write(r.target, undefined, undefined, undefined, undefined, true);
|
|
37
57
|
for (const c of segment.reads)
|
|
38
58
|
if (c.provenance === "write_redirect_target")
|
|
39
|
-
write(c);
|
|
59
|
+
write(c, undefined, undefined, undefined, undefined, true);
|
|
40
60
|
const owners = writeOwnersOf(segment).map(({ row, words, program }) => {
|
|
41
61
|
const args = words.map((w) => w.spelled);
|
|
42
62
|
const all = writeReadings(row, args);
|
|
43
|
-
const
|
|
44
|
-
|
|
63
|
+
const selected = implementationsOf(row).flatMap((view) => selectedOptions(view, args, "one-implementation"));
|
|
64
|
+
const moved = [...new Set(selected.flatMap((o) => o.writesAt ?? []))];
|
|
65
|
+
return { row, words, program, all, readings: all.filter((r) => r.written.length > 0 || (r.unexplained && r.operandRole !== undefined)), override: moved.length > 0 ? moved : undefined, beyondOperands: selected.some((o) => o.effect === "writes" || o.effect === "executes") };
|
|
45
66
|
});
|
|
46
67
|
const edited = new Map();
|
|
47
68
|
for (const c of segment.reads) {
|
|
@@ -77,7 +98,7 @@ function writeTargetsOf(segment) {
|
|
|
77
98
|
const seats = stated ? [...new Set(roles.flatMap((role) => o.override ?? role.seats ?? ["landing"]))] : undefined;
|
|
78
99
|
const written = unexplained || roles.some((role) => role.writtenAt === undefined) ? undefined : [...new Set(roles.flatMap((role) => role.writtenAt ?? []))];
|
|
79
100
|
const speculative = readings < o.all.length && roles.every((role) => role.effect === "edit-in-place") ? c : undefined;
|
|
80
|
-
write(c, seats, written, undefined, speculative);
|
|
101
|
+
write(c, seats, written, undefined, speculative, !unexplained && writesThrough(roles, o.row, o.words) ? true : undefined);
|
|
81
102
|
if (roles.some((role) => role.effect === "edit-in-place") && c.expands === false)
|
|
82
103
|
edited.set(o, [...(edited.get(o) ?? []), { candidate: c, ...(speculative !== undefined ? { onlyIfExists: speculative } : {}) }]);
|
|
83
104
|
}
|
|
@@ -85,11 +106,25 @@ function writeTargetsOf(segment) {
|
|
|
85
106
|
writeOnly.add(c);
|
|
86
107
|
}
|
|
87
108
|
for (const o of owners) {
|
|
88
|
-
for (const c of copyDestinationChildren(segment, o.words, o.readings))
|
|
109
|
+
for (const c of copyDestinationChildren(segment, o.row, o.words, o.readings))
|
|
89
110
|
write(c, ["landing", "entry"], undefined, true);
|
|
90
111
|
out.push(...backupTargetsOf(edited.get(o) ?? [], o.readings, o.override));
|
|
91
112
|
}
|
|
92
|
-
|
|
113
|
+
const readWords = new Set();
|
|
114
|
+
for (const o of owners) {
|
|
115
|
+
if (!o.program)
|
|
116
|
+
continue;
|
|
117
|
+
const args = o.words.map((w) => w.spelled);
|
|
118
|
+
const found = subcommandOf(o.row, args);
|
|
119
|
+
const sub = found !== undefined && found.row.operands !== undefined ? found : undefined;
|
|
120
|
+
const at = sub === undefined ? 0 : sub.at + 1;
|
|
121
|
+
for (const e of readArgRoles(sub?.row ?? o.row, args.slice(at))) {
|
|
122
|
+
const role = e.kind === "operand" || e.kind === "value" ? e.role : undefined;
|
|
123
|
+
if (role?.kind === "path" && (role.effect === "read" || role.writtenAt?.length === 0))
|
|
124
|
+
readWords.add(o.words[at + e.at].raw);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return { targets: out, writeOnly, beyondOperands: owners.some((o) => o.beyondOperands), boundedRead: owners.some((o) => o.program && byteBoundIsSmall(o.row, o.words.map((w) => w.spelled))), readWords };
|
|
93
128
|
}
|
|
94
129
|
function backupTargetsOf(edited, readings, override) {
|
|
95
130
|
const suffixes = [...new Set(readings.flatMap((r) => r.suffixes))];
|
|
@@ -98,7 +133,7 @@ function backupTargetsOf(edited, readings, override) {
|
|
|
98
133
|
? [{ candidate: { ...renamed(f, `${f.spelled}${suffix}`), face: "write" }, seats: ["entry"], followed: { operand: f, suffix }, ...(onlyIfExists !== undefined ? { onlyIfExists } : {}) }]
|
|
99
134
|
: sedBackupNames(f.spelled, suffix).map((spelled) => ({ candidate: { ...renamed(f, spelled), face: "write" }, seats: ["entry"], ...(onlyIfExists !== undefined ? { onlyIfExists } : {}) }))));
|
|
100
135
|
}
|
|
101
|
-
function copyDestinationChildren(segment, words, readings) {
|
|
136
|
+
function copyDestinationChildren(segment, row, words, readings) {
|
|
102
137
|
const candidateOf = (raw) => segment.reads.find((c) => c.raw === raw && WORD_PROVENANCES.has(c.provenance));
|
|
103
138
|
const children = new Map();
|
|
104
139
|
for (const r of readings) {
|
|
@@ -109,6 +144,9 @@ function copyDestinationChildren(segment, words, readings) {
|
|
|
109
144
|
const destCandidate = candidateOf(dest.raw);
|
|
110
145
|
if (destCandidate !== undefined && destCandidate.expands !== false)
|
|
111
146
|
continue;
|
|
147
|
+
const destRole = r.written.find((w) => w.at === r.copy.destination.at)?.role;
|
|
148
|
+
if (destCandidate !== undefined && destRole !== undefined && passesUnasked({ ...destCandidate, face: "write", ...(writesThrough([destRole], row, words) ? { through: true } : {}) }))
|
|
149
|
+
continue;
|
|
112
150
|
for (const at of r.copy.sources) {
|
|
113
151
|
const src = words[at];
|
|
114
152
|
const source = candidateOf(src.raw);
|
|
@@ -123,8 +161,21 @@ function copyDestinationChildren(segment, words, readings) {
|
|
|
123
161
|
return [...children.values()];
|
|
124
162
|
}
|
|
125
163
|
export function judgedCandidatesOf(segment) {
|
|
126
|
-
const { targets: writes, writeOnly } = writeTargetsOf(segment);
|
|
127
|
-
const
|
|
164
|
+
const { targets: writes, writeOnly, beyondOperands, boundedRead, readWords } = writeTargetsOf(segment);
|
|
165
|
+
const throughWritten = new Set(writes.filter((w) => w.candidate.through === true && w.candidate.device === true).map((w) => w.candidate.raw));
|
|
166
|
+
const opened = (c) => {
|
|
167
|
+
if (c.provenance === "unlisted_word" && c.device === true && !readWords.has(c.raw) && !throughWritten.has(c.raw)) {
|
|
168
|
+
const { device: _unread, ...judged } = c;
|
|
169
|
+
return judged;
|
|
170
|
+
}
|
|
171
|
+
if (boundedRead && c.device !== true && c.expands === false && c.speculative === undefined && c.denyOnly !== true && GENERATOR_DEVICES.has(c.spelled) && OPENED_PROVENANCES.has(c.provenance) && (c.provenance !== "unlisted_word" || readWords.has(c.raw)))
|
|
172
|
+
return { ...c, device: true };
|
|
173
|
+
if (!beyondOperands || c.device !== true || c.provenance === "stdin_redirect")
|
|
174
|
+
return c;
|
|
175
|
+
const { device: _device, ...judged } = c;
|
|
176
|
+
return judged;
|
|
177
|
+
};
|
|
178
|
+
const reads = segment.reads.flatMap((c) => (c.provenance === "write_redirect_target" ? [] : [opened(writeOnly.has(c) ? { ...c, denyOnly: true } : c)]));
|
|
128
179
|
const plain = (cs) => cs.map((candidate) => ({ candidate }));
|
|
129
180
|
return [...plain(reads), ...plain(denyFloorShadowsOf(reads)), ...writes, ...plain(denyFloorShadowsOf(writes.map((w) => w.candidate)))];
|
|
130
181
|
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"repo": "core",
|
|
3
|
+
"version": "7.49.4",
|
|
4
|
+
"from": "33e4b503cea033b8c08b96103e4707a5f8a34573",
|
|
5
|
+
"to": "18d7fa8fa5f2d2949a3848397709cdf60920dbca",
|
|
6
|
+
"added": [],
|
|
7
|
+
"removed": [],
|
|
8
|
+
"changed": [],
|
|
9
|
+
"narrowed": [],
|
|
10
|
+
"closedSetMembers": [],
|
|
11
|
+
"closedSetsUnreadable": [],
|
|
12
|
+
"typeKeys": [],
|
|
13
|
+
"typeKeysUnreadableArms": [],
|
|
14
|
+
"typeKeysFlattenedCount": 223,
|
|
15
|
+
"signatures": [],
|
|
16
|
+
"declarationMoves": [],
|
|
17
|
+
"mintMoves": [],
|
|
18
|
+
"criteriaObserves": [
|
|
19
|
+
{
|
|
20
|
+
"kind": "typeMember",
|
|
21
|
+
"name": "AskRequest.classes",
|
|
22
|
+
"assertions": [
|
|
23
|
+
"G1.a",
|
|
24
|
+
"G2.a",
|
|
25
|
+
"G7.a"
|
|
26
|
+
]
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"kind": "typeMember",
|
|
30
|
+
"name": "AskRequest.mandated",
|
|
31
|
+
"assertions": [
|
|
32
|
+
"G1.a",
|
|
33
|
+
"G7.a",
|
|
34
|
+
"G8.a"
|
|
35
|
+
]
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"kind": "typeMember",
|
|
39
|
+
"name": "AskRequest.requiresRealApproval",
|
|
40
|
+
"assertions": [
|
|
41
|
+
"G8.a"
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"kind": "typeMember",
|
|
46
|
+
"name": "RedactionReport.findings",
|
|
47
|
+
"assertions": [
|
|
48
|
+
"G4.a",
|
|
49
|
+
"G5.a",
|
|
50
|
+
"G6.a"
|
|
51
|
+
]
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"kind": "typeMember",
|
|
55
|
+
"name": "ShellReadVerdict.finding",
|
|
56
|
+
"assertions": [
|
|
57
|
+
"G3.a"
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
],
|
|
61
|
+
"consumersHint": {
|
|
62
|
+
"cli": [],
|
|
63
|
+
"server": [],
|
|
64
|
+
"sdk": [],
|
|
65
|
+
"note": "scanned cli@26456d2d server@a0533487 sdk@f1b30d4 — a name listed is MENTIONED there today, which is evidence of consumption, not proof of it"
|
|
66
|
+
},
|
|
67
|
+
"breakingCount": 0,
|
|
68
|
+
"breakingItems": []
|
|
69
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
{
|
|
2
|
+
"repo": "core",
|
|
3
|
+
"version": "7.49.5",
|
|
4
|
+
"from": "40a79ac3341fc6750aae1664c64840a44abaa205",
|
|
5
|
+
"to": "9ba02c33f3eea253894b0132dca7ed98c390fb08",
|
|
6
|
+
"added": [],
|
|
7
|
+
"removed": [],
|
|
8
|
+
"changed": [],
|
|
9
|
+
"narrowed": [],
|
|
10
|
+
"closedSetMembers": [],
|
|
11
|
+
"closedSetsUnreadable": [],
|
|
12
|
+
"typeKeys": [],
|
|
13
|
+
"typeKeysUnreadableArms": [],
|
|
14
|
+
"typeKeysFlattenedCount": 223,
|
|
15
|
+
"signatures": [
|
|
16
|
+
{
|
|
17
|
+
"name": "FileDurableRulePartitionProvider.constructor",
|
|
18
|
+
"at": [
|
|
19
|
+
"src/stores/file/permission-rule-store.ts:671"
|
|
20
|
+
],
|
|
21
|
+
"from": [
|
|
22
|
+
"(dir: string, onError?: (message: string) => void, opts?: { dataRoot?: string; })"
|
|
23
|
+
],
|
|
24
|
+
"to": [
|
|
25
|
+
"(dir: string, onError?: (message: string) => void, opts?: { dataRoot?: string; platform?: NodeJS.Platform; })"
|
|
26
|
+
],
|
|
27
|
+
"changes": [
|
|
28
|
+
{
|
|
29
|
+
"aspect": "param",
|
|
30
|
+
"detail": "param 3 `opts` type widened: { dataRoot?: string; [ -> platform?: NodeJS.Platform; ]}",
|
|
31
|
+
"breaking": false
|
|
32
|
+
}
|
|
33
|
+
],
|
|
34
|
+
"breaking": false,
|
|
35
|
+
"criteriaCovered": false
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"name": "judgePeerRecordFile",
|
|
39
|
+
"at": [
|
|
40
|
+
"src/agents/peer-directory.ts:484"
|
|
41
|
+
],
|
|
42
|
+
"from": [
|
|
43
|
+
"(stat: { uid?: number; mode: number; isFile: boolean; size: number; }, selfUid: number | undefined): { ok: false; code: \"not_regular\" | \"foreign_owner\" | \"group_or_world_writable\" | \"too_large\"; } | { ok: true; }"
|
|
44
|
+
],
|
|
45
|
+
"to": [
|
|
46
|
+
"(stat: { uid?: number; mode: number; isFile: boolean; size: number; }, selfUid: number | undefined, platform?: NodeJS.Platform): { ok: false; code: \"not_regular\" | \"foreign_owner\" | \"group_or_world_writable\" | \"too_large\"; } | { ok: true; }"
|
|
47
|
+
],
|
|
48
|
+
"changes": [
|
|
49
|
+
{
|
|
50
|
+
"aspect": "param",
|
|
51
|
+
"detail": "+optional param `platform?: NodeJS.Platform`",
|
|
52
|
+
"breaking": false
|
|
53
|
+
}
|
|
54
|
+
],
|
|
55
|
+
"breaking": false,
|
|
56
|
+
"criteriaCovered": false
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"name": "vetPeerRegistryDirectory",
|
|
60
|
+
"at": [
|
|
61
|
+
"src/agents/peer-directory.ts:452"
|
|
62
|
+
],
|
|
63
|
+
"from": [
|
|
64
|
+
"(dir: string, opts?: { uid?: number; stopAt?: string; }): Promise<PeerRegistryDirectoryVerdict>"
|
|
65
|
+
],
|
|
66
|
+
"to": [
|
|
67
|
+
"(dir: string, opts?: { uid?: number; stopAt?: string; platform?: NodeJS.Platform; }): Promise<PeerRegistryDirectoryVerdict>"
|
|
68
|
+
],
|
|
69
|
+
"changes": [
|
|
70
|
+
{
|
|
71
|
+
"aspect": "param",
|
|
72
|
+
"detail": "param 2 `opts` type widened: …umber; stopAt?: string; [ -> platform?: NodeJS.Platform; ]}",
|
|
73
|
+
"breaking": false
|
|
74
|
+
}
|
|
75
|
+
],
|
|
76
|
+
"breaking": false,
|
|
77
|
+
"criteriaCovered": false
|
|
78
|
+
}
|
|
79
|
+
],
|
|
80
|
+
"declarationMoves": [],
|
|
81
|
+
"mintMoves": [],
|
|
82
|
+
"criteriaObserves": [
|
|
83
|
+
{
|
|
84
|
+
"kind": "typeMember",
|
|
85
|
+
"name": "AskRequest.classes",
|
|
86
|
+
"assertions": [
|
|
87
|
+
"G1.a",
|
|
88
|
+
"G2.a"
|
|
89
|
+
]
|
|
90
|
+
}
|
|
91
|
+
],
|
|
92
|
+
"consumersHint": {
|
|
93
|
+
"cli": [
|
|
94
|
+
"FileDurableRulePartitionProvider"
|
|
95
|
+
],
|
|
96
|
+
"server": [
|
|
97
|
+
"FileDurableRulePartitionProvider"
|
|
98
|
+
],
|
|
99
|
+
"sdk": [],
|
|
100
|
+
"note": "scanned cli@7006be65 server@72f3abe9 sdk@f1b30d4 — 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: 2 name(s) matched ONLY in bookkeeping files and were set aside (judgePeerRecordFile, vetPeerRegistryDirectory)"
|
|
101
|
+
},
|
|
102
|
+
"breakingCount": 0,
|
|
103
|
+
"breakingItems": []
|
|
104
|
+
}
|