@sema-agent/core 1.292.0 → 1.294.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 (72) hide show
  1. package/dist/agents/subagent.d.ts.map +1 -1
  2. package/dist/agents/subagent.js +1 -0
  3. package/dist/agents/subagent.js.map +1 -1
  4. package/dist/agents/verify.d.ts +1 -0
  5. package/dist/agents/verify.d.ts.map +1 -1
  6. package/dist/agents/verify.js +1 -1
  7. package/dist/agents/verify.js.map +1 -1
  8. package/dist/core/auto-compaction.d.ts +2 -0
  9. package/dist/core/auto-compaction.d.ts.map +1 -1
  10. package/dist/core/auto-compaction.js +32 -5
  11. package/dist/core/auto-compaction.js.map +1 -1
  12. package/dist/core/checkpoint-store.d.ts +14 -2
  13. package/dist/core/checkpoint-store.d.ts.map +1 -1
  14. package/dist/core/checkpoint-store.js.map +1 -1
  15. package/dist/core/fs-write-gate-policy.d.ts +1 -0
  16. package/dist/core/fs-write-gate-policy.d.ts.map +1 -1
  17. package/dist/core/fs-write-gate-policy.js +16 -0
  18. package/dist/core/fs-write-gate-policy.js.map +1 -1
  19. package/dist/core/hooks.d.ts.map +1 -1
  20. package/dist/core/hooks.js.map +1 -1
  21. package/dist/core/runner/prepare-task.d.ts +17 -1
  22. package/dist/core/runner/prepare-task.d.ts.map +1 -1
  23. package/dist/core/runner/prepare-task.js +269 -8
  24. package/dist/core/runner/prepare-task.js.map +1 -1
  25. package/dist/core/runner/runtask.d.ts +3 -1
  26. package/dist/core/runner/runtask.d.ts.map +1 -1
  27. package/dist/core/runner/runtask.js +120 -20
  28. package/dist/core/runner/runtask.js.map +1 -1
  29. package/dist/core/runner/synthetic-tools.d.ts +7 -1
  30. package/dist/core/runner/synthetic-tools.d.ts.map +1 -1
  31. package/dist/core/runner/synthetic-tools.js +62 -6
  32. package/dist/core/runner/synthetic-tools.js.map +1 -1
  33. package/dist/core/trace.d.ts +1 -1
  34. package/dist/core/trace.d.ts.map +1 -1
  35. package/dist/core/trace.js.map +1 -1
  36. package/dist/core/types.d.ts +6 -0
  37. package/dist/core/types.d.ts.map +1 -1
  38. package/dist/engine/compaction/compaction.d.ts +4 -2
  39. package/dist/engine/compaction/compaction.d.ts.map +1 -1
  40. package/dist/engine/compaction/compaction.js +21 -6
  41. package/dist/engine/compaction/compaction.js.map +1 -1
  42. package/dist/engine/compaction/utils.d.ts +13 -0
  43. package/dist/engine/compaction/utils.d.ts.map +1 -1
  44. package/dist/engine/compaction/utils.js +126 -0
  45. package/dist/engine/compaction/utils.js.map +1 -1
  46. package/dist/engine/harness/agent-harness.d.ts.map +1 -1
  47. package/dist/engine/harness/agent-harness.js +5 -1
  48. package/dist/engine/harness/agent-harness.js.map +1 -1
  49. package/dist/engine/harness/types.d.ts +5 -1
  50. package/dist/engine/harness/types.d.ts.map +1 -1
  51. package/dist/engine/harness/types.js.map +1 -1
  52. package/dist/engine/session/session.d.ts +3 -2
  53. package/dist/engine/session/session.d.ts.map +1 -1
  54. package/dist/engine/session/session.js +14 -4
  55. package/dist/engine/session/session.js.map +1 -1
  56. package/dist/internal/harness.d.ts +3 -1
  57. package/dist/internal/harness.d.ts.map +1 -1
  58. package/dist/internal/harness.js +2 -1
  59. package/dist/internal/harness.js.map +1 -1
  60. package/dist/orchestration/run-workflow-tool.d.ts +2 -0
  61. package/dist/orchestration/run-workflow-tool.d.ts.map +1 -1
  62. package/dist/orchestration/run-workflow-tool.js +13 -3
  63. package/dist/orchestration/run-workflow-tool.js.map +1 -1
  64. package/dist/orchestration/workflow.d.ts +5 -1
  65. package/dist/orchestration/workflow.d.ts.map +1 -1
  66. package/dist/orchestration/workflow.js +8 -2
  67. package/dist/orchestration/workflow.js.map +1 -1
  68. package/dist/prompts/supervisor.d.ts +1 -1
  69. package/dist/prompts/supervisor.d.ts.map +1 -1
  70. package/dist/prompts/supervisor.js +9 -4
  71. package/dist/prompts/supervisor.js.map +1 -1
  72. package/package.json +1 -1
