@sema-agent/core 7.17.0 → 7.17.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.
Files changed (37) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/core/memory-engine/engine.js +2 -1
  3. package/dist/core/memory-engine/layout.d.ts +18 -6
  4. package/dist/core/memory-engine/layout.js +40 -21
  5. package/dist/core/physical-path.d.ts +37 -0
  6. package/dist/core/physical-path.js +30 -0
  7. package/dist/core/runner/contracts.d.ts +1 -1
  8. package/dist/core/runner/prepare-artifact.d.ts +4 -5
  9. package/dist/core/runner/prepare-artifact.js +2 -16
  10. package/dist/core/runner/prepare-policy-chain.js +2 -2
  11. package/dist/core/runner/prepare-question-face.js +2 -1
  12. package/dist/core/runner/prepare-task.js +2 -2
  13. package/dist/core/runner/run-harness-handlers.js +4 -1
  14. package/dist/core/sensitive-path-policy.js +7 -8
  15. package/dist/core/skills-directory.js +4 -3
  16. package/dist/core/spec-contract.js +5 -4
  17. package/dist/core/task-registry-shared.d.ts +5 -1
  18. package/dist/core/task-registry-shared.js +1 -0
  19. package/dist/core/tool-catalog-entries.js +1 -1
  20. package/dist/core/tool-policy.d.ts +15 -0
  21. package/dist/core/tool-policy.js +3 -0
  22. package/dist/engine/execution-env/node-execution-env.js +4 -3
  23. package/dist/index.d.ts +1 -0
  24. package/dist/index.js +1 -0
  25. package/dist/orchestration/workflow-script-store.js +9 -25
  26. package/dist/orchestration/workflow.js +6 -3
  27. package/dist/stores/cc/task-list-store.js +2 -10
  28. package/dist/stores/file/fs-atomic.d.ts +15 -18
  29. package/dist/stores/file/fs-atomic.js +4 -14
  30. package/dist/stores/file/mailbox-store.d.ts +7 -11
  31. package/dist/stores/file/mailbox-store.js +4 -11
  32. package/dist/tools/artifact/local-stub.js +4 -3
  33. package/dist/tools/fs/bash-readonly-classifier.d.ts +17 -1
  34. package/dist/tools/fs/bash-readonly-classifier.js +125 -12
  35. package/dist/tools/fs/fs-bash.js +42 -17
  36. package/package.json +1 -1
  37. package/test/export-surface.snapshot.json +5 -1
@@ -11,7 +11,7 @@ import { isRemoteExecutionEnv, hasDestroy, isIsolated } from "../../core/remote-
11
11
  import { ghRateLimitHint } from "./gh-rate-limit.js";
12
12
  import { resolveBashTimeoutCaps, bashTimeoutCapsSec, bashTimeoutArgRefusal, bashTimeoutParamDescription, envErrorDetail, bashMaxOutputChars, clipShellOutput, writeShellOverflowFile, createShellOverflowSpoolFence, shellRecoveryHint, CWD_SENTINEL, BASH_READONLY_CONFINEMENT_NOTE, } from "./fs-shared.js";
13
13
  import { PROBE_CAUSE_PATH_MAX, inlineUntrusted } from "../../core/untrusted-text.js";
14
- import { BASH_CLASSIFY_DEFAULT_ALLOW, BASH_READONLY_DEFAULT_ALLOW, coarseReadonlyCheck, classifyBoundedReadonlyPollLoopDetailed, classifyCompoundReadonlyDetailed, classifyOutOfRootReadGate, classifySimpleCommandReadBoundary, NOT_AUTO_ALLOWED, } from "./bash-readonly-classifier.js";
14
+ import { BASH_CLASSIFY_DEFAULT_ALLOW, BASH_READONLY_DEFAULT_ALLOW, coarseReadonlyCheck, classifyBoundedReadonlyPollLoopDetailed, classifyCompoundReadonlyDetailed, classifyOutOfRootReadGate, refusedCommandMayRead, classifySimpleCommandReadBoundary, NOT_AUTO_ALLOWED, } from "./bash-readonly-classifier.js";
15
15
  import { toolFace } from "../../core/tool-catalog-entries.js";
16
16
  const RECURSIVE_CAUSE_MAX_PATHS = 3;
17
17
  const RECURSIVE_READ_CAUSE_CODE = "shell.recursive_read_unbounded";
@@ -47,13 +47,16 @@ export function bashReversibilityProbe(allow, boundary) {
47
47
  const loop = classifyBoundedReadonlyPollLoopDetailed(command, allowSet, resolved);
48
48
  if (loop.reason === undefined)
49
49
  return { reversible: true };
50
- if (boundaryDeclared(loop))
50
+ if (boundaryDeclared(loop) || unjudgedRead(command, allowSet, resolved, loop))
51
51
  return { reversible: false, mandated: true };
52
52
  return { reversible: false, ...boundaryGate(detailed) };
53
53
  };
54
54
  }
55
55
  function boundaryUnread(verdict) {
56
- return (verdict.undecidedPaths !== undefined && verdict.undecidedPaths.length > 0) || (verdict.unresolvedOperands !== undefined && verdict.unresolvedOperands.length > 0);
56
+ return boundaryUndecided(verdict) || boundaryUnjudged(verdict);
57
+ }
58
+ function boundaryUndecided(verdict) {
59
+ return verdict.undecidedPaths !== undefined && verdict.undecidedPaths.length > 0;
57
60
  }
