@sema-agent/core 7.25.0 → 7.26.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.
Files changed (75) hide show
  1. package/CHANGELOG.md +81 -0
  2. package/dist/core/arg-summary.d.ts +0 -7
  3. package/dist/core/arg-summary.js +2 -1
  4. package/dist/core/ask-origin.d.ts +84 -0
  5. package/dist/core/ask-origin.js +31 -3
  6. package/dist/core/auto-compaction.d.ts +5 -0
  7. package/dist/core/auto-compaction.js +7 -0
  8. package/dist/core/auto-mode-directive.d.ts +45 -0
  9. package/dist/core/auto-mode-directive.js +47 -0
  10. package/dist/core/checkpoint-store.d.ts +10 -1
  11. package/dist/core/engine-notice.d.ts +10 -0
  12. package/dist/core/gate-lanes.js +18 -10
  13. package/dist/core/governance-codes.d.ts +1 -1
  14. package/dist/core/governance-codes.js +3 -0
  15. package/dist/core/hooks.d.ts +3 -0
  16. package/dist/core/mcp-probe.d.ts +122 -0
  17. package/dist/core/mcp-probe.js +132 -0
  18. package/dist/core/memory-engine/engine.d.ts +6 -1
  19. package/dist/core/memory-engine/engine.js +30 -2
  20. package/dist/core/memory-engine/index.d.ts +1 -0
  21. package/dist/core/memory-engine/index.js +1 -0
  22. package/dist/core/memory-engine/shadowing.d.ts +58 -0
  23. package/dist/core/memory-engine/shadowing.js +40 -0
  24. package/dist/core/memory-engine/tools.d.ts +33 -1
  25. package/dist/core/memory-engine/tools.js +136 -31
  26. package/dist/core/memory-engine/types.d.ts +10 -0
  27. package/dist/core/memory.d.ts +60 -0
  28. package/dist/core/memory.js +47 -2
  29. package/dist/core/permission-rule-store.d.ts +51 -8
  30. package/dist/core/permission-rule-store.js +112 -65
  31. package/dist/core/reminder-mint.d.ts +41 -0
  32. package/dist/core/reminder-mint.js +55 -0
  33. package/dist/core/runner/compaction-restate.d.ts +9 -0
  34. package/dist/core/runner/compaction-restate.js +20 -0
  35. package/dist/core/runner/contracts.d.ts +18 -1
  36. package/dist/core/runner/denial-limit-arms.js +1 -1
  37. package/dist/core/runner/permission-rule-lanes.d.ts +5 -17
  38. package/dist/core/runner/permission-rule-lanes.js +5 -23
  39. package/dist/core/runner/prepare-ask-lane.js +2 -0
  40. package/dist/core/runner/prepare-context-lane.d.ts +4 -0
  41. package/dist/core/runner/prepare-context-lane.js +7 -2
  42. package/dist/core/runner/prepare-inherited-gate.d.ts +5 -1
  43. package/dist/core/runner/prepare-inherited-gate.js +4 -2
  44. package/dist/core/runner/prepare-memory.js +47 -6
  45. package/dist/core/runner/prepare-park-ask.js +1 -0
  46. package/dist/core/runner/prepare-policy-chain.js +8 -4
  47. package/dist/core/runner/prepare-suspend-saga.d.ts +2 -0
  48. package/dist/core/runner/prepare-suspend-saga.js +3 -1
  49. package/dist/core/runner/prepare-task.js +7 -4
  50. package/dist/core/runner/run-leg.js +9 -1
  51. package/dist/core/runner/run-recovery-lanes.js +2 -2
  52. package/dist/core/runner/run-terminal-adoption.js +2 -2
  53. package/dist/core/runner/run-turn-boundary.js +2 -2
  54. package/dist/core/store-contracts/permission-rule-write-contract.d.ts +20 -0
  55. package/dist/core/store-contracts/permission-rule-write-contract.js +77 -0
  56. package/dist/core/task-result.d.ts +11 -0
  57. package/dist/core/task-spec.d.ts +31 -0
  58. package/dist/core/tool-catalog-entries.js +3 -3
  59. package/dist/core/tool-policy.d.ts +38 -0
  60. package/dist/core/tool-policy.js +35 -24
  61. package/dist/core/types.d.ts +1 -1
  62. package/dist/index.d.ts +7 -2
  63. package/dist/index.js +6 -1
  64. package/dist/stores/file/permission-rule-store.js +48 -29
  65. package/dist/tools/fs/bash-lexer.d.ts +13 -0
  66. package/dist/tools/fs/bash-lexer.js +61 -0
  67. package/dist/tools/fs/bash-program-position.d.ts +32 -3
  68. package/dist/tools/fs/bash-program-position.js +33 -2
  69. package/dist/tools/fs/bash-readonly-classifier.d.ts +6 -4
  70. package/dist/tools/fs/bash-readonly-classifier.js +55 -18
  71. package/dist/tools/fs/shell-read-plan.js +9 -11
  72. package/package.json +1 -1
  73. package/test/export-surface.snapshot.json +29 -1
  74. package/wire-changes/core@7.25.1.json +64 -0
  75. package/wire-changes/core@7.26.0.json +695 -0