@@ -30,7 +30,7 @@ import { reservedCollisions, reservedFor } from "../../brain/request-params.js";
30
30
  import { defineTool } from "../tools.js";
31
31
  import { pathToUri } from "../lsp-protocol.js";
32
32
  import { DEFAULT_TOOL_RESULT_THRESHOLD_CHARS, firstPartyOffloadPolicy, InMemoryToolResultStore, RunnerSharedToolResultStore, ScopedToolResultStore, isVolatileOffloadStore, OFFLOAD_TOOL_NAME, makeReadToolResultTool, withToolResultOffload, } from "../tool-result-store.js";
33
- import { OUTPUT_TOOL_NAME, REPORT_FINDINGS_TOOL_NAME, SKILL_TOOL_NAME, buildSkillsBlock, makeOutputTool, makeReportBlockedTool, makeReportFindingsTool, makeSkillTool, normalizeSkills } from "./synthetic-tools.js";
33
+ import { OUTPUT_TOOL_NAME, REPORT_FINDINGS_TOOL_NAME, SKILL_CONTENT_MAX_CHARS, SKILL_TOOL_NAME, buildSkillsBlock, makeOutputTool, makeReportBlockedTool, makeReportFindingsTool, makeSkillTool, normalizeSkills } from "./synthetic-tools.js";
34
34
  import { compileOutputSchema } from "./strict-output-schema.js";
35
35
  import { TOOL_SEARCH_NAME, buildDeferredRegistry, classifyDeferred, extractDiscoveredToolNames, makePlaceholderTool, makeToolSearchTool, } from "./tool-disclosure.js";
36
36
  import { composeMemoryBlock, normalizeMemorySpec } from "../memory.js";
@@ -524,6 +524,62 @@ export async function prepareTask(spec, deps, sessions, resume, _memorySelector,
524
524
  };
525
525
  const subagentRetain = spec.retainSubagentSessions ? new SubagentRetainLedger(spec.retainSubagentSessions) : undefined;
526
526
  const worktreeIsolation = spec.handsReadOnly !== true ? createSubagentWorktreeHelper(executionEnv, taskRootPath) : undefined;
