@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.
@@ -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 moved = [...new Set(implementationsOf(row).flatMap((view) => selectedOptions(view, args, "one-implementation")).flatMap((o) => o.writesAt ?? []))];
44
- return { words, program, all, readings: all.filter((r) => r.written.length > 0 || (r.unexplained && r.operandRole !== undefined)), override: moved.length > 0 ? moved : undefined };
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
- return { targets: out, writeOnly };
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 reads = segment.reads.flatMap((c) => (c.provenance === "write_redirect_target" ? [] : [writeOnly.has(c) ? { ...c, denyOnly: true } : c]));
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sema-agent/core",
3
- "version": "7.49.3",
3
+ "version": "7.49.5",
4
4
  "description": "Stateless, task-oriented AI agent core",
5
5
  "type": "module",
6
6
  "license": "BUSL-1.1",
@@ -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
+ }