58
61
  function boundaryDeclared(verdict) {
59
62
  return denyJudgeSpoke(verdict) || verdict.outOfRootRead === true;
@@ -69,9 +72,23 @@ function isBackgroundShellCall(args) {
69
72
  return args?.run_in_background === true;
70
73
  }
71
74
  function readBoundaryMandate(command, allowSet, resolved, verdict) {
72
- if (denyJudgeSpoke(verdict))
75
+ if (resolved === undefined)
76
+ return {};
77
+ if (denyJudgeSpoke(verdict) || unjudgedRead(command, allowSet, resolved, verdict))
73
78
  return { mandated: true };
74
- return resolved !== undefined && classifyOutOfRootReadGate(command, allowSet, resolved).gated ? { mandated: true } : {};
79
+ return classifyOutOfRootReadGate(command, allowSet, resolved).gated ? { mandated: true } : {};
80
+ }
81
+ function boundaryUnjudged(verdict) {
82
+ return verdict.refusedWhole === true || (verdict.unresolvedOperands !== undefined && verdict.unresolvedOperands.length > 0);
83
+ }
84
+ function unjudgedRead(command, allowSet, resolved, verdict) {
85
+ if (verdict.unresolvedOperands !== undefined && verdict.unresolvedOperands.length > 0)
86
+ return true;
87
+ if (verdict.refusedWhole !== true)
88
+ return false;
89
+ if (refusedCommandMayRead(command, allowSet))
90
+ return true;
91
+ return resolved !== undefined && classifyOutOfRootReadGate(command, allowSet, resolved).gated;
75
92
  }
76
93
  function recursiveReadCause(detailed) {
77
94
  const recursive = detailed.recursiveReadPaths;
@@ -94,23 +111,31 @@ export function bashReadBoundaryProbe(boundary) {
94
111
  const resolved = typeof boundary === "function" ? boundary() : boundary;
95
112
  if (resolved === undefined)
96
113
  return { reversible: true };
114
+ const seatVerdict = (verdict) => {
115
+ if (boundaryDeclared(verdict) || unjudgedRead(command, allowSet, resolved, verdict)) {
116
+ const cause = recursiveReadCause(verdict);
117
+ return { reversible: false, mandated: true, ...(cause !== undefined ? { cause } : {}) };
118
+ }
119
+ if (boundaryUndecided(verdict))
120
+ return { reversible: false };
121
+ if (verdict.reason === undefined)
122
+ return { reversible: true };
123
+ return undefined;
124
+ };
97
125
  const detailed = classifyCompoundReadonlyDetailed(command, allowSet, resolved);
98
- if (boundaryDeclared(detailed)) {
99
- const cause = recursiveReadCause(detailed);
100
- return { reversible: false, mandated: true, ...(cause !== undefined ? { cause } : {}) };
101
- }
102
- if (boundaryUnread(detailed))
103
- return { reversible: false };
104
126
  if (detailed.reason === undefined)
105
- return { reversible: true };
127
+ return seatVerdict(detailed) ?? { reversible: true };
106
128
  const loop = classifyBoundedReadonlyPollLoopDetailed(command, allowSet, resolved);
107
129
  if (loop.reason === undefined)
108
- return { reversible: true };
109
- if (boundaryDeclared(loop))
130
+ return seatVerdict(loop) ?? { reversible: true };
131
+ const compoundVerdict = seatVerdict(detailed);
132
+ const loopVerdict = seatVerdict(loop);
133
+ const mandated = [compoundVerdict, loopVerdict].find((verdict) => verdict?.mandated === true);
134
+ if (mandated !== undefined)
135
+ return mandated;
136
+ if (readBoundaryMandate(command, allowSet, resolved, detailed).mandated === true)
110
137
  return { reversible: false, mandated: true };
111
- if (boundaryUnread(loop))
112
- return { reversible: false };
113
- return { reversible: true };
138
+ return compoundVerdict ?? loopVerdict ?? { reversible: true };
114
139
  };
115
140
  }
116
141
  export { FULL_SHELL_CONTRACT_ID } from "../../core/tool-catalog-entries.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sema-agent/core",
3
- "version": "7.17.0",
3
+ "version": "7.17.1",
4
4
  "description": "Stateless, task-oriented AI agent core",
5
5
  "type": "module",
6
6
  "license": "BUSL-1.1",
@@ -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": 2333,
4
+ "count": 2335,
5
5
  "exports": {
6
6
  "A2ATaskState": "type",
7
7
  "A2ATaskStateReversal": "type",
@@ -2080,6 +2080,8 @@
2080
2080
  "peerSessionBoxHandle": "function",
2081
2081
  "permissionRuleSyncContract": "function",
2082
2082
  "pgQuery": "function",
2083
+ "physicalPathOf": "function",
2084
+ "physicalPathOfExisting": "function",
2083
2085
  "planParseRepairs": "function",
2084
2086
  "precheckEditedRuleText": "function",
2085
2087
  "predictMountedToolNames": "function",
@@ -4415,6 +4417,8 @@
4415
4417
  "peerSessionBoxHandle": "advanced",
4416
4418
  "permissionRuleSyncContract": "advanced",
4417
4419
  "pgQuery": "advanced",
4420
+ "physicalPathOf": "advanced",
4421
+ "physicalPathOfExisting": "advanced",
4418
4422
  "planParseRepairs": "advanced",
4419
4423
  "precheckEditedRuleText": "advanced",
4420
4424
  "predictMountedToolNames": "advanced",