527
+ const liveInheritedGate = internals?.inheritedGate;
528
+ const seedInheritedGate = resume?.seed.inheritedGate;
529
+ const inheritedAncestorRules = (() => {
530
+ const seedRules = seedInheritedGate?.ancestorRules;
531
+ const liveRules = liveInheritedGate?.ancestorRules;
532
+ if (seedRules === undefined || seedRules.length === 0)
533
+ return liveRules ?? seedRules;
534
+ if (liveRules === undefined || liveRules.length === 0)
535
+ return seedRules;
536
+ const merged = seedRules.map((s) => {
537
+ const live = liveRules.find((l) => l.sessionId === s.sessionId && l.principal === s.principal);
538
+ return live !== undefined && live.rev >= s.rev ? live : s;
539
+ });
540
+ const extras = liveRules.filter((l) => !seedRules.some((s) => s.sessionId === l.sessionId && s.principal === l.principal));
541
+ return [...merged, ...extras];
542
+ })();
543
+ const shellGateRank = { off: 0, classify: 1, always: 2 };
544
+ const liveShellGate = liveInheritedGate?.shellGate;
545
+ const seedShellGate = seedInheritedGate?.shellGate;
546
+ const inheritedShellGate = liveShellGate === undefined
547
+ ? seedShellGate
548
+ : seedShellGate === undefined
549
+ ? liveShellGate
550
+ : shellGateRank[liveShellGate] >= shellGateRank[seedShellGate]
551
+ ? liveShellGate
552
+ : seedShellGate;
553
+ const inheritedParentConstraints = liveInheritedGate?.parentConstraints;
554
+ const specShellGate = spec.shellGate ?? "off";
555
+ const effectiveShellGate = inheritedShellGate !== undefined && shellGateRank[inheritedShellGate] > shellGateRank[specShellGate] ? inheritedShellGate : specShellGate;
556
+ const ownSessionRulesRef = {};
557
+ const frozenOnAsk = spec.onAsk ?? deps.onAsk;
558
+ const inheritedGateForChildren = () => {
559
+ const ancestorRules = [
560
+ ...(inheritedAncestorRules ?? []),
561
+ ...(ownSessionRulesRef.current !== undefined ? [ownSessionRulesRef.current] : []),
562
+ ];
563
+ const ownCallerPolicy = spec.toolPolicy ?? deps.toolPolicy;
564
+ const durableMandate = runtimeCaps?.forceDurableGate === true || (spec.durableApproval !== undefined && frozenOnAsk === undefined);
565
+ const parentConstraints = [
566
+ ...(inheritedParentConstraints ?? []),
567
+ ...(ownCallerPolicy !== undefined
568
+ ? [
569
+ {
570
+ policy: ownCallerPolicy,
571
+ ...(frozenOnAsk !== undefined ? { onAsk: frozenOnAsk } : {}),
572
+ ...(durableMandate ? { durableMandate: true } : {}),
573
+ },
574
+ ]
575
+ : []),
576
+ ];
577
+ return {
578
+ ...(ancestorRules.length > 0 ? { ancestorRules } : {}),
579
+ ...(effectiveShellGate !== "off" ? { shellGate: effectiveShellGate } : {}),
580
+ ...(parentConstraints.length > 0 ? { parentConstraints } : {}),
581
+ };
582
+ };
527
583
  let agentForkDenial;
528
584
  let observersActive = false;
529
585
  let autoModeDecider;
@@ -538,6 +594,7 @@ export async function prepareTask(spec, deps, sessions, resume, _memorySelector,
538
594
  clientContext: spec.clientContext,
539
595
  parentCwd: taskRootPath,
540
596
  activeSkillScope: () => skillScope.active(),
597
+ inheritedGateForChildren,
541
598
  taskId: hostTaskId,
542
599
  sessionId,
543
600
  ...(spec.backgroundScope !== undefined ? { backgroundScope: spec.backgroundScope } : {}),
@@ -641,6 +698,8 @@ export async function prepareTask(spec, deps, sessions, resume, _memorySelector,
641
698
  workflowDepth: internals?.workflowDepth,
642
699
  parentCwd: taskRootPath,
643
700
  parentThinking: () => harnessRef.current?.getThinkingLevel() ?? thinking,
701
+ ...(forwardEvent ? { forwardEvent } : {}),
702
+ inheritedGateForChildren,
644
703
  }));
645
704
  }
646
705
  const suspendRef = {};
@@ -829,7 +888,7 @@ export async function prepareTask(spec, deps, sessions, resume, _memorySelector,
829
888
  }
830
889
  }