@@ -35,6 +35,11 @@ export type ImageInput = {
35
35
  * shell-gated ask (`RiskDescriptor.shellGateDoctrine`) and folds across a delegation chain (max-rank: `off` <
36
36
  * `classify` < `always`). One closed set; every seat that names a doctrine spells it through this alias. */
37
37
  export type ShellGateDoctrine = "off" | "classify" | "always";
38
+ /** The approval POSTURE a host declares for a task — {@link TaskSpec.approverPosture}'s value set: a
39
+ * statement about who answers this run's approval cards, never an instruction to the gate. One word
40
+ * today (`"bypass"` — the host answers every card itself, automatically). The engine only RENDERS it,
41
+ * so adding a word here changes what the model is told and nothing else. */
42
+ export type ApproverPosture = "bypass";
38
43
  export interface TaskSpec {
39
44
  taskId?: string;
40
45
  /** The instruction / latest user message for this turn. */
@@ -924,6 +929,32 @@ export interface TaskSpec {
924
929
  * deployment's face and the resuming principal's deny bit are judged afresh on every leg.
925
930
  */
926
931
  autoModeRequested?: true;
932
+ /**
933
+ * The host's declared APPROVER POSTURE for this task — a typed fact seat, the same ownership split
934
+ * as {@link shellGate} and {@link autoModeRequested}: the service layer declares it (it is the layer
935
+ * that knows who sits at the cards), core only CONSUMES it. `"bypass"` says the host answers every
936
+ * approval card itself, automatically.
937
+ *
938
+ * **The gate does not read it.** Cards are raised, routed and recorded byte-identically with and
939
+ * without this seat — no rule is relaxed, no ask is skipped, no decision is pre-empted. The seat's
940
+ * one effect is that the ENGINE tells the model which posture the run is under, in its own marked
941
+ * `<system-reminder>` on the first turn. That is the whole point of the seat: a posture is a fact of
942
+ * the run, and a host that instead splices the sentence into the objective hands the model
943
+ * reminder-shaped text with no engine mark, which the mark declaration tells it to treat as data and
944
+ * flag. One fact, one seat, one mint.
945
+ *
946
+ * Absent ⇒ no posture declared, zero bytes rendered (byte-identical to the pre-seat shape). Only the
947
+ * literal `"bypass"` is a value: any other present value is refused at the door
948
+ * (`config.approver_posture_invalid`) rather than folded back to absence — a marshalled typo must not
949
+ * silently un-declare a posture the host meant to declare.
950
+ *
951
+ * **Inheritance / resume:** session-wide, exactly like {@link autoModeRequested} — an engine-spawned
952
+ * child inherits it through the trusted constraint chain (`InheritedGate.approverPosture`), and the
953
+ * resolved value is recorded on the checkpoint's data half so a redemption in another process still
954
+ * knows the posture without the seat being re-passed. Re-passing it is honoured; the sources fold
955
+ * seat-first.
956
+ */
957
+ approverPosture?: ApproverPosture;
927
958
  /** Task-scoped MCP servers, materialized into tools then disposed. */
928
959
  mcp?: McpServerSpec[];
929
960
  /** Task-scoped A2A peers (remote agents), whose advertised skills mount as `a2a__<peer>__<skill>`
@@ -123,9 +123,9 @@ export const TOOL_CATALOG_ENTRIES = [
123
123
  { id: "exit-plan-mode", name: "ExitPlanMode", source: "builtin", definedIn: "src/core/present-plan-tool.ts", mountedBy: ["optional"], cards: ["exit-plan-mode"], face: { family: "plan", effect: "read", contract: c("core.exit_plan_mode@1"), renderHints: { userFacingName: "", approvalCard: "plan" } } },
124
124
  { id: "enter-plan-mode", name: "EnterPlanMode", source: "builtin", definedIn: "src/core/present-plan-tool.ts", mountedBy: ["optional"], cards: ["enter-plan-mode"], face: { family: "plan", effect: "read", contract: c("core.enter_plan_mode@1") } },
125
125
  { id: "refresh-mcp-tools", name: REFRESH_MCP_TOOLS_TOOL_NAME, source: "builtin", definedIn: "src/core/runner/prepare-protocol-tools.ts", mountedBy: ["optional"], cards: [], face: { family: "protocol", effect: "read" } },
126
- { id: "memory-search", name: "memory_search", source: "builtin", definedIn: "src/core/memory-engine/tools.ts", mountedBy: ["memory"], cards: [], face: { family: "memory", effect: "read", contentOrigin: "local", contract: c("core.memory_search@1", "6"), offload: false } },
127
- { id: "memory-get", name: "memory_get", source: "builtin", definedIn: "src/core/memory-engine/tools.ts", mountedBy: ["memory"], cards: [], face: { family: "memory", effect: "read", contentOrigin: "local", contract: c("core.memory_get@1", "6"), offload: false } },
128
- { id: "memory-index", name: "memory_index", source: "builtin", definedIn: "src/core/memory-engine/tools.ts", mountedBy: ["memory"], cards: [], face: { family: "memory", effect: "read", contentOrigin: "local", contract: c("core.memory_index@1"), offload: false } },
126
+ { id: "memory-search", name: "memory_search", source: "builtin", definedIn: "src/core/memory-engine/tools.ts", mountedBy: ["memory"], cards: [], face: { family: "memory", effect: "read", contentOrigin: "local", contract: c("core.memory_search@1", "7"), offload: false } },
127
+ { id: "memory-get", name: "memory_get", source: "builtin", definedIn: "src/core/memory-engine/tools.ts", mountedBy: ["memory"], cards: [], face: { family: "memory", effect: "read", contentOrigin: "local", contract: c("core.memory_get@1", "7"), offload: false } },
128
+ { id: "memory-index", name: "memory_index", source: "builtin", definedIn: "src/core/memory-engine/tools.ts", mountedBy: ["memory"], cards: [], face: { family: "memory", effect: "read", contentOrigin: "local", contract: c("core.memory_index@1", "2"), offload: false } },
129
129
  { id: "memory-list", name: "memory_list", source: "builtin", definedIn: "src/core/shared-memory/tools.ts", mountedBy: ["memory"], cards: [], face: { family: "memory", effect: "read", contract: c("core.memory_list@1"), offload: false } },
130
130
  { id: "memory-read", name: "memory_read", source: "builtin", definedIn: "src/core/shared-memory/tools.ts", mountedBy: ["memory"], cards: [], face: { family: "memory", effect: "read", contract: c("core.memory_read@1"), offload: false } },
131
131
  { id: "cron-create", name: "CronCreate", source: "builtin", definedIn: "src/tools/scheduler-tools.ts", mountedBy: ["scheduler"], cards: ["cron-create"], face: { family: "other", effect: "write", contract: c("core.cron_create@1") } },
@@ -321,6 +321,13 @@ export type PermissionResult = {
321
321
  * in the one direction the stamp cannot reach (a caller composing its own ask) the claim is
322
322
  * tightening-only: it can make an ask outlive a rule, never turn one into an allow. */
323
323
  probeMandated?: true;
324
+ /** This ask is MANDATED — no persisted allow rule and no standing posture may retire it, only an
325
+ * answer to THIS call. ENGINE-STAMPED at the gate's single origin stamp from the ONE derivation
326
+ * the approval card's rule-offer word also reads ({@link import("./ask-origin.js").ruleClearanceOf},
327
+ * which lists the doors). TIGHTENING-ONLY: a layer below the mint may not clear one a layer above
328
+ * set, and a policy self-declaring it only opts its own ask OUT of automatic answering. Carried
329
+ * onto the approval request as {@link AskRequest.mandated}. */
330
+ mandated?: true;
324
331
  /** The probe named a directory that would clear this ask
325
332
  * ({@link import("./types.js").ReversibilityVerdict.readRootCandidate}). Display metadata like the two
326
333
  * `probe*` above; ENGINE-STAMPED and VALIDATED at the tighten, and deliberately NOT merged onto an ask
@@ -1230,6 +1237,37 @@ export interface AskRequest {
1230
1237
  * clear this ask (see that field's doc). `readonly`, filled by the gate from the decision, never a
1231
1238
  * caller/worker-settable field. */
1232
1239
  readonly requiresRealApproval?: boolean;
1240
+ /**
1241
+ * PRESENCE ONLY, and a FACT ABOUT THIS ASK: no persisted allow rule and no standing posture can
1242
+ * retire this question. ABSENT is not the inverse claim: a person's own explicit `ask` rule and a
1243
+ * matching allow rule the lane already refused both leave it absent and still block rule clearance
1244
+ * ({@link ruleOffersAbsence} words those `shadowed`). The wire twin of the
1245
+ * {@link PermissionResult} ask-arm member of the same name, minted once by the engine at the gate's
1246
+ * origin stamp and copied here by the four mint stations. The DOORS are enumerated once, at
1247
+ * {@link import("./ask-origin.js").ruleClearanceOf}: the tool seat's own egress / irreversibility
1248
+ * marks, an operator's per-call shell doctrine, the read station's structural demotion or a probe
1249
+ * that could not answer, a write the protection judge matched or could not resolve, governance
1250
+ * ({@link requiresRealApproval}), a hook's screening authority, and an ask an ANCESTOR's approver
1251
+ * decides. Not a door: a person's own explicit `ask` rule, which {@link ruleOffersAbsence} words
1252
+ * `shadowed` — a rule they wrote is speaking, and a posture answering it crosses no mandate.
1253
+ *
1254
+ * WHY a surface must read THIS member and not its neighbour. {@link ruleOffersAbsence} answers what
1255
+ * the RULE-OFFER LANE has to give, and that lane is structurally silent for any tool it does not
1256
+ * speak for, any deployment that wired no rule store and any task that cannot hold a rule — its
1257
+ * absence is not a claim (its own doc says so). Reading it as "not mandated" made two read faces of
1258
+ * one command disagree: the same out-of-root read asked as a mandated question on the shell tool and
1259
+ * as an apparently ordinary one on the monitor tool. This member is a property of the QUESTION,
1260
+ * present on every ask that carries one, whatever lane is wired.
1261
+ *
1262
+ * WHAT IT DOES NOT SAY: that no answerer may answer. An approver — a person, a hook, a deployment's
1263
+ * blanket `onAsk: "allow"` seat — resolves a mandated ask normally; {@link requiresRealApproval} is
1264
+ * the stronger, separate demand and is the one the engine's blanket seat refuses. A surface whose
1265
+ * POSTURE seat declines to auto-answer mandated cards reads this member to know which they are.
1266
+ * ABSENT is not the opposite claim on an older engine: a consumer that must tell "this engine mints
1267
+ * no such member" from "this ask is ordinary" reads the engine version, not this seat. Filled by the
1268
+ * gate, never caller/worker-settable; tightening-only.
1269
+ */
1270
+ readonly mandated?: true;
1233
1271
  /** Present ⇔ this ask is the classifier DENIAL-LIMIT fallback (see the
1234
1272
  * {@link PermissionResult} ask-arm member of the same name): the counts that tripped the bound and
1235
1273
  * this ask's own auto-deny window. Two readers: a card renders it as a countdown; {@link resolveAsk}
@@ -13,6 +13,7 @@ import { thrownText } from "./thrown-value.js";
13
13
  import { isNamespacedCoveringRuleName, namespacedRuleNameCovers, parsePermissionRule } from "./permission-rules.js";
14
14
  import { protocolOf } from "./protocol-table.js";
15
15
  import { isAbsoluteForFamily, isAbsolutePathForm, joinForFamily, normalizeAbsPathLexically, pathFamilyOf, writeTargetPath } from "../tools/fs/safety.js";
16
+ import { ASSIGNMENT_PREFIX, writtenAssignmentPrefix } from "../tools/fs/bash-program-position.js";
16
17
  export function advertisedWritableRootsSeat(seat) {
17
18
  return seat === undefined ? {} : { advertisedWritableRoots: Object.freeze([...seat.roots]) };
18
19
  }
@@ -458,6 +459,7 @@ export function combinePolicies(...policies) {
458
459
  let anyRecord = false;
459
460
  let ruleAskText;
460
461
  let probeMandateSeen = false;
462
+ let mandateSeen = false;
461
463
  let fallbackSeen;
462
464
  for (const p of policies) {
463
465
  const d = refuseOutOfContractDecision(await p.check(current, signal));
@@ -489,6 +491,8 @@ export function combinePolicies(...policies) {
489
491
  }
490
492
  if (d.action === "ask" && d.probeMandated === true)
491
493
  probeMandateSeen = true;
494
+ if (d.action === "ask" && d.mandated === true)
495
+ mandateSeen = true;
492
496
  if (d.action === "ask" && d.denialLimitFallback !== undefined && fallbackSeen === undefined)
493
497
  fallbackSeen = d.denialLimitFallback;
494
498
  }
@@ -496,7 +500,8 @@ export function combinePolicies(...policies) {
496
500
  const merged = rewrite?.updatedInput;
497
501
  const withRuleAsk = ruleAskText !== undefined && asked.matchedAskRule === undefined ? { ...asked, matchedAskRule: ruleAskText } : asked;
498
502
  const withMark = probeMandateSeen && withRuleAsk.probeMandated !== true ? { ...withRuleAsk, probeMandated: true } : withRuleAsk;
499
- const withFallback = fallbackSeen !== undefined && withMark.denialLimitFallback === undefined ? { ...withMark, denialLimitFallback: fallbackSeen, requiresRealApproval: true } : withMark;
503
+ const withMandate = mandateSeen && withMark.mandated !== true ? { ...withMark, mandated: true } : withMark;
504
+ const withFallback = fallbackSeen !== undefined && withMandate.denialLimitFallback === undefined ? { ...withMandate, denialLimitFallback: fallbackSeen, requiresRealApproval: true } : withMandate;
500
505
  return merged !== undefined ? { ...withFallback, updatedInput: merged } : withFallback;
501
506
  }
502
507
  const allowed = rewrite ?? ALLOW;
@@ -618,22 +623,28 @@ export function findUnverifiableRecursiveDelete(command, safeVars = new Set(UNVE
618
623
  }
619
624
  return false;
620
625
  };
626
+ const applyAssignmentWord = (words, at) => {
627
+ const written = writtenAssignmentPrefix(words[at]);
628
+ if (written === undefined) {
629
+ assigned.delete(words[at].replace(/\[.*$/, ""));
630
+ return;
631
+ }
632
+ const value = restOfAssignment(words, at, written.prefix.length - 1);
633
+ if ((!written.settlesWholeName && !assigned.has(written.name)) || valueIsOpaque(value, assigned, safeVars))
634
+ assigned.delete(written.name);
635
+ else
636
+ assigned.add(written.name);
637
+ if (valueEscapesRoot(value, safeVars))
638
+ assignedEscapesRoot.add(written.name);
639
+ else if (written.settlesWholeName)
640
+ assignedEscapesRoot.delete(written.name);
641
+ };
621
642
  const statements = command.replace(/\\\r?\n/g, " ").split(STATEMENT_SPLIT);
622
643
  for (const stmt of statements) {
623
644
  const tokens = stmt.trim().split(/\s+/).filter(Boolean);
624
645
  let i = 0;
625
- while (i < tokens.length && /^[A-Za-z_][A-Za-z0-9_]*=/.test(tokens[i])) {
626
- const eq = tokens[i].indexOf("=");
627
- const name = tokens[i].slice(0, eq);
628
- const value = restOfAssignment(tokens, i, eq);
629
- if (valueIsOpaque(value, assigned, safeVars))
630
- assigned.delete(name);
631
- else
632
- assigned.add(name);
633
- if (valueEscapesRoot(value, safeVars))
634
- assignedEscapesRoot.add(name);
635
- else
636
- assignedEscapesRoot.delete(name);
646
+ while (i < tokens.length && ASSIGNMENT_PREFIX.test(tokens[i])) {
647
+ applyAssignmentWord(tokens, i);
637
648
  i += assignmentTokenSpan(tokens, i);
638
649
  }
639
650
  let sawWrapper = false;
@@ -646,7 +657,7 @@ export function findUnverifiableRecursiveDelete(command, safeVars = new Set(UNVE
646
657
  if (DELETE_WRAPPERS.has(t)) {
647
658
  sawWrapper = true;
648
659
  i++;
649
- while (i < tokens.length && (/^-/.test(tokens[i]) || /^[A-Za-z_][A-Za-z0-9_]*=/.test(tokens[i])))
660
+ while (i < tokens.length && (/^-/.test(tokens[i]) || ASSIGNMENT_PREFIX.test(tokens[i])))
650
661
  i++;
651
662
  continue;
652
663
  }
@@ -672,16 +683,16 @@ export function findUnverifiableRecursiveDelete(command, safeVars = new Set(UNVE
672
683
  i = headIdx;
673
684
  const head = stripTokenEdges(tokens[i]).replace(/^\\/, "");
674
685
  const headName = head.split("/").pop() ?? head;
675
- let m;
676
- if ((m = stmt.trim().match(/^(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)=(.*)$/))) {
677
- if (valueIsOpaque(m[2], assigned, safeVars))
678
- assigned.delete(m[1]);
679
- else
680
- assigned.add(m[1]);
681
- if (valueEscapesRoot(m[2], safeVars))
682
- assignedEscapesRoot.add(m[1]);
683
- else
684
- assignedEscapesRoot.delete(m[1]);
686
+ const declStmt = stmt.trim();
687
+ const declaredWords = /^(?:export|declare|typeset|local|readonly)\b/.test(declStmt) ? declStmt.split(/\s+/).filter(Boolean).slice(1) : ASSIGNMENT_PREFIX.test(declStmt) ? [declStmt] : [];
688
+ for (let d = 0; d < declaredWords.length;) {
689
+ if (/^[-+]/.test(declaredWords[d])) {
690
+ d += 1;
691
+ continue;
692
+ }
693
+ declaredWords[d] = stripTokenEdges(declaredWords[d]);
694
+ applyAssignmentWord(declaredWords, d);
695
+ d += assignmentTokenSpan(declaredWords, d);
685
696
  }
686
697
  if (headName === "read") {
687
698
  void 0;
@@ -13,7 +13,7 @@ import type { AgentTool, ThinkingLevel, ToolInputValidationContext, ToolInputVer
13
13
  import type { Model, StreamFn } from "../internal/llm.js";
14
14
  export type { ModelRef, ModelRole, RoleSpec, ModelRoles, Brain } from "./model-seat.js";
15
15
  export { MODEL_ROLES } from "./model-seat.js";
16
- export type { StaleToolResultOffloadOptions, ImageInput, TaskSpec, ShellGateDoctrine } from "./task-spec.js";
16
+ export type { StaleToolResultOffloadOptions, ImageInput, TaskSpec, ShellGateDoctrine, ApproverPosture } from "./task-spec.js";
17
17
  export type { ToolEffect, ToolContentOrigin, ReversibilityVerdict, ReadRootGrantCandidate, ToolSpec, ToolReturn, NestedUsage, NestedUsageAccum, ToolExecuteContext } from "./tool-spec.js";
18
18
  export type { BeforeWriteRequest, BeforeWriteResult, BeforeWriteHook, TrackEditRequest, TrackEditResult, TrackFileEditHook, FileEditedNotice, FileEditedHook, HandsBandOptions } from "./hands-band.js";
19
19
  export type { AgentDefinition, SkillManifest, SkillSpec } from "./agent-definition.js";
package/dist/index.d.ts CHANGED
@@ -58,6 +58,7 @@ export { decideAutoPromote, deriveTripwire, FROZEN_DENYLIST_FLOOR, type AutoProm
58
58
  export { runCascade, type CascadeRung, type CascadeConfig, type CascadeAttempt, type CascadeRunResult, type GateVerdict, } from "./agents/cascade.js";
59
59
  export { pgQuery, mysqlQuery, sqliteQuery } from "./tools/sql-adapters.js";
60
60
  export { materializeMcpTools, MCP_PREFIX, type MaterializedMcp, type McpServerStatus, type McpRefreshResult, type McpReconnectResult } from "./core/mcp.js";
61
+ export { probeMcpServers, type McpProbeResult } from "./core/mcp-probe.js";
61
62
  export { MCP_FAILURE_KINDS, MCP_DELIVERY_VERDICTS, MCP_LIVENESS_STATES, classifyMcpFailure, type McpFailure, type McpFailureKind, type McpDelivered, type McpLivenessState, type McpServerLiveness } from "./core/mcp-failure.js";
62
63
  export { MCP_INJECTION_DROP_REASONS, MCP_INJECTION_DROP_TEXT, mcpInjectionDroppedNotice, type McpInjectionDropReason, type McpInjectionDropFacts } from "./core/mcp-injection-drop.js";
63
64
  export { askUnresolvableNotice, type AskUnresolvableFacts } from "./core/ask-unresolvable-notice.js";
@@ -220,7 +221,7 @@ export { adoptLocalDataRoot, ackAdoptionConfig, witnessAdoptionConfig, listAdopt
220
221
  export { formatHookFeedback, runToolGate, createHookEnvCapabilities, createPreToolUseConstraintPolicy, type PersistedRuleHit, type PersistedRuleHitRule, type PersistedRuleUnreadable, type PersistedRuleCoverage, type PersistedRuleAnswer, normalizePersistedRuleHit, type Hooks, type HookToolContext, type HookInvocationIdentity, type UserPromptSubmitContext, type PostToolBatchContext, type HookEnvCapabilities, type HookToolOutput, type PreToolUseResult, type PostToolUseResult, type UserPromptSubmitResult, type HookToolFailure, type PostToolUseFailureResult, type PostToolBatchCall, type PostToolBatchResult, type PreCompactContext, type PreCompactResult, type PostCompactContext, type StopFailureContext, type PermissionDeniedPayload, } from "./core/hooks.js";
221
222
  export { HOOK_FAMILIES, HOOKS_INVALID_CODE, type HookFamily, type WiringManifestHookEntry } from "./core/hook-seats.js";
222
223
  export { InMemoryMemoryStore, composeMemoryBlock, composeLayeredMemoryBlock, normalizeMemorySpec, type NormalizedMemorySpec, type MemorySpecInput, supportsConsolidation, supportsPeriodicConsolidation, firstSentence, expandLexicalTerms, lexicalSearchMatch, type Embedder, classifyPromotable, enforcePromotableWriteGate, guardedMemoryStore, MemoryGateError, MemoryProjectionError, detectSecret, enforceSecretWriteGate, enforceStructuredNoteSecretGate, type UtilityGate, type MemoryStore, type MemoryVectorMode, type ScoredMemory, type MemoryNoteHeader, type MemoryNoteRecord, type MemoryNoteType, type StructuredNoteInput, } from "./core/memory.js";
223
- export { MemoryEngine, FileMemoryEngineBackend, memoryBackendContract, assertMemoryBackendSearchEquivalence, type MemoryBackendContractHooks, buildMemoryInstruction, writableRootOf, truncateIndex, scanEntryFiles, deriveRepoKey, deriveRepoMemoryDir, deriveControlPlaneDir, deriveRepoControlPlaneDir, resolveMemoryEngineRoot, scopeDirName, ControlPlaneCorruptError, parseEntryFile, serializeEntryFile, computeEntryRev, entryFromFile, MEMORY_ORIGIN_CAUSES, committedOriginOf, originEquals, consolidationExposedFrontmatter, ambiguousOriginRepresentation, type OriginClearanceRow, type OriginClearanceEvent, type OriginClearanceShadow, committedDistilledOf, distilledEquals, type MemoryEntryDistilled, type MemoryEntryDistilledInput, CONSOLIDATION_DEFAULTS, ConsolidationRefusedError, MEMORY_SEARCH_SUPERSEDED_TAG, consolidationTypeEligible, deriveSupersededSet, memorySupersededNote, readIntentCredentials, supersessionFuseCeiling, memoryConsolidationRecommendedNotice, memoryConsolidationCommittedNotice, memoryConsolidationConflictNotice, memoryConsolidationIncompleteNotice, memoryConsolidationRefusedNotice, memoryConsolidationWithheldNotice, type ConsolidationGateRead, type ConsolidationGateRow, type ConsolidationIntent, type ConsolidationIntentCredentialRow, type ConsolidationLeaseSeat, type ConsolidationProductProposal, type ConsolidationProposal, type MemoryConsolidationOptions, type ConsolidationCommitReceipt, type ConsolidationReconcileReport, type ConsolidationResolveReceipt, type ConsolidationPlanSummary, type ConsolidationPlanFoldEvidence, type SessionMemoryStatus, DISTILLER_DEFAULT_MAX_INPUTS_PER_PRODUCT, LLM_DISTILLER_CONTRACT, LLM_DISTILLER_CONTRACT_DL2, LLM_DISTILLER_CONTRACT_DL3, LLM_DISTILLER_CONTRACTS, MEMORY_DISTILLER_CONTRACT_V1, contractGroupingDiff, driveConsolidationToFixpoint, isAliasModelId, llmPlanDistiller, mintExposurePartitionedPlan, mintLlmConsolidationPlan, MEMORY_DISTILLER_PURITY_CONTRACT_V1, detectCleanArmVerbatimLeak, type CleanArmLeakFinding, type CleanArmLeakVerdict, type MemoryDistillerPurityContract, openAiCompatChatSeat, parseJsonAnswer, planParseRepairs, sanitizeLlmGroups, scheduleUnderFuse, type ConsolidationDistillFn, type ConsolidationDriveCycleRow, type ConsolidationDriveEngine, type ConsolidationDriveResult, type ConsolidationFoldState, type DistillerCandidate, type DistillerChatAnswer, type DistillerChatFn, type DistillerChatRequest, type FuseSchedule, type LlmConsolidationPlan, type LlmConsolidationPlanArm, type LlmConsolidationPlanProduct, type LlmDistillerContract, type MintLlmConsolidationPlanResult, type PlanParseRepairs, type SanitizedLlmGroups, CONSOLIDATION_DRIVER_PLANS_DIR, CONSOLIDATION_DRIVER_RUNS_FILE, CONSOLIDATION_RUN_STOP_REASONS, archiveDistillerPlan, readConsolidationDriverRun, runMemoryConsolidationDriver, type ConsolidationDriverEngine, type ConsolidationDriverRunRow, type ConsolidationRunReceipt, type ConsolidationRunStopReason, type RunMemoryConsolidationOptions, isInstructionEntry, type MemoryEntryOrigin, type MemoryOriginCause, MEMORY_INSTRUCTION_TEMPLATE, MEMORY_RECALL_DISCIPLINE, MEMORY_PREFERENCE_DISCIPLINE, MEMORY_READONLY_NOTICE, MEMORY_CAPTURE_OPTOUT_NOTICE, memoryCaptureOptedOutNotice, memoryCaptureOptOutUnpersistedNotice, SESSION_CAPTURE_OPTOUT_DIR, markSessionCaptureOptOut, readSessionCaptureOptOut, listSessionCaptureOptOut, fileSessionCaptureRecordStore, type SessionCaptureOptOutRecord, type SessionCaptureOptOutMarkOutcome, type SessionCaptureRecordStore, readV2HeaderHints, type V2HeaderHints, LINEAGE_FILE, CHALLENGES_FILE, CHALLENGED_HISTORY_FILE, CHALLENGE_LEDGER_MAX_EVENTS, rebuildStrictControlPlaneLedger, type ControlPlaneRebuildReceipt, type StrictControlPlaneLedger, type ChallengeAssignment, type ChallengeEvent, type ChallengedHistoryRow, type LineagePendingTxn, type LineagePromotion, MEMORY_INDEX_FILENAME, MEMORY_INDEX_MAX_LINES, MEMORY_INDEX_MAX_BYTES, MEMORY_SEARCH_TOOL_NAME, MEMORY_GET_TOOL_NAME, MEMORY_INDEX_TOOL_NAME, MEMORY_ENGINE_TOOL_NAMES, type MemorySearchDetails, type MemorySearchHit, type CleanMemorySearchHit, type ExposedMemorySearchHit, MEMORY_EXPOSURE_BANNER, MEMORY_EXPOSURE_HANDLE_TAG, memoryExposureIndexRow, type MemoryGetDetails, type MemoryIndexDetails, type MemoryIndexRow, type CleanMemoryIndexRow, type ExposedMemoryIndexRow, STUB_ARCHIVED_LINE, DEFAULT_MAX_MEMORY_FILES, DEFAULT_MAX_ENTRY_DEPTH, DEFAULT_HARVEST_DEADLINE_MS, DEFAULT_HARVEST_FILE_BUDGET, MASS_DELETION_FUSE_RATIO, scanMemoryWrite, scanMemoryFileName, scanRemediation, MEMORY_FILENAME_SEGMENT_RE, renderAnnouncements, enqueueMemoryAnnouncement, drainMemoryAnnouncements, peekMemoryAnnouncements, bumpScanFuse, scanFuseCount, clearScanFuse, ANNOUNCEMENTS_FILE, MEMORY_ANNOUNCEMENTS_MAX, SCAN_FUSE_FILE, SCAN_FUSE_THRESHOLD, type MemoryAnnouncement, type ScanFinding, type MemoryEngineOptions, type MemoryInjection, type EntryProvenanceAccount, type TransferEvidence, type CommittedBinding, type CommittedEntrySnapshot, type CommittedScopeSnapshots, type EntryCustodyReport, erasureSelectHash, type EraseMemoryEntriesInput, type ErasureSelect, type ErasedBinding, type MemoryErasureAttestation, computeMemoryBundleHash, type MemoryExportBundle, type MemoryImportReport, type MemoryExportSnapshot, type MemoryBundleImportPlan, type BundleChallengeRow, type BundleLineageRow, type BundlePollutedSession, type MemoryBackend, type MemoryEntry, type MemoryEntryFrontmatter, type MemoryEntryHeader, type MemoryScopeEnumeration, type ScoredMemoryEntry, type NotePatch, type PatchReport, type MaterializedFile, type MemorySessionHandle, type HarvestReport, type HarvestRejection, type HarvestRejectionCode, type ParsedEntryFile, type ScannedEntryFile, SCOPE_SEGMENT_MAX_ENCODED, PROJECT_MARKER_PATH, encodeScopeSegment, decodeScopeSegment, parseScopeKey, formatUserScope, formatOrgScope, formatProjScope, formatUserProjScope, isPersonalScope, assertScopeContractPlacement, formatProjectMarker, parseProjectMarker, resolveProjectId, PROJECT_ID_REGEX, type ParsedScopeKey, migrateScope, type MigrateScopeReport, materializeEntriesToFiles, harvestFilesToPatches, projectionsToWriteBack, screenInboundEntries, REMOTE_HARVEST_PER_FILE_BYTES, REMOTE_MASS_DELETION_FUSE_RATIO, type RemoteMemoryFile, type RemoteMemoryBaseline, type RemoteMaterialization, type RemoteHarvestResult, type InboundEntryFinding, deriveProjectMemoryDir, deriveProjectControlDir, recordProjectIdHint, lookupProjectIdHint, PROJECT_ID_HINTS_FILE, reconcileMemoryEntries, nextSyncBaseline, mergeRecallHits, type MemorySyncCursor, type MemorySyncConflict, type MemorySyncPlan, type RecallSource, syncMemoryScope, type MemorySyncTransport, type MemorySyncRequestBody, type MemorySyncResponseBody, type MemorySyncClientConflict, type SyncMemoryScopeOptions, type MemorySyncClientResult, } from "./core/memory-engine/index.js";
224
+ export { MemoryEngine, FileMemoryEngineBackend, memoryBackendContract, assertMemoryBackendSearchEquivalence, type MemoryBackendContractHooks, buildMemoryInstruction, writableRootOf, truncateIndex, scanEntryFiles, deriveRepoKey, deriveRepoMemoryDir, deriveControlPlaneDir, deriveRepoControlPlaneDir, resolveMemoryEngineRoot, scopeDirName, ControlPlaneCorruptError, parseEntryFile, serializeEntryFile, computeEntryRev, entryFromFile, MEMORY_ORIGIN_CAUSES, committedOriginOf, originEquals, consolidationExposedFrontmatter, ambiguousOriginRepresentation, type OriginClearanceRow, type OriginClearanceEvent, type OriginClearanceShadow, committedDistilledOf, distilledEquals, type MemoryEntryDistilled, type MemoryEntryDistilledInput, CONSOLIDATION_DEFAULTS, ConsolidationRefusedError, MEMORY_SEARCH_SUPERSEDED_TAG, consolidationTypeEligible, deriveSupersededSet, memorySupersededNote, readIntentCredentials, supersessionFuseCeiling, deriveShadowedSet, memoryConsolidationRecommendedNotice, memoryConsolidationCommittedNotice, memoryConsolidationConflictNotice, memoryConsolidationIncompleteNotice, memoryConsolidationRefusedNotice, memoryConsolidationWithheldNotice, type ConsolidationGateRead, type ConsolidationGateRow, type ConsolidationIntent, type ConsolidationIntentCredentialRow, type ConsolidationLeaseSeat, type ConsolidationProductProposal, type ConsolidationProposal, type MemoryConsolidationOptions, type ConsolidationCommitReceipt, type ConsolidationReconcileReport, type ConsolidationResolveReceipt, type ConsolidationPlanSummary, type ConsolidationPlanFoldEvidence, type SessionMemoryStatus, DISTILLER_DEFAULT_MAX_INPUTS_PER_PRODUCT, LLM_DISTILLER_CONTRACT, LLM_DISTILLER_CONTRACT_DL2, LLM_DISTILLER_CONTRACT_DL3, LLM_DISTILLER_CONTRACTS, MEMORY_DISTILLER_CONTRACT_V1, contractGroupingDiff, driveConsolidationToFixpoint, isAliasModelId, llmPlanDistiller, mintExposurePartitionedPlan, mintLlmConsolidationPlan, MEMORY_DISTILLER_PURITY_CONTRACT_V1, detectCleanArmVerbatimLeak, type CleanArmLeakFinding, type CleanArmLeakVerdict, type MemoryDistillerPurityContract, openAiCompatChatSeat, parseJsonAnswer, planParseRepairs, sanitizeLlmGroups, scheduleUnderFuse, type ConsolidationDistillFn, type ConsolidationDriveCycleRow, type ConsolidationDriveEngine, type ConsolidationDriveResult, type ConsolidationFoldState, type DistillerCandidate, type DistillerChatAnswer, type DistillerChatFn, type DistillerChatRequest, type FuseSchedule, type LlmConsolidationPlan, type LlmConsolidationPlanArm, type LlmConsolidationPlanProduct, type LlmDistillerContract, type MintLlmConsolidationPlanResult, type PlanParseRepairs, type SanitizedLlmGroups, CONSOLIDATION_DRIVER_PLANS_DIR, CONSOLIDATION_DRIVER_RUNS_FILE, CONSOLIDATION_RUN_STOP_REASONS, archiveDistillerPlan, readConsolidationDriverRun, runMemoryConsolidationDriver, type ConsolidationDriverEngine, type ConsolidationDriverRunRow, type ConsolidationRunReceipt, type ConsolidationRunStopReason, type RunMemoryConsolidationOptions, isInstructionEntry, type MemoryEntryOrigin, type MemoryOriginCause, MEMORY_INSTRUCTION_TEMPLATE, MEMORY_RECALL_DISCIPLINE, MEMORY_PREFERENCE_DISCIPLINE, MEMORY_READONLY_NOTICE, MEMORY_CAPTURE_OPTOUT_NOTICE, memoryCaptureOptedOutNotice, memoryCaptureOptOutUnpersistedNotice, SESSION_CAPTURE_OPTOUT_DIR, markSessionCaptureOptOut, readSessionCaptureOptOut, listSessionCaptureOptOut, fileSessionCaptureRecordStore, type SessionCaptureOptOutRecord, type SessionCaptureOptOutMarkOutcome, type SessionCaptureRecordStore, readV2HeaderHints, type V2HeaderHints, LINEAGE_FILE, CHALLENGES_FILE, CHALLENGED_HISTORY_FILE, CHALLENGE_LEDGER_MAX_EVENTS, rebuildStrictControlPlaneLedger, type ControlPlaneRebuildReceipt, type StrictControlPlaneLedger, type ChallengeAssignment, type ChallengeEvent, type ChallengedHistoryRow, type LineagePendingTxn, type LineagePromotion, MEMORY_INDEX_FILENAME, MEMORY_INDEX_MAX_LINES, MEMORY_INDEX_MAX_BYTES, MEMORY_SEARCH_TOOL_NAME, MEMORY_GET_TOOL_NAME, MEMORY_INDEX_TOOL_NAME, MEMORY_ENGINE_TOOL_NAMES, type MemorySearchDetails, type MemorySearchHit, type CleanMemorySearchHit, type ExposedMemorySearchHit, MEMORY_EXPOSURE_BANNER, MEMORY_EXPOSURE_HANDLE_TAG, memoryExposureIndexRow, type MemoryGetDetails, type MemoryIndexDetails, type MemoryIndexRow, type CleanMemoryIndexRow, type ExposedMemoryIndexRow, STUB_ARCHIVED_LINE, DEFAULT_MAX_MEMORY_FILES, DEFAULT_MAX_ENTRY_DEPTH, DEFAULT_HARVEST_DEADLINE_MS, DEFAULT_HARVEST_FILE_BUDGET, MASS_DELETION_FUSE_RATIO, scanMemoryWrite, scanMemoryFileName, scanRemediation, MEMORY_FILENAME_SEGMENT_RE, renderAnnouncements, enqueueMemoryAnnouncement, drainMemoryAnnouncements, peekMemoryAnnouncements, bumpScanFuse, scanFuseCount, clearScanFuse, ANNOUNCEMENTS_FILE, MEMORY_ANNOUNCEMENTS_MAX, SCAN_FUSE_FILE, SCAN_FUSE_THRESHOLD, type MemoryAnnouncement, type ScanFinding, type MemoryEngineOptions, type MemoryInjection, type EntryProvenanceAccount, type TransferEvidence, type CommittedBinding, type CommittedEntrySnapshot, type CommittedScopeSnapshots, type EntryCustodyReport, erasureSelectHash, type EraseMemoryEntriesInput, type ErasureSelect, type ErasedBinding, type MemoryErasureAttestation, computeMemoryBundleHash, type MemoryExportBundle, type MemoryImportReport, type MemoryExportSnapshot, type MemoryBundleImportPlan, type BundleChallengeRow, type BundleLineageRow, type BundlePollutedSession, type MemoryBackend, type MemoryEntry, type MemoryEntryFrontmatter, type MemoryEntryHeader, type MemoryScopeEnumeration, type ScoredMemoryEntry, type NotePatch, type PatchReport, type MaterializedFile, type MemorySessionHandle, type HarvestReport, type HarvestRejection, type HarvestRejectionCode, type ParsedEntryFile, type ScannedEntryFile, SCOPE_SEGMENT_MAX_ENCODED, PROJECT_MARKER_PATH, encodeScopeSegment, decodeScopeSegment, parseScopeKey, formatUserScope, formatOrgScope, formatProjScope, formatUserProjScope, isPersonalScope, assertScopeContractPlacement, formatProjectMarker, parseProjectMarker, resolveProjectId, PROJECT_ID_REGEX, type ParsedScopeKey, migrateScope, type MigrateScopeReport, materializeEntriesToFiles, harvestFilesToPatches, projectionsToWriteBack, screenInboundEntries, REMOTE_HARVEST_PER_FILE_BYTES, REMOTE_MASS_DELETION_FUSE_RATIO, type RemoteMemoryFile, type RemoteMemoryBaseline, type RemoteMaterialization, type RemoteHarvestResult, type InboundEntryFinding, deriveProjectMemoryDir, deriveProjectControlDir, recordProjectIdHint, lookupProjectIdHint, PROJECT_ID_HINTS_FILE, reconcileMemoryEntries, nextSyncBaseline, mergeRecallHits, type MemorySyncCursor, type MemorySyncConflict, type MemorySyncPlan, type RecallSource, syncMemoryScope, type MemorySyncTransport, type MemorySyncRequestBody, type MemorySyncResponseBody, type MemorySyncClientConflict, type SyncMemoryScopeOptions, type MemorySyncClientResult, } from "./core/memory-engine/index.js";
224
225
  export { SHARED_MEMORY_READ_CAP_BYTES, SHARED_MEMORY_LIST_PAGE_SIZE, SharedMemoryStoreError, type SharedMemoryStoreProvider, type SharedMemoryStoreReader, type SharedMemoryPagedList, type SharedMemoryStoreInfo, type SharedMemoryDocumentEntry, type SharedMemorySnapshot, type SharedMemoryRequestContext, type MemoryListDetails, type MemoryReadDetails, } from "./core/shared-memory/types.js";
225
226
  export { sharedMemoryStoreContract, type SharedMemoryFixture, type SharedMemoryStoreContractHooks, } from "./core/shared-memory/contract.js";
226
227
  export { termSet, jaccardDistance, cosineDistance } from "./core/memory-vector.js";
@@ -277,12 +278,16 @@ export { toolResultStoreContract } from "./core/store-contracts/tool-result-stor
277
278
  export { fileHistoryStoreContract } from "./core/store-contracts/file-history-store-contract.js";
278
279
  export { workflowJournalStoreContract } from "./core/store-contracts/workflow-journal-store-contract.js";
279
280
  export { permissionRuleSyncContract, type PermissionRuleSyncContractHooks } from "./core/store-contracts/permission-rule-sync-contract.js";
281
+ export { permissionRuleWriteContract, type PermissionRuleWriteContractHooks } from "./core/store-contracts/permission-rule-write-contract.js";
280
282
  export { MAILBOX_CONTRACT_SCOPE, mailboxStoreContract, mailboxAckOwnershipContract, mailboxBundledOnlyContract, mailboxTombstonedRecipientContract, type MailboxTombstonedRecipientContractHooks, mailboxCrossProcessContract, type MailboxCrossProcessContractHooks, } from "./core/store-contracts/mailbox-store-contract.js";
281
283
  export { BACKGROUND_AGENT_CONTRACT_SCOPE, backgroundAgentStoreContract, backgroundAgentStoreScopesContract, } from "./core/store-contracts/background-agent-store-contract.js";
282
284
  export { PEER_DIRECTORY_CONTRACT_SCOPE, peerDirectoryContract, type PeerDirectoryContractHooks } from "./core/store-contracts/peer-directory-contract.js";
283
285
  export { type BackgroundAgentStore, type BackgroundAgentRecord, type BackgroundAgentRowSummary, type BackgroundAgentUsage, canAccessAgentRecord, STALE_RUNNING_REAP_ATTRIBUTION, BackgroundAgentStoreError, InMemoryBackgroundAgentStore, reconcileParkedAgents, queryBackgroundAgents, type BackgroundAgentQuery, } from "./core/background-agent-store.js";
284
286
  export { serveDurableAgentRowLane, buildAgentPollDetails, type AgentPollDetailsInput, } from "./core/task-registry-agent.js";
285
287
  export type { UnifiedTaskResult } from "./core/task-registry-shared.js";
288
+ export { TASK_OUTPUT_REPLAY_KINDS, type TaskOutputReplay } from "./core/task-registry-shared.js";
289
+ export { REMOVAL_LIVENESS_WORDS, type RemovalLiveness, RULE_WRITE_COMMITTED_WORDS, type RuleWriteCommitted } from "./core/permission-rule-store.js";
290
+ export { normalizeReadRootCandidate, READ_ROOT_CANDIDATE_DIR_MAX } from "./core/read-root-candidate.js";
286
291
  export { FileBackgroundAgentStore, type FileBackgroundAgentStoreOptions } from "./stores/file/background-agent-store.js";
287
292
  export { A2A_TASK_STATES, type A2ATaskState, type A2ATaskStateReversal, type A2ATaskStateReversalFaithful, type A2ATaskStateReversalLossy, toA2ATaskState, fromA2ATaskState, } from "./core/a2a-task-state.js";
288
293
  export { type WorkflowJournalStore, type WorkflowJournalEntry, InMemoryWorkflowJournalStore, callKeyOrdinal, JOURNAL_OVERSIZE_ERROR_CODE, WorkflowJournalOversizeError, assertJournalEntryFits, } from "./core/workflow-journal-store.js";
@@ -334,7 +339,7 @@ export { ROUTE_ADJUDICATION_CONFORMANCE_CORPUS, type RouteAdjudicationVector } f
334
339
  export { type BrainTimeoutConfig } from "./brain/timeout.js";
335
340
  export { createAssistantMessageEventStream } from "./internal/llm.js";
336
341
  export type { AssistantMessage, AssistantMessageEvent, CompleteSimpleFn, Context, DocumentContent, ImageContent, Message, StopReason, StreamFn, TextContent, ThinkingContent, ToolCall, ToolResultMessage, Usage, UserMessage, } from "./internal/llm.js";
337
- export type { AgentDefinition, BeforeWriteHook, BeforeWriteRequest, BeforeWriteResult, TrackFileEditHook, TrackEditRequest, TrackEditResult, FileEditedHook, FileEditedNotice, HandsBandOptions, Brain, BrainStatus, BrainStatusPhase, BrainRetryErrClass, ImageInput, McpElicitRequest, McpElicitResponse, McpServerSpec, A2aServerSpec, OnElicit, Model, ModelRef, ProjectMemoryLoad, RunnerDeps, ResumePreflightInfo, ResumePreflightVerdict, EngineNotice, RuntimeCaps, BackgroundChildEvent, DelegationLifecycleEvent, SkillManifest, SkillSpec, TaskEvent, TaskEventIdentity, ToolActivity, TaskLimits, StaleToolResultOffloadOptions, TaskResult, TerminalCause, PausedCause, EffectiveMemoryScopes, RemoteEnvFailureNote, TaskSpec, ShellGateDoctrine, TaskStatus, TaskStream, CompactOutcome, ThinkingLevel, ToolExecuteContext, ToolReturn, ToolSpec, ToolInputVerdict, ToolInputValidationContext, ReversibilityVerdict, ReadRootGrantCandidate, ToolEffect, ToolContentOrigin, WorkflowGovernanceBaseline, DelegationTaskType, } from "./core/types.js";
342
+ export type { AgentDefinition, BeforeWriteHook, BeforeWriteRequest, BeforeWriteResult, TrackFileEditHook, TrackEditRequest, TrackEditResult, FileEditedHook, FileEditedNotice, HandsBandOptions, Brain, BrainStatus, BrainStatusPhase, BrainRetryErrClass, ImageInput, McpElicitRequest, McpElicitResponse, McpServerSpec, A2aServerSpec, OnElicit, Model, ModelRef, ProjectMemoryLoad, RunnerDeps, ResumePreflightInfo, ResumePreflightVerdict, EngineNotice, RuntimeCaps, BackgroundChildEvent, DelegationLifecycleEvent, SkillManifest, SkillSpec, TaskEvent, TaskEventIdentity, ToolActivity, TaskLimits, StaleToolResultOffloadOptions, TaskResult, TerminalCause, PausedCause, EffectiveMemoryScopes, RemoteEnvFailureNote, TaskSpec, ShellGateDoctrine, ApproverPosture, TaskStatus, TaskStream, CompactOutcome, ThinkingLevel, ToolExecuteContext, ToolReturn, ToolSpec, ToolInputVerdict, ToolInputValidationContext, ReversibilityVerdict, ReadRootGrantCandidate, ToolEffect, ToolContentOrigin, WorkflowGovernanceBaseline, DelegationTaskType, } from "./core/types.js";
338
343
  export { Type } from "typebox";
339
344
  export type { TSchema, Static } from "typebox";
340
345
  export { explainPromptAssembly, describeDefaultPack, type DefaultPackDescription, type ExplainInput } from "./prompt-assembly/explain.js";
package/dist/index.js CHANGED
@@ -44,6 +44,7 @@ export { decideAutoPromote, deriveTripwire, FROZEN_DENYLIST_FLOOR, } from "./cor
44
44
  export { runCascade, } from "./agents/cascade.js";
45
45
  export { pgQuery, mysqlQuery, sqliteQuery } from "./tools/sql-adapters.js";
46
46
  export { materializeMcpTools, MCP_PREFIX } from "./core/mcp.js";
47
+ export { probeMcpServers } from "./core/mcp-probe.js";
47
48
  export { MCP_FAILURE_KINDS, MCP_DELIVERY_VERDICTS, MCP_LIVENESS_STATES, classifyMcpFailure } from "./core/mcp-failure.js";
48
49
  export { MCP_INJECTION_DROP_REASONS, MCP_INJECTION_DROP_TEXT, mcpInjectionDroppedNotice } from "./core/mcp-injection-drop.js";
49
50
  export { askUnresolvableNotice } from "./core/ask-unresolvable-notice.js";
@@ -176,7 +177,7 @@ export { adoptLocalDataRoot, ackAdoptionConfig, witnessAdoptionConfig, listAdopt
176
177
  export { formatHookFeedback, runToolGate, createHookEnvCapabilities, createPreToolUseConstraintPolicy, normalizePersistedRuleHit, } from "./core/hooks.js";
177
178
  export { HOOK_FAMILIES, HOOKS_INVALID_CODE } from "./core/hook-seats.js";
178
179
  export { InMemoryMemoryStore, composeMemoryBlock, composeLayeredMemoryBlock, normalizeMemorySpec, supportsConsolidation, supportsPeriodicConsolidation, firstSentence, expandLexicalTerms, lexicalSearchMatch, classifyPromotable, enforcePromotableWriteGate, guardedMemoryStore, MemoryGateError, MemoryProjectionError, detectSecret, enforceSecretWriteGate, enforceStructuredNoteSecretGate, } from "./core/memory.js";
179
- export { MemoryEngine, FileMemoryEngineBackend, memoryBackendContract, assertMemoryBackendSearchEquivalence, buildMemoryInstruction, writableRootOf, truncateIndex, scanEntryFiles, deriveRepoKey, deriveRepoMemoryDir, deriveControlPlaneDir, deriveRepoControlPlaneDir, resolveMemoryEngineRoot, scopeDirName, ControlPlaneCorruptError, parseEntryFile, serializeEntryFile, computeEntryRev, entryFromFile, MEMORY_ORIGIN_CAUSES, committedOriginOf, originEquals, consolidationExposedFrontmatter, ambiguousOriginRepresentation, committedDistilledOf, distilledEquals, CONSOLIDATION_DEFAULTS, ConsolidationRefusedError, MEMORY_SEARCH_SUPERSEDED_TAG, consolidationTypeEligible, deriveSupersededSet, memorySupersededNote, readIntentCredentials, supersessionFuseCeiling, memoryConsolidationRecommendedNotice, memoryConsolidationCommittedNotice, memoryConsolidationConflictNotice, memoryConsolidationIncompleteNotice, memoryConsolidationRefusedNotice, memoryConsolidationWithheldNotice, DISTILLER_DEFAULT_MAX_INPUTS_PER_PRODUCT, LLM_DISTILLER_CONTRACT, LLM_DISTILLER_CONTRACT_DL2, LLM_DISTILLER_CONTRACT_DL3, LLM_DISTILLER_CONTRACTS, MEMORY_DISTILLER_CONTRACT_V1, contractGroupingDiff, driveConsolidationToFixpoint, isAliasModelId, llmPlanDistiller, mintExposurePartitionedPlan, mintLlmConsolidationPlan, MEMORY_DISTILLER_PURITY_CONTRACT_V1, detectCleanArmVerbatimLeak, openAiCompatChatSeat, parseJsonAnswer, planParseRepairs, sanitizeLlmGroups, scheduleUnderFuse, CONSOLIDATION_DRIVER_PLANS_DIR, CONSOLIDATION_DRIVER_RUNS_FILE, CONSOLIDATION_RUN_STOP_REASONS, archiveDistillerPlan, readConsolidationDriverRun, runMemoryConsolidationDriver, isInstructionEntry, MEMORY_INSTRUCTION_TEMPLATE, MEMORY_RECALL_DISCIPLINE, MEMORY_PREFERENCE_DISCIPLINE, MEMORY_READONLY_NOTICE, MEMORY_CAPTURE_OPTOUT_NOTICE, memoryCaptureOptedOutNotice, memoryCaptureOptOutUnpersistedNotice, SESSION_CAPTURE_OPTOUT_DIR, markSessionCaptureOptOut, readSessionCaptureOptOut, listSessionCaptureOptOut, fileSessionCaptureRecordStore, readV2HeaderHints, LINEAGE_FILE, CHALLENGES_FILE, CHALLENGED_HISTORY_FILE, CHALLENGE_LEDGER_MAX_EVENTS, rebuildStrictControlPlaneLedger, MEMORY_INDEX_FILENAME, MEMORY_INDEX_MAX_LINES, MEMORY_INDEX_MAX_BYTES, MEMORY_SEARCH_TOOL_NAME, MEMORY_GET_TOOL_NAME, MEMORY_INDEX_TOOL_NAME, MEMORY_ENGINE_TOOL_NAMES, MEMORY_EXPOSURE_BANNER, MEMORY_EXPOSURE_HANDLE_TAG, memoryExposureIndexRow, STUB_ARCHIVED_LINE, DEFAULT_MAX_MEMORY_FILES, DEFAULT_MAX_ENTRY_DEPTH, DEFAULT_HARVEST_DEADLINE_MS, DEFAULT_HARVEST_FILE_BUDGET, MASS_DELETION_FUSE_RATIO, scanMemoryWrite, scanMemoryFileName, scanRemediation, MEMORY_FILENAME_SEGMENT_RE, renderAnnouncements, enqueueMemoryAnnouncement, drainMemoryAnnouncements, peekMemoryAnnouncements, bumpScanFuse, scanFuseCount, clearScanFuse, ANNOUNCEMENTS_FILE, MEMORY_ANNOUNCEMENTS_MAX, SCAN_FUSE_FILE, SCAN_FUSE_THRESHOLD, erasureSelectHash, computeMemoryBundleHash, SCOPE_SEGMENT_MAX_ENCODED, PROJECT_MARKER_PATH, encodeScopeSegment, decodeScopeSegment, parseScopeKey, formatUserScope, formatOrgScope, formatProjScope, formatUserProjScope, isPersonalScope, assertScopeContractPlacement, formatProjectMarker, parseProjectMarker, resolveProjectId, PROJECT_ID_REGEX, migrateScope, materializeEntriesToFiles, harvestFilesToPatches, projectionsToWriteBack, screenInboundEntries, REMOTE_HARVEST_PER_FILE_BYTES, REMOTE_MASS_DELETION_FUSE_RATIO, deriveProjectMemoryDir, deriveProjectControlDir, recordProjectIdHint, lookupProjectIdHint, PROJECT_ID_HINTS_FILE, reconcileMemoryEntries, nextSyncBaseline, mergeRecallHits, syncMemoryScope, } from "./core/memory-engine/index.js";
180
+ export { MemoryEngine, FileMemoryEngineBackend, memoryBackendContract, assertMemoryBackendSearchEquivalence, buildMemoryInstruction, writableRootOf, truncateIndex, scanEntryFiles, deriveRepoKey, deriveRepoMemoryDir, deriveControlPlaneDir, deriveRepoControlPlaneDir, resolveMemoryEngineRoot, scopeDirName, ControlPlaneCorruptError, parseEntryFile, serializeEntryFile, computeEntryRev, entryFromFile, MEMORY_ORIGIN_CAUSES, committedOriginOf, originEquals, consolidationExposedFrontmatter, ambiguousOriginRepresentation, committedDistilledOf, distilledEquals, CONSOLIDATION_DEFAULTS, ConsolidationRefusedError, MEMORY_SEARCH_SUPERSEDED_TAG, consolidationTypeEligible, deriveSupersededSet, memorySupersededNote, readIntentCredentials, supersessionFuseCeiling, deriveShadowedSet, memoryConsolidationRecommendedNotice, memoryConsolidationCommittedNotice, memoryConsolidationConflictNotice, memoryConsolidationIncompleteNotice, memoryConsolidationRefusedNotice, memoryConsolidationWithheldNotice, DISTILLER_DEFAULT_MAX_INPUTS_PER_PRODUCT, LLM_DISTILLER_CONTRACT, LLM_DISTILLER_CONTRACT_DL2, LLM_DISTILLER_CONTRACT_DL3, LLM_DISTILLER_CONTRACTS, MEMORY_DISTILLER_CONTRACT_V1, contractGroupingDiff, driveConsolidationToFixpoint, isAliasModelId, llmPlanDistiller, mintExposurePartitionedPlan, mintLlmConsolidationPlan, MEMORY_DISTILLER_PURITY_CONTRACT_V1, detectCleanArmVerbatimLeak, openAiCompatChatSeat, parseJsonAnswer, planParseRepairs, sanitizeLlmGroups, scheduleUnderFuse, CONSOLIDATION_DRIVER_PLANS_DIR, CONSOLIDATION_DRIVER_RUNS_FILE, CONSOLIDATION_RUN_STOP_REASONS, archiveDistillerPlan, readConsolidationDriverRun, runMemoryConsolidationDriver, isInstructionEntry, MEMORY_INSTRUCTION_TEMPLATE, MEMORY_RECALL_DISCIPLINE, MEMORY_PREFERENCE_DISCIPLINE, MEMORY_READONLY_NOTICE, MEMORY_CAPTURE_OPTOUT_NOTICE, memoryCaptureOptedOutNotice, memoryCaptureOptOutUnpersistedNotice, SESSION_CAPTURE_OPTOUT_DIR, markSessionCaptureOptOut, readSessionCaptureOptOut, listSessionCaptureOptOut, fileSessionCaptureRecordStore, readV2HeaderHints, LINEAGE_FILE, CHALLENGES_FILE, CHALLENGED_HISTORY_FILE, CHALLENGE_LEDGER_MAX_EVENTS, rebuildStrictControlPlaneLedger, MEMORY_INDEX_FILENAME, MEMORY_INDEX_MAX_LINES, MEMORY_INDEX_MAX_BYTES, MEMORY_SEARCH_TOOL_NAME, MEMORY_GET_TOOL_NAME, MEMORY_INDEX_TOOL_NAME, MEMORY_ENGINE_TOOL_NAMES, MEMORY_EXPOSURE_BANNER, MEMORY_EXPOSURE_HANDLE_TAG, memoryExposureIndexRow, STUB_ARCHIVED_LINE, DEFAULT_MAX_MEMORY_FILES, DEFAULT_MAX_ENTRY_DEPTH, DEFAULT_HARVEST_DEADLINE_MS, DEFAULT_HARVEST_FILE_BUDGET, MASS_DELETION_FUSE_RATIO, scanMemoryWrite, scanMemoryFileName, scanRemediation, MEMORY_FILENAME_SEGMENT_RE, renderAnnouncements, enqueueMemoryAnnouncement, drainMemoryAnnouncements, peekMemoryAnnouncements, bumpScanFuse, scanFuseCount, clearScanFuse, ANNOUNCEMENTS_FILE, MEMORY_ANNOUNCEMENTS_MAX, SCAN_FUSE_FILE, SCAN_FUSE_THRESHOLD, erasureSelectHash, computeMemoryBundleHash, SCOPE_SEGMENT_MAX_ENCODED, PROJECT_MARKER_PATH, encodeScopeSegment, decodeScopeSegment, parseScopeKey, formatUserScope, formatOrgScope, formatProjScope, formatUserProjScope, isPersonalScope, assertScopeContractPlacement, formatProjectMarker, parseProjectMarker, resolveProjectId, PROJECT_ID_REGEX, migrateScope, materializeEntriesToFiles, harvestFilesToPatches, projectionsToWriteBack, screenInboundEntries, REMOTE_HARVEST_PER_FILE_BYTES, REMOTE_MASS_DELETION_FUSE_RATIO, deriveProjectMemoryDir, deriveProjectControlDir, recordProjectIdHint, lookupProjectIdHint, PROJECT_ID_HINTS_FILE, reconcileMemoryEntries, nextSyncBaseline, mergeRecallHits, syncMemoryScope, } from "./core/memory-engine/index.js";
180
181
  export { SHARED_MEMORY_READ_CAP_BYTES, SHARED_MEMORY_LIST_PAGE_SIZE, SharedMemoryStoreError, } from "./core/shared-memory/types.js";
181
182
  export { sharedMemoryStoreContract, } from "./core/shared-memory/contract.js";
182
183
  export { termSet, jaccardDistance, cosineDistance } from "./core/memory-vector.js";
@@ -231,11 +232,15 @@ export { toolResultStoreContract } from "./core/store-contracts/tool-result-stor
231
232
  export { fileHistoryStoreContract } from "./core/store-contracts/file-history-store-contract.js";
232
233
  export { workflowJournalStoreContract } from "./core/store-contracts/workflow-journal-store-contract.js";
233
234
  export { permissionRuleSyncContract } from "./core/store-contracts/permission-rule-sync-contract.js";
235
+ export { permissionRuleWriteContract } from "./core/store-contracts/permission-rule-write-contract.js";
234
236
  export { MAILBOX_CONTRACT_SCOPE, mailboxStoreContract, mailboxAckOwnershipContract, mailboxBundledOnlyContract, mailboxTombstonedRecipientContract, mailboxCrossProcessContract, } from "./core/store-contracts/mailbox-store-contract.js";
235
237
  export { BACKGROUND_AGENT_CONTRACT_SCOPE, backgroundAgentStoreContract, backgroundAgentStoreScopesContract, } from "./core/store-contracts/background-agent-store-contract.js";
236
238
  export { PEER_DIRECTORY_CONTRACT_SCOPE, peerDirectoryContract } from "./core/store-contracts/peer-directory-contract.js";
237
239
  export { canAccessAgentRecord, STALE_RUNNING_REAP_ATTRIBUTION, BackgroundAgentStoreError, InMemoryBackgroundAgentStore, reconcileParkedAgents, queryBackgroundAgents, } from "./core/background-agent-store.js";
238
240
  export { serveDurableAgentRowLane, buildAgentPollDetails, } from "./core/task-registry-agent.js";
241
+ export { TASK_OUTPUT_REPLAY_KINDS } from "./core/task-registry-shared.js";
242
+ export { REMOVAL_LIVENESS_WORDS, RULE_WRITE_COMMITTED_WORDS } from "./core/permission-rule-store.js";
243
+ export { normalizeReadRootCandidate, READ_ROOT_CANDIDATE_DIR_MAX } from "./core/read-root-candidate.js";
239
244
  export { FileBackgroundAgentStore } from "./stores/file/background-agent-store.js";
240
245
  export { A2A_TASK_STATES, toA2ATaskState, fromA2ATaskState, } from "./core/a2a-task-state.js";
241
246
  export { InMemoryWorkflowJournalStore, callKeyOrdinal, JOURNAL_OVERSIZE_ERROR_CODE, WorkflowJournalOversizeError, assertJournalEntryFits, } from "./core/workflow-journal-store.js";
@@ -2,7 +2,7 @@ import { closeSync, constants as FS, existsSync, fsyncSync, lstatSync, mkdirSync
2
2
  import { join } from "node:path";
3
3
  import { createHash, randomBytes } from "node:crypto";
4
4
  import { isRuleBehavior } from "../../core/permission-rule-model.js";
5
- import { PERMISSION_RULE_WRITER, applySyncJoin, applyTombstones, assertDeleteDeltaCarriesNoAdd, assertRedemptionNotQuarantined, assertWriteDeltaScopeDurable, foldDelta, } from "../../core/permission-rule-store.js";
5
+ import { PERMISSION_RULE_WRITER, applySyncJoin, applyTombstones, assertDeleteDeltaCarriesNoAdd, assertRedemptionNotQuarantined, assertWriteDeltaScopeDurable, foldDelta, unknownRuleWriteDeltaError, } from "../../core/permission-rule-store.js";
6
6
  import { canonicalize } from "../../core/canonical-json.js";
7
7
  import { BootLock } from "./fs-atomic.js";
8
8
  import { assertAdoptionBootGate } from "./adoption/marker.js";
@@ -284,36 +284,55 @@ class FileDurableRulePartition {
284
284
  const cur = this.current();
285
285
  if (cur.rev !== opts.expectedRev)
286
286
  return { conflict: true, rev: cur.rev };
287
- if (delta.kind === "sync-join") {
288
- const { next, report } = applySyncJoin({
289
- actor: cur.actor,
290
- counter: cur.counter,
291
- rules: cur.rules,
292
- tombstones: cur.tombstones,
293
- quarantined: cur.quarantined ?? [],
294
- ...(cur.sync?.observedVector !== undefined ? { observedVector: cur.sync.observedVector } : {}),
295
- }, delta, Date.now());
296
- const landed = {
297
- ...cur,
298
- rev: cur.rev + 1,
299
- rules: next.rules,
300
- tombstones: next.tombstones,
301
- sync: {
302
- ...(next.observedVector !== undefined ? { observedVector: next.observedVector } : {}),
303
- lastRoundAtMs: Date.now(),
304
- },
305
- ...(next.quarantined.length > 0 ? { quarantined: next.quarantined } : {}),
306
- };
307
- if (!this.writeAndVerify(landed)) {
308
- throw new Error("the permission-rule store did not survive its own write; the change was not committed");
287
+ let next;
288
+ switch (delta.kind) {
289
+ case "sync-join": {
290
+ const { next: joined, report } = applySyncJoin({
291
+ actor: cur.actor,
292
+ counter: cur.counter,
293
+ rules: cur.rules,
294
+ tombstones: cur.tombstones,
295
+ quarantined: cur.quarantined ?? [],
296
+ ...(cur.sync?.observedVector !== undefined ? { observedVector: cur.sync.observedVector } : {}),
297
+ }, delta, Date.now());
298
+ const landed = {
299
+ ...cur,
300
+ rev: cur.rev + 1,
301
+ rules: joined.rules,
302
+ tombstones: joined.tombstones,
303
+ sync: {
304
+ ...(joined.observedVector !== undefined ? { observedVector: joined.observedVector } : {}),
305
+ lastRoundAtMs: Date.now(),
306
+ },
307
+ ...(joined.quarantined.length > 0 ? { quarantined: joined.quarantined } : {}),
308
+ };
309
+ if (!this.writeAndVerify(landed)) {
310
+ throw new Error("the permission-rule store did not survive its own write; the change was not committed");
311
+ }
312
+ return { rev: cur.rev + 1, sync: report };
313
+ }
314
+ case "redemption-add": {
315
+ assertWriteDeltaScopeDurable(delta);
316
+ assertRedemptionNotQuarantined(cur.quarantined ?? [], delta);
317
+ next = { ...cur, rev: cur.rev + 1, rules: foldDelta(cur.rules, delta) };
318
+ break;
319
+ }
320
+ case "tighten-add": {
321
+ assertWriteDeltaScopeDurable(delta);
322
+ next = { ...cur, rev: cur.rev + 1, rules: foldDelta(cur.rules, delta) };
323
+ break;
324
+ }
325
+ case "tighten-delete": {
326
+ assertWriteDeltaScopeDurable(delta);
327
+ assertDeleteDeltaCarriesNoAdd(delta);
328
+ next = { ...cur, rev: cur.rev + 1, tombstones: [...cur.tombstones, delta.tombstone] };
329
+ break;
330
+ }
331
+ default: {
332
+ const unhandled = delta;
333
+ throw unknownRuleWriteDeltaError(unhandled);
309
334
  }
310
- return { rev: cur.rev + 1, sync: report };
311
335
  }
312
- const next = delta.kind === "redemption-add"
313
- ? (assertWriteDeltaScopeDurable(delta), assertRedemptionNotQuarantined(cur.quarantined ?? [], delta), { ...cur, rev: cur.rev + 1, rules: foldDelta(cur.rules, delta) })
314
- : delta.kind === "tighten-add"
315
- ? (assertWriteDeltaScopeDurable(delta), { ...cur, rev: cur.rev + 1, rules: foldDelta(cur.rules, delta) })
316
- : (assertWriteDeltaScopeDurable(delta), assertDeleteDeltaCarriesNoAdd(delta), { ...cur, rev: cur.rev + 1, tombstones: [...cur.tombstones, delta.tombstone] });
317
336
  if (!this.writeAndVerify(next)) {
318
337
  throw new Error("the permission-rule store did not survive its own write; the change was not committed");
319
338
  }
@@ -93,6 +93,19 @@ export interface SegmentTokens {
93
93
  * judges words sees "this word carries text the shell computes" rather than the computing text itself. */
94
94
  export declare const SUBSTITUTION_PLACEHOLDER = " subst";
95
95
  export type QuoteOpen = '"' | "'" | undefined;
96
+ /**
97
+ * Does the `$` at `at` OPEN a quote form (`$'…'` / `$"…"`)? ONE question, asked by every walker that has to
98
+ * answer it — the word scan here and the expansion scan in the classifier — because a `$` one of them reads
99
+ * as escaped and the other as bare yields two different words for the same text, and the judge then compares
100
+ * the wrong one. Escaped means an ODD run of backslashes in front of it: `\$'y'` is a literal `$`, while
101
+ * `x\\$'y'` is a literal backslash followed by a real ANSI-C quote (both read off /bin/bash). Counting the
102
+ * run is what a one-character peek behind cannot do.
103
+ */
104
+ export declare function dollarOpensQuote(text: string, at: number): boolean;
105
+ /** The `'` that CLOSES the ANSI-C quote opened at `open`, or `undefined` when none does. `\'` does not close
106
+ * one — the single place a quote region honours a backslash, and a pairing walk blind to it reads the real
107
+ * closing quote as an OPENING one and everything after as quoted, which hides an expansion the shell performs. */
108
+ export declare function ansiCQuoteClose(source: string, open: number): number | undefined;
96
109
  /**
97
110
  * Which QUOTE holds each character of `s`, by the same pairing rule the lexer walks with, and the boolean view
98
111
  * of it. The pairing quote characters themselves belong to the region they bound — they are not operators
@@ -4,11 +4,44 @@ function quoteStep(open, ch) {
4
4
  return ch === '"' || ch === "'" ? ch : undefined;
5
5
  return open === ch ? undefined : open;
6
6
  }
7
+ export function dollarOpensQuote(text, at) {
8
+ const next = text[at + 1];
9
+ if (next !== "'" && next !== '"')
10
+ return false;
11
+ let run = 0;
12
+ for (let k = at - 1; k >= 0 && text[k] === "\\"; k--)
13
+ run += 1;
14
+ return run % 2 === 0;
15
+ }
16
+ export function ansiCQuoteClose(source, open) {
17
+ for (let i = open + 1; i < source.length; i++) {
18
+ if (source[i] === "\\") {
19
+ i += 1;
20
+ continue;
21
+ }
22
+ if (source[i] === "'")
23
+ return i;
24
+ }
25
+ return undefined;
26
+ }
7
27
  export function quoteMask(s) {
8
28
  const openedBy = new Array(s.length).fill(undefined);
9
29
  const quoted = new Array(s.length).fill(false);
10
30
  let open;
11
31
  for (let i = 0; i < s.length; i++) {
32
+ if (open === undefined && s[i] === "$" && s[i + 1] === "'") {
33
+ const close = ansiCQuoteClose(s, i + 1);
34
+ for (let k = i; k <= (close ?? s.length - 1); k++) {
35
+ openedBy[k] = "'";
36
+ quoted[k] = true;
37
+ }
38
+ if (close === undefined) {
39
+ open = "'";
40
+ break;
41
+ }
42
+ i = close;
43
+ continue;
44
+ }
12
45
  const before = open;
13
46
  open = quoteStep(open, s[i]);
14
47
  const holds = before ?? open;
@@ -32,6 +65,13 @@ function tildeIsLiteral(raw) {
32
65
  }
33
66
  return false;
34
67
  }
68
+ function ansiCBody(source, open) {
69
+ const close = ansiCQuoteClose(source, open);
70
+ if (close === undefined)
71
+ return undefined;
72
+ const body = source.slice(open + 1, close);
73
+ return body.includes("\\") ? { unreadable: true, close } : { text: body, close };
74
+ }
35
75
  export function wordsOf(segment) {
36
76
  const folded = [];
37
77
  const raw = [];
@@ -310,6 +350,27 @@ function scan(source, opts, quotesLiteral) {
310
350
  i = j;
311
351
  }
312
352
  const ch = source[i];
353
+ if (!quotesLiteral && ch === "$" && !inSingle && !inDouble && dollarOpensQuote(source, i)) {
354
+ const q = next(i);
355
+ if (source[q] === '"') {
356
+ raw += ch;
357
+ started = true;
358
+ i = q - 1;
359
+ continue;
360
+ }
361
+ if (source[q] === "'") {
362
+ const ansi = ansiCBody(source, q);
363
+ if (ansi === undefined)
364
+ return { reject: "an ANSI-C quoted word never closes" };
365
+ if ("unreadable" in ansi)
366
+ return { reject: "an ANSI-C quoted word carries an escape this lexer does not fold" };
367
+ raw += source.slice(i, ansi.close + 1);
368
+ folded += ansi.text;
369
+ started = true;
370
+ i = ansi.close;
371
+ continue;
372
+ }
373
+ }
313
374
  if (!quotesLiteral) {
314
375
  if (ch === "'" && !inDouble) {
315
376
  inSingle = !inSingle;