831
890
  tools.push(...band.map((t) => firstPartyOffload(t)));
832
- const shellGate = spec.shellGate ?? "off";
891
+ const shellGate = effectiveShellGate;
833
892
  if (shellGate !== "off" && !(executionEnv instanceof StubExecutionEnv) && spec.handsReadOnly !== true) {
834
893
  shellGatedBash = !egressTools.has("Bash") && !irreversibilityTier.has("Bash");
835
894
  irreversibilityTier.set("Bash", shellGate === "always" ? "always" : "maybe");
@@ -1163,7 +1222,12 @@ export async function prepareTask(spec, deps, sessions, resume, _memorySelector,
1163
1222
  memoryBlock = memoryBlock ? `${memoryBlock}\n\n${projectBlock}` : projectBlock;
1164
1223
  }
1165
1224
  }
1166
- const skillSpecs = normalizeSkills(spec.skills);
1225
+ const skillSpecs = normalizeSkills(spec.skills ?? []).filter((s) => {
1226
+ if (s.content.length <= SKILL_CONTENT_MAX_CHARS)
1227
+ return true;
1228
+ deps.onError?.(new Error(`Skill "${s.name}" content is ${s.content.length} chars, over the ${SKILL_CONTENT_MAX_CHARS}-char load limit — skill not loaded (skills are never truncated; shrink the body or move material to attachments/files).`), { phase: "config", sessionId });
1229
+ return false;
1230
+ });
1167
1231
  const inheritedFrames = internals?.inheritedManifestScope ?? [];
1168
1232
  for (const frame of inheritedFrames) {
1169
1233
  skillScope.push(frame);
@@ -1516,8 +1580,28 @@ export async function prepareTask(spec, deps, sessions, resume, _memorySelector,
1516
1580
  const rules = await deps.sessionPolicyStore.getRules(spec.sessionId, spec.principal);
1517
1581
  if (rules) {
1518
1582
  sessionRulePolicy = createSessionRulePolicy(rules, { env: executionEnv, rootPath: taskRootPath, toolEffects });
1583
+ ownSessionRulesRef.current = {
1584
+ sessionId: spec.sessionId,
1585
+ ...(spec.principal !== undefined ? { principal: spec.principal } : {}),
1586
+ rev: rules.rev,
1587
+ rules,
1588
+ };
1519
1589
  }
1520
1590
  }
1591
+ const ancestorRulePolicies = [];
1592
+ for (const snap of inheritedAncestorRules ?? []) {
1593
+ let ancestorRules = snap.rules;
1594
+ if (deps.sessionPolicyStore) {
1595
+ try {
1596
+ const live = await deps.sessionPolicyStore.getRules(snap.sessionId, snap.principal);
1597
+ if (live !== null && live.rev >= snap.rev)
1598
+ ancestorRules = live;
1599
+ }
1600
+ catch {
1601
+ }
1602
+ }
1603
+ ancestorRulePolicies.push(createSessionRulePolicy(ancestorRules, { env: executionEnv, rootPath: taskRootPath, toolEffects }));
1604
+ }
1521
1605
  const skillScopePolicy = hasSkillManifest
1522
1606
  ? createActiveSkillScopePolicy({
1523
1607
  scope: skillScope,
@@ -1526,12 +1610,177 @@ export async function prepareTask(spec, deps, sessions, resume, _memorySelector,
1526
1610
  toolEffects,
1527
1611
  })
1528
1612
  : undefined;
1529
- const narrowingLayers = [sessionRulePolicy, skillScopePolicy].filter((p) => p !== undefined);
1613
+ const narrowingLayers = [sessionRulePolicy, ...ancestorRulePolicies, skillScopePolicy].filter((p) => p !== undefined);
1530
1614
  const denyNarrowingPolicy = narrowingLayers.length === 0 ? undefined : narrowingLayers.length === 1 ? narrowingLayers[0] : combinePolicies(...narrowingLayers);
1531
- const policyLayers = policy !== undefined ? [...narrowingLayers, policy, ...narrowingLayers] : narrowingLayers;
1615
+ const sameInstanceAncestorCount = policy === undefined ? 0 : (inheritedParentConstraints ?? []).reduce((n, pc) => (pc.policy === policy ? n + 1 : n), 0);
1616
+ const sharedFirstDecision = new Map();
1617
+ const SHARED_FIRST_DECISION_CAP = 256;
1618
+ const callerPolicyLayer = policy !== undefined && sameInstanceAncestorCount > 0
1619
+ ? {
1620
+ check: async (creq, csignal) => {
1621
+ const decision = await policy.check(creq, csignal ?? abortController.signal);
1622
+ sharedFirstDecision.set(creq.toolCallId, decision);
1623
+ if (sharedFirstDecision.size > SHARED_FIRST_DECISION_CAP) {
1624
+ const oldest = sharedFirstDecision.keys().next().value;
1625
+ if (oldest !== undefined)
1626
+ sharedFirstDecision.delete(oldest);
1627
+ }
1628
+ return decision;
1629
+ },
1630
+ }
1631
+ : policy;
1632
+ const parentConstraintWrappers = (inheritedParentConstraints ?? []).map((pc) => policy !== undefined && pc.policy === policy
1633
+ ? {
1634
+ check: async (creq, csignal) => {
1635
+ const first = sharedFirstDecision.get(creq.toolCallId);
1636
+ if (first === undefined) {
1637
+ return {
1638
+ action: "deny",
1639
+ reason: `inherited parent policy could not be arbitrated for "${creq.toolName}" ` +
1640
+ `(shared-instance first decision unavailable); denied fail-closed`,
1641
+ };
1642
+ }
1643
+ if (first.action === "deny")
1644
+ return first;
1645
+ if (first.action === "allow")
1646
+ return { action: "allow" };
1647
+ if (pc.durableMandate === true) {
1648
+ return {
1649
+ action: "deny",
1650
+ reason: `inherited parent policy requires durable approval for "${creq.toolName}" — the parent's durable ` +
1651
+ `ask cannot be reconstructed in a delegated child; denied fail-closed (tighten-only)`,
1652
+ };
1653
+ }
1654
+ const presentedArgs = creq.args;
1655
+ const resolved = await resolveAsk({
1656
+ toolName: creq.toolName,
1657
+ toolCallId: creq.toolCallId,
1658
+ args: presentedArgs,
1659
+ message: first.message ?? first.reason ?? `approval required for "${creq.toolName}" (inherited parent policy)`,
1660
+ principal: spec.principal,
1661
+ sourceTaskId: sessionId,
1662
+ }, pc.onAsk, csignal ?? abortController.signal);
1663
+ return resolved.action === "allow" ? { action: "allow" } : resolved;
1664
+ },
1665
+ }
1666
+ : {
1667
+ check: async (creq, csignal) => {
1668
+ let decision;
1669
+ try {
1670
+ decision = await pc.policy.check(creq, csignal ?? abortController.signal);
1671
+ }
1672
+ catch (err) {
1673
+ return {
1674
+ action: "deny",
1675
+ reason: `inherited parent policy errored for "${creq.toolName}": ${err instanceof Error ? err.message : String(err)}`,
1676
+ };
1677
+ }
1678
+ if (decision.action !== "ask")
1679
+ return decision;
1680
+ if (pc.durableMandate === true) {
1681
+ return {
1682
+ action: "deny",
1683
+ reason: `inherited parent policy requires durable approval for "${creq.toolName}" — the parent's durable ` +
1684
+ `ask cannot be reconstructed in a delegated child; denied fail-closed (tighten-only)`,
1685
+ };
1686
+ }
1687
+ const presentedArgs = decision.updatedInput !== undefined ? decision.updatedInput : creq.args;
1688
+ const resolved = await resolveAsk({
1689
+ toolName: creq.toolName,
1690
+ toolCallId: creq.toolCallId,
1691
+ args: presentedArgs,
1692
+ message: decision.message ?? decision.reason ?? `approval required for "${creq.toolName}" (inherited parent policy)`,
1693
+ principal: spec.principal,
1694
+ sourceTaskId: sessionId,
1695
+ }, pc.onAsk, csignal ?? abortController.signal);
1696
+ return resolved.action === "allow" && decision.updatedInput !== undefined
1697
+ ? { ...resolved, updatedInput: decision.updatedInput }
1698
+ : resolved;
1699
+ },
1700
+ });
1701
+ const rewriteCapableLayers = policy !== undefined || parentConstraintWrappers.length > 0;
1702
+ const rewriteEmitterIndex = new Map();
1703
+ const rewriteCapableChain = [
1704
+ ...(callerPolicyLayer !== undefined ? [callerPolicyLayer] : []),
1705
+ ...parentConstraintWrappers,
1706
+ ];
1707
+ const callerSlotOffset = callerPolicyLayer !== undefined ? 1 : 0;
1708
+ const sameInstanceAdapterIndices = new Set();
1709
+ (inheritedParentConstraints ?? []).forEach((pc, j) => {
1710
+ if (policy !== undefined && pc.policy === policy)
1711
+ sameInstanceAdapterIndices.add(j + callerSlotOffset);
1712
+ });
1713
+ const instrumentedChain = rewriteCapableChain.map((layer, idx) => ({
1714
+ check: async (creq, csignal) => {
1715
+ const d = await layer.check(creq, csignal);
1716
+ if (d.updatedInput !== undefined)
1717
+ rewriteEmitterIndex.set(creq.toolCallId, idx);
1718
+ return d;
1719
+ },
1720
+ }));
1721
+ const policyLayers = [
1722
+ ...narrowingLayers,
1723
+ ...instrumentedChain,
1724
+ ...(rewriteCapableLayers ? narrowingLayers : []),
1725
+ ];
1532
1726
  const integrityGuardLayers = [createTranscriptIntegrityPolicy(), createUnverifiableDeletePolicy()];
1533
- const guardedPolicyLayers = policy !== undefined ? [...integrityGuardLayers, ...policyLayers, ...integrityGuardLayers] : [...integrityGuardLayers, ...policyLayers];
1534
- const effectivePolicy = guardedPolicyLayers.length === 1 ? guardedPolicyLayers[0] : combinePolicies(...guardedPolicyLayers);
1727
+ const guardedPolicyLayers = rewriteCapableLayers
1728
+ ? [...integrityGuardLayers, ...policyLayers, ...integrityGuardLayers]
1729
+ : [...integrityGuardLayers, ...policyLayers];
1730
+ const foldedPolicy = guardedPolicyLayers.length === 1 ? guardedPolicyLayers[0] : combinePolicies(...guardedPolicyLayers);
1731
+ const effectivePolicy = foldedPolicy !== undefined && rewriteCapableLayers
1732
+ ? {
1733
+ check: async (req, signal) => {
1734
+ let decision;
1735
+ try {
1736
+ decision = await foldedPolicy.check(req, signal);
1737
+ }
1738
+ catch (err) {
1739
+ rewriteEmitterIndex.delete(req.toolCallId);
1740
+ throw err;
1741
+ }
1742
+ const emitterIdx = rewriteEmitterIndex.get(req.toolCallId);
1743
+ rewriteEmitterIndex.delete(req.toolCallId);
1744
+ if (decision.action === "deny" || decision.updatedInput === undefined)
1745
+ return decision;
1746
+ const recheckPrefix = rewriteCapableChain.slice(0, emitterIdx ?? rewriteCapableChain.length);
1747
+ const postEmitterSameInstanceAdapters = [];
1748
+ if (emitterIdx !== undefined && emitterIdx > 0) {
1749
+ for (let i = emitterIdx + 1; i < rewriteCapableChain.length; i++) {
1750
+ if (sameInstanceAdapterIndices.has(i))
1751
+ postEmitterSameInstanceAdapters.push(rewriteCapableChain[i]);
1752
+ }
1753
+ }
1754
+ const recheckLayers = [...recheckPrefix, ...postEmitterSameInstanceAdapters];
1755
+ const finalReq = { ...req, args: decision.updatedInput };
1756
+ let asked;
1757
+ try {
1758
+ for (const layer of recheckLayers) {
1759
+ const d = await layer.check(finalReq, signal);
1760
+ if (d.action === "deny") {
1761
+ return { ...d, updatedInput: decision.updatedInput };
1762
+ }
1763
+ if (d.updatedInput !== undefined) {
1764
+ return {
1765
+ action: "deny",
1766
+ message: "policy required a rewrite during final-form re-check — the arguments that would execute were not accepted as-is (fail-closed; rewrite chains are not iterated to a fixpoint)",
1767
+ updatedInput: decision.updatedInput,
1768
+ };
1769
+ }
1770
+ if (d.action === "ask" && asked === undefined)
1771
+ asked = d;
1772
+ }
1773
+ }
1774
+ finally {
1775
+ rewriteEmitterIndex.delete(req.toolCallId);
1776
+ }
1777
+ if (asked !== undefined && decision.action === "allow") {
1778
+ return { ...asked, updatedInput: decision.updatedInput };
1779
+ }
1780
+ return decision;
1781
+ },
1782
+ }
1783
+ : foldedPolicy;
1535
1784
  const hooks = spec.hooks ?? deps.hooks;
1536
1785
  const onAsk = spec.onAsk ?? deps.onAsk;
1537
1786
  const handWriteTools = handsEnabled
@@ -1653,6 +1902,18 @@ export async function prepareTask(spec, deps, sessions, resume, _memorySelector,
1653
1902
  return live.length > 0 ? live : undefined;
1654
1903
  })(),
1655
1904
  pendingSteer: undefined,
1905
+ inheritedGate: (() => {
1906
+ const requiresParentConstraint = (inheritedParentConstraints?.length ?? 0) > 0 || seedInheritedGate?.requiresParentConstraint === true;
1907
+ const parentConstraintCount = (inheritedParentConstraints?.length ?? 0) > 0 ? inheritedParentConstraints.length : seedInheritedGate?.parentConstraintCount;
1908
+ return inheritedAncestorRules !== undefined || inheritedShellGate !== undefined || requiresParentConstraint
1909
+ ? {
1910
+ ...(inheritedAncestorRules !== undefined ? { ancestorRules: structuredClone(inheritedAncestorRules) } : {}),
1911
+ ...(inheritedShellGate !== undefined ? { shellGate: inheritedShellGate } : {}),
1912
+ requiresParentConstraint,
1913
+ ...(requiresParentConstraint && parentConstraintCount !== undefined ? { parentConstraintCount } : {}),
1914
+ }
1915
+ : undefined;
1916
+ })(),
1656
1917
  });
1657
1918
  const commitSuspendSaga = async (token, cp, remoteEnv, remoteHandle) => {
1658
1919
  if (!checkpointStore)
@@ -1846,7 +2107,7 @@ export async function prepareTask(spec, deps, sessions, resume, _memorySelector,
1846
2107
  : undefined;
1847
2108
  const suspendAsk = checkpointStore && (durableApproval || irreversibleTools.size > 0 || egressTools.size > 0)
1848
2109
  ? async (req, postHookArgs, safety) => {
1849
- if (safety === undefined && durableApproval === undefined && onAsk !== undefined) {
2110
+ if (safety === undefined && onAsk !== undefined && runtimeCaps?.forceDurableGate !== true) {
1850
2111
  return undefined;
1851
2112
  }
1852
2113
  let token;