opencode-matrixx 2.6.6 → 2.6.7

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/dist/cli.js +51 -4
  2. package/dist/config/schema/background-task.d.ts +37 -0
  3. package/dist/config/schema/dcp.d.ts +46 -0
  4. package/dist/config/schema/matrixx-config.d.ts +32 -0
  5. package/dist/features/background-agent/admission.d.ts +24 -0
  6. package/dist/features/background-agent/concurrency.d.ts +9 -0
  7. package/dist/features/background-agent/constants.d.ts +13 -0
  8. package/dist/features/background-agent/handle-index.d.ts +12 -0
  9. package/dist/features/background-agent/manager.d.ts +59 -4
  10. package/dist/features/background-agent/notification-builder.d.ts +1 -0
  11. package/dist/features/background-agent/reconcile.d.ts +33 -0
  12. package/dist/features/background-agent/revive.d.ts +39 -0
  13. package/dist/features/background-agent/session-output.d.ts +40 -0
  14. package/dist/features/background-agent/task-history.d.ts +20 -0
  15. package/dist/features/background-agent/types.d.ts +21 -1
  16. package/dist/features/background-agent/wake-scheduler.d.ts +47 -0
  17. package/dist/features/background-agent/wallclock.d.ts +37 -0
  18. package/dist/features/bdd/schema.d.ts +5 -5
  19. package/dist/hooks/context-mode-enforcer/constants.d.ts +1 -1
  20. package/dist/index.js +1909 -716
  21. package/dist/matrixx.schema.json +165 -3
  22. package/dist/plugin-handlers/agent-config-handler.d.ts +2 -1
  23. package/dist/shared/context-mode-enforcement.d.ts +35 -0
  24. package/dist/shared/index.d.ts +1 -1
  25. package/dist/shared/revive-outcome.d.ts +15 -0
  26. package/dist/shared/saturated-outcome.d.ts +18 -0
  27. package/dist/shared/wallclock-outcome.d.ts +18 -0
  28. package/dist/tools/background-task/constants.d.ts +1 -0
  29. package/dist/tools/background-task/create-background-revive.d.ts +3 -0
  30. package/dist/tools/background-task/index.d.ts +1 -1
  31. package/dist/tools/background-task/tools.d.ts +1 -0
  32. package/dist/tools/background-task/types.d.ts +9 -0
  33. package/dist/tools/dcp-switch-profile/tools.d.ts +1 -0
  34. package/dist/tools/index.d.ts +1 -1
  35. package/package.json +1 -1
  36. package/dist/shared/context-mode-prompt.d.ts +0 -12
  37. package/dist/shared/context-mode-prompt.test.d.ts +0 -1
package/dist/cli.js CHANGED
@@ -15787,6 +15787,20 @@ var CircuitBreakerConfigSchema = exports_external.object({
15787
15787
  maxToolCalls: exports_external.number().int().min(10).optional(),
15788
15788
  consecutiveThreshold: exports_external.number().int().min(5).optional()
15789
15789
  });
15790
+ var NestedAdmissionConfigSchema = exports_external.object({
15791
+ enabled: exports_external.boolean().optional(),
15792
+ mode: exports_external.enum(["bypass", "reserve"]).optional(),
15793
+ maxDepth: exports_external.number().int().min(1).max(5).optional()
15794
+ });
15795
+ var WakeSchedulerConfigSchema = exports_external.object({
15796
+ enabled: exports_external.boolean().optional(),
15797
+ intervalMs: exports_external.number().min(60000).optional()
15798
+ });
15799
+ var JobBoardConfigSchema = exports_external.object({
15800
+ enabled: exports_external.boolean().optional(),
15801
+ strategy: exports_external.enum(["latest", "checkpoint-compatible"]).optional(),
15802
+ maxRetainedSnapshots: exports_external.number().int().min(1).max(100).optional()
15803
+ });
15790
15804
  var BackgroundTaskConfigSchema = exports_external.object({
15791
15805
  defaultConcurrency: exports_external.number().min(1).optional(),
15792
15806
  providerConcurrency: exports_external.record(exports_external.string(), exports_external.number().min(0)).optional(),
@@ -15794,7 +15808,13 @@ var BackgroundTaskConfigSchema = exports_external.object({
15794
15808
  staleTimeoutMs: exports_external.number().min(60000).optional(),
15795
15809
  messageStalenessTimeoutMs: exports_external.number().min(60000).optional(),
15796
15810
  maxToolCalls: exports_external.number().int().min(10).optional(),
15797
- circuitBreaker: CircuitBreakerConfigSchema.optional()
15811
+ circuitBreaker: CircuitBreakerConfigSchema.optional(),
15812
+ admissionTimeoutMs: exports_external.union([exports_external.literal(0), exports_external.number().min(60000)]).optional(),
15813
+ nestedAdmission: NestedAdmissionConfigSchema.optional(),
15814
+ wakeScheduler: WakeSchedulerConfigSchema.optional(),
15815
+ jobBoard: JobBoardConfigSchema.optional(),
15816
+ wallClockTimeoutMs: exports_external.union([exports_external.literal(0), exports_external.number().int().min(60000).max(2147483647)]).optional(),
15817
+ wallClockAbortGraceMs: exports_external.number().int().min(1000).max(60000).optional()
15798
15818
  });
15799
15819
 
15800
15820
  // src/config/schema/browser-automation.ts
@@ -15873,7 +15893,7 @@ var CommentCheckerConfigSchema = exports_external.object({
15873
15893
  var ContextModeConfigSchema = exports_external.object({
15874
15894
  enabled: exports_external.boolean().default(true),
15875
15895
  enforce: exports_external.boolean().default(false),
15876
- blocked_tools: exports_external.array(exports_external.string()).default(["read", "grep", "glob"])
15896
+ blocked_tools: exports_external.array(exports_external.string()).default(["grep", "glob"])
15877
15897
  });
15878
15898
 
15879
15899
  // src/config/schema/dcp.ts
@@ -15959,12 +15979,37 @@ var BUILTIN_DCP_PROFILES = {
15959
15979
  turnProtection: { enabled: true, turns: 5 },
15960
15980
  experimental: { allowSubAgents: true },
15961
15981
  strategies: { purgeErrors: { turns: 4 } }
15982
+ },
15983
+ brutal: {
15984
+ pruneNotification: "off",
15985
+ compress: {
15986
+ maxContextLimit: "15%",
15987
+ minContextLimit: "10%",
15988
+ nudgeFrequency: 1,
15989
+ nudgeForce: "strong",
15990
+ iterationNudgeThreshold: 1
15991
+ },
15992
+ turnProtection: { enabled: false },
15993
+ experimental: { allowSubAgents: false },
15994
+ strategies: { purgeErrors: { turns: 1 } }
15962
15995
  }
15963
15996
  };
15997
+ var DcpHandoffCompressionSchema = exports_external.object({
15998
+ enabled: exports_external.boolean().default(true),
15999
+ maxMessages: exports_external.number().int().min(1).default(6),
16000
+ keepFirst: exports_external.number().int().min(0).default(2),
16001
+ keepLast: exports_external.number().int().min(0).default(3)
16002
+ });
15964
16003
  var DcpConfigSchema = exports_external.object({
15965
16004
  enabled: exports_external.boolean().default(true),
15966
16005
  profiles: exports_external.record(exports_external.string(), DcpProfileDefinitionSchema).default(BUILTIN_DCP_PROFILES),
15967
16006
  default_profile: exports_external.string().optional(),
16007
+ handoffCompression: DcpHandoffCompressionSchema.default({
16008
+ enabled: true,
16009
+ maxMessages: 6,
16010
+ keepFirst: 2,
16011
+ keepLast: 3
16012
+ }),
15968
16013
  base: exports_external.object({
15969
16014
  autoUpdate: exports_external.boolean().default(false),
15970
16015
  debug: exports_external.boolean().default(false),
@@ -16021,7 +16066,8 @@ var DcpConfigSchema = exports_external.object({
16021
16066
  enabled: false,
16022
16067
  automaticStrategies: true
16023
16068
  }),
16024
- protectedFilePatterns: exports_external.array(exports_external.string()).default([])
16069
+ protectedFilePatterns: exports_external.array(exports_external.string()).default([]),
16070
+ experimental: DcpExperimentalSchema.default({ allowSubAgents: true })
16025
16071
  }).default({
16026
16072
  autoUpdate: false,
16027
16073
  debug: false,
@@ -16042,7 +16088,8 @@ var DcpConfigSchema = exports_external.object({
16042
16088
  },
16043
16089
  commands: { enabled: true, protectedTools: [] },
16044
16090
  manualMode: { enabled: false, automaticStrategies: true },
16045
- protectedFilePatterns: []
16091
+ protectedFilePatterns: [],
16092
+ experimental: { allowSubAgents: true }
16046
16093
  })
16047
16094
  });
16048
16095
 
@@ -1,4 +1,18 @@
1
1
  import { z } from "zod";
2
+ /** Idle-parent wake scheduler settings (default ON, default interval 300000ms, minimum 60000ms) */
3
+ export declare const WakeSchedulerConfigSchema: z.ZodObject<{
4
+ enabled: z.ZodOptional<z.ZodBoolean>;
5
+ intervalMs: z.ZodOptional<z.ZodNumber>;
6
+ }, z.core.$strip>;
7
+ /** Job-board snapshot settings (defaults: enabled true, strategy "latest", maxRetainedSnapshots 20) */
8
+ export declare const JobBoardConfigSchema: z.ZodObject<{
9
+ enabled: z.ZodOptional<z.ZodBoolean>;
10
+ strategy: z.ZodOptional<z.ZodEnum<{
11
+ latest: "latest";
12
+ "checkpoint-compatible": "checkpoint-compatible";
13
+ }>>;
14
+ maxRetainedSnapshots: z.ZodOptional<z.ZodNumber>;
15
+ }, z.core.$strip>;
2
16
  export declare const BackgroundTaskConfigSchema: z.ZodObject<{
3
17
  defaultConcurrency: z.ZodOptional<z.ZodNumber>;
4
18
  providerConcurrency: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNumber>>;
@@ -11,5 +25,28 @@ export declare const BackgroundTaskConfigSchema: z.ZodObject<{
11
25
  maxToolCalls: z.ZodOptional<z.ZodNumber>;
12
26
  consecutiveThreshold: z.ZodOptional<z.ZodNumber>;
13
27
  }, z.core.$strip>>;
28
+ admissionTimeoutMs: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<0>, z.ZodNumber]>>;
29
+ nestedAdmission: z.ZodOptional<z.ZodObject<{
30
+ enabled: z.ZodOptional<z.ZodBoolean>;
31
+ mode: z.ZodOptional<z.ZodEnum<{
32
+ bypass: "bypass";
33
+ reserve: "reserve";
34
+ }>>;
35
+ maxDepth: z.ZodOptional<z.ZodNumber>;
36
+ }, z.core.$strip>>;
37
+ wakeScheduler: z.ZodOptional<z.ZodObject<{
38
+ enabled: z.ZodOptional<z.ZodBoolean>;
39
+ intervalMs: z.ZodOptional<z.ZodNumber>;
40
+ }, z.core.$strip>>;
41
+ jobBoard: z.ZodOptional<z.ZodObject<{
42
+ enabled: z.ZodOptional<z.ZodBoolean>;
43
+ strategy: z.ZodOptional<z.ZodEnum<{
44
+ latest: "latest";
45
+ "checkpoint-compatible": "checkpoint-compatible";
46
+ }>>;
47
+ maxRetainedSnapshots: z.ZodOptional<z.ZodNumber>;
48
+ }, z.core.$strip>>;
49
+ wallClockTimeoutMs: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<0>, z.ZodNumber]>>;
50
+ wallClockAbortGraceMs: z.ZodOptional<z.ZodNumber>;
14
51
  }, z.core.$strip>;
15
52
  export type BackgroundTaskConfig = z.infer<typeof BackgroundTaskConfigSchema>;
@@ -158,7 +158,44 @@ export declare const BUILTIN_DCP_PROFILES: {
158
158
  };
159
159
  };
160
160
  };
161
+ readonly brutal: {
162
+ readonly pruneNotification: "off";
163
+ readonly compress: {
164
+ readonly maxContextLimit: "15%";
165
+ readonly minContextLimit: "10%";
166
+ readonly nudgeFrequency: 1;
167
+ readonly nudgeForce: "strong";
168
+ readonly iterationNudgeThreshold: 1;
169
+ };
170
+ readonly turnProtection: {
171
+ readonly enabled: false;
172
+ };
173
+ readonly experimental: {
174
+ readonly allowSubAgents: false;
175
+ };
176
+ readonly strategies: {
177
+ readonly purgeErrors: {
178
+ readonly turns: 1;
179
+ };
180
+ };
181
+ };
161
182
  };
183
+ /**
184
+ * Configuration for compressing background task results when sending
185
+ * completion notifications to the parent session (handoff boundary).
186
+ *
187
+ * When enabled, assistant messages beyond `maxMessages` are truncated:
188
+ * the first `keepFirst` and last `keepLast` messages are preserved,
189
+ * with a "[... N messages truncated]" marker inserted between them.
190
+ * This reduces the context cost of notifying the parent session.
191
+ */
192
+ export declare const DcpHandoffCompressionSchema: z.ZodObject<{
193
+ enabled: z.ZodDefault<z.ZodBoolean>;
194
+ maxMessages: z.ZodDefault<z.ZodNumber>;
195
+ keepFirst: z.ZodDefault<z.ZodNumber>;
196
+ keepLast: z.ZodDefault<z.ZodNumber>;
197
+ }, z.core.$strip>;
198
+ export type DcpHandoffCompression = z.infer<typeof DcpHandoffCompressionSchema>;
162
199
  export declare const DcpConfigSchema: z.ZodObject<{
163
200
  enabled: z.ZodDefault<z.ZodBoolean>;
164
201
  profiles: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
@@ -194,6 +231,12 @@ export declare const DcpConfigSchema: z.ZodObject<{
194
231
  }, z.core.$strip>>;
195
232
  }, z.core.$strip>>>;
196
233
  default_profile: z.ZodOptional<z.ZodString>;
234
+ handoffCompression: z.ZodDefault<z.ZodObject<{
235
+ enabled: z.ZodDefault<z.ZodBoolean>;
236
+ maxMessages: z.ZodDefault<z.ZodNumber>;
237
+ keepFirst: z.ZodDefault<z.ZodNumber>;
238
+ keepLast: z.ZodDefault<z.ZodNumber>;
239
+ }, z.core.$strip>>;
197
240
  base: z.ZodDefault<z.ZodObject<{
198
241
  autoUpdate: z.ZodDefault<z.ZodBoolean>;
199
242
  debug: z.ZodDefault<z.ZodBoolean>;
@@ -240,6 +283,9 @@ export declare const DcpConfigSchema: z.ZodObject<{
240
283
  automaticStrategies: z.ZodDefault<z.ZodBoolean>;
241
284
  }, z.core.$strip>>;
242
285
  protectedFilePatterns: z.ZodDefault<z.ZodArray<z.ZodString>>;
286
+ experimental: z.ZodDefault<z.ZodObject<{
287
+ allowSubAgents: z.ZodOptional<z.ZodBoolean>;
288
+ }, z.core.$strip>>;
243
289
  }, z.core.$strip>>;
244
290
  }, z.core.$strip>;
245
291
  export type DcpConfig = z.infer<typeof DcpConfigSchema>;
@@ -1608,6 +1608,12 @@ export declare const MatrixxConfigSchema: z.ZodObject<{
1608
1608
  }, z.core.$strip>>;
1609
1609
  }, z.core.$strip>>>;
1610
1610
  default_profile: z.ZodOptional<z.ZodString>;
1611
+ handoffCompression: z.ZodDefault<z.ZodObject<{
1612
+ enabled: z.ZodDefault<z.ZodBoolean>;
1613
+ maxMessages: z.ZodDefault<z.ZodNumber>;
1614
+ keepFirst: z.ZodDefault<z.ZodNumber>;
1615
+ keepLast: z.ZodDefault<z.ZodNumber>;
1616
+ }, z.core.$strip>>;
1611
1617
  base: z.ZodDefault<z.ZodObject<{
1612
1618
  autoUpdate: z.ZodDefault<z.ZodBoolean>;
1613
1619
  debug: z.ZodDefault<z.ZodBoolean>;
@@ -1654,6 +1660,9 @@ export declare const MatrixxConfigSchema: z.ZodObject<{
1654
1660
  automaticStrategies: z.ZodDefault<z.ZodBoolean>;
1655
1661
  }, z.core.$strip>>;
1656
1662
  protectedFilePatterns: z.ZodDefault<z.ZodArray<z.ZodString>>;
1663
+ experimental: z.ZodDefault<z.ZodObject<{
1664
+ allowSubAgents: z.ZodOptional<z.ZodBoolean>;
1665
+ }, z.core.$strip>>;
1657
1666
  }, z.core.$strip>>;
1658
1667
  }, z.core.$strip>>;
1659
1668
  auto_update: z.ZodOptional<z.ZodBoolean>;
@@ -1701,6 +1710,29 @@ export declare const MatrixxConfigSchema: z.ZodObject<{
1701
1710
  maxToolCalls: z.ZodOptional<z.ZodNumber>;
1702
1711
  consecutiveThreshold: z.ZodOptional<z.ZodNumber>;
1703
1712
  }, z.core.$strip>>;
1713
+ admissionTimeoutMs: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<0>, z.ZodNumber]>>;
1714
+ nestedAdmission: z.ZodOptional<z.ZodObject<{
1715
+ enabled: z.ZodOptional<z.ZodBoolean>;
1716
+ mode: z.ZodOptional<z.ZodEnum<{
1717
+ bypass: "bypass";
1718
+ reserve: "reserve";
1719
+ }>>;
1720
+ maxDepth: z.ZodOptional<z.ZodNumber>;
1721
+ }, z.core.$strip>>;
1722
+ wakeScheduler: z.ZodOptional<z.ZodObject<{
1723
+ enabled: z.ZodOptional<z.ZodBoolean>;
1724
+ intervalMs: z.ZodOptional<z.ZodNumber>;
1725
+ }, z.core.$strip>>;
1726
+ jobBoard: z.ZodOptional<z.ZodObject<{
1727
+ enabled: z.ZodOptional<z.ZodBoolean>;
1728
+ strategy: z.ZodOptional<z.ZodEnum<{
1729
+ latest: "latest";
1730
+ "checkpoint-compatible": "checkpoint-compatible";
1731
+ }>>;
1732
+ maxRetainedSnapshots: z.ZodOptional<z.ZodNumber>;
1733
+ }, z.core.$strip>>;
1734
+ wallClockTimeoutMs: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<0>, z.ZodNumber]>>;
1735
+ wallClockAbortGraceMs: z.ZodOptional<z.ZodNumber>;
1704
1736
  }, z.core.$strip>>;
1705
1737
  notification: z.ZodOptional<z.ZodObject<{
1706
1738
  force_enable: z.ZodOptional<z.ZodBoolean>;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Whether a background launch originates from the root session or from a
3
+ * managed (subagent) session descended from it. Nested launches are exempt
4
+ * from the concurrency semaphore so a saturated managed child cannot deadlock
5
+ * by waiting on its own background work.
6
+ */
7
+ export type AdmissionClass = {
8
+ kind: "root";
9
+ } | {
10
+ kind: "nested";
11
+ depth: number;
12
+ };
13
+ /**
14
+ * Classify a launch whose requesting session is `parentSessionID`.
15
+ *
16
+ * Walks the child→parent session registry using `getParentSessionID`, treating
17
+ * each registered ancestor hop as one level of nesting. Depth is capped at
18
+ * `maxDepth` and reported as actually reached.
19
+ *
20
+ * Fails open to `root` when the requester is absent from the process-local
21
+ * registry (undefined, empty, or unregistered), so a cold start can never
22
+ * misclassify a root launch as nested.
23
+ */
24
+ export declare function classifyAdmission(parentSessionID: string | undefined, maxDepth: number): AdmissionClass;
@@ -1,11 +1,20 @@
1
1
  import type { BackgroundTaskConfig } from "../../config/schema";
2
+ export type AcquireOutcome = {
3
+ granted: true;
4
+ } | {
5
+ granted: false;
6
+ reason: "timeout" | "cancelled";
7
+ waitedMs: number;
8
+ };
2
9
  export declare class ConcurrencyManager {
3
10
  private config?;
4
11
  private counts;
5
12
  private queues;
6
13
  constructor(config?: BackgroundTaskConfig);
7
14
  getConcurrencyLimit(model: string): number;
15
+ private tryAcquireSlot;
8
16
  acquire(model: string): Promise<void>;
17
+ acquireWithDeadline(model: string, timeoutMs?: number): Promise<AcquireOutcome>;
9
18
  release(model: string): void;
10
19
  /**
11
20
  * Cancel all waiting acquires for a model. Used during cleanup.
@@ -12,6 +12,19 @@ export declare const MIN_IDLE_TIME_MS = 5000;
12
12
  export declare const POLLING_INTERVAL_MS = 3000;
13
13
  export declare const PRUNE_THROTTLE_MS = 30000;
14
14
  export declare const TASK_CLEANUP_DELAY_MS: number;
15
+ export declare const DEFAULT_ADMISSION_TIMEOUT_MS = 0;
16
+ export declare const DEFAULT_WALL_CLOCK_TIMEOUT_MS = 0;
17
+ export declare const DEFAULT_WALL_CLOCK_ABORT_GRACE_MS = 5000;
18
+ export declare const DEFAULT_NESTED_ADMISSION_ENABLED = true;
19
+ export declare const DEFAULT_NESTED_ADMISSION_MODE: "bypass";
20
+ export declare const DEFAULT_NESTED_MAX_DEPTH = 2;
21
+ export declare const DEFAULT_WAKE_SCHEDULER_ENABLED = true;
22
+ export declare const DEFAULT_WAKE_INTERVAL_MS = 300000;
23
+ export declare const MIN_WAKE_INTERVAL_MS = 60000;
24
+ export declare const DEFAULT_JOB_BOARD_ENABLED = true;
25
+ export declare const DEFAULT_JOB_BOARD_STRATEGY: "latest";
26
+ export declare const DEFAULT_MAX_RETAINED_SNAPSHOTS = 20;
27
+ export declare const RECONCILE_CONFIRMATION_GRACE_MS = 5000;
15
28
  export type ProcessCleanupEvent = NodeJS.Signals | "beforeExit" | "exit";
16
29
  export type OpencodeClient = PluginInput["client"];
17
30
  export interface MessagePartInfo {
@@ -26,7 +26,19 @@ export declare const BgHandleSchema: z.ZodObject<{
26
26
  pending: "pending";
27
27
  running: "running";
28
28
  completed: "completed";
29
+ stopped: "stopped";
30
+ statusUncertain: "statusUncertain";
29
31
  }>;
32
+ sessionID: z.ZodOptional<z.ZodString>;
33
+ terminalReason: z.ZodOptional<z.ZodEnum<{
34
+ aborted: "aborted";
35
+ "queue-saturated": "queue-saturated";
36
+ "no-output": "no-output";
37
+ uncertain: "uncertain";
38
+ stale: "stale";
39
+ "nested-depth-exceeded": "nested-depth-exceeded";
40
+ "wall-clock-timeout": "wall-clock-timeout";
41
+ }>>;
30
42
  model: z.ZodOptional<z.ZodObject<{
31
43
  providerID: z.ZodString;
32
44
  modelID: z.ZodString;
@@ -1,7 +1,7 @@
1
1
  import type { PluginInput } from "@opencode-ai/plugin";
2
- import type { BackgroundTaskConfig, TmuxConfig } from "../../config/schema";
2
+ import type { BackgroundTaskConfig, DcpHandoffCompression, TmuxConfig } from "../../config/schema";
3
3
  import { TaskHistory } from "./task-history";
4
- import type { BackgroundTask, LaunchInput, ResumeInput } from "./types";
4
+ import type { BackgroundTask, LaunchInput, ResumeInput, ReviveInput } from "./types";
5
5
  export interface EventProperties {
6
6
  sessionID?: string;
7
7
  info?: {
@@ -41,15 +41,26 @@ export declare class BackgroundManager {
41
41
  private processingKeys;
42
42
  private completionTimers;
43
43
  private idleDeferralTimers;
44
+ private wakeScheduler;
44
45
  private notificationQueueByParent;
45
46
  private enableParentSessionNotifications;
46
47
  private cachedCircuitBreakerSettings?;
48
+ private handoffCompression?;
49
+ /** Active nested bypass admits per concurrency key (maxDepth cap). */
50
+ private nestedActive;
51
+ /** Task IDs admitted via nested bypass — used to decrement `nestedActive` exactly once. */
52
+ private nestedBypassTaskIds;
53
+ /** Elapsed-time bound supervisor (U7 wall-clock). OFF by default — arms nothing when disabled. */
54
+ private wallclock;
55
+ /** Grace timers pending a terminal wall-clock mark, keyed by task id. */
56
+ private wallclockGraceTimers;
47
57
  readonly taskHistory: TaskHistory;
48
58
  constructor(ctx: PluginInput, config?: BackgroundTaskConfig, options?: {
49
59
  tmuxConfig?: TmuxConfig;
50
60
  onSubagentSessionCreated?: OnSubagentSessionCreated;
51
61
  onShutdown?: () => void;
52
62
  enableParentSessionNotifications?: boolean;
63
+ handoffCompression?: DcpHandoffCompression;
53
64
  });
54
65
  /**
55
66
  * Persist a lightweight handle for the given task. Called on running and
@@ -57,14 +68,45 @@ export declare class BackgroundManager {
57
68
  * Best-effort: write failures are logged and never break task lifecycle.
58
69
  */
59
70
  private persistHandle;
71
+ private armWallclock;
72
+ private disarmWallclock;
73
+ private onWallclockFire;
74
+ private completeWallclockTimeout;
60
75
  /**
61
76
  * Recover handles persisted by a previous manager/process. Sweeps stale
62
- * handles first, then loads the remainder into memory. Running handles are
63
- * marked `"interrupt"` (C6) and no concurrency is re-acquired (C7).
77
+ * handles first, then loads the remainder into memory. Persisted
78
+ * `running|pending` handles are reconciled against the live host instead of
79
+ * being flattened to a false `"interrupt"` (C6). No concurrency is
80
+ * re-acquired for restored running handles (C7).
64
81
  */
65
82
  restoreHandles(): Promise<void>;
83
+ /**
84
+ * Probe the live host for a persisted in-flight handle and apply the
85
+ * reconciled outcome. Never throws: any unexpected failure degrades to
86
+ * `statusUncertain`, never a false completion. `restoreHandles()`'s caller
87
+ * is fire-and-forget (`create-managers.ts`), so rejection is not an option.
88
+ */
89
+ private reconcileRestoredTask;
66
90
  launch(input: LaunchInput): Promise<BackgroundTask>;
67
91
  private processKey;
92
+ /**
93
+ * Admit a nested launch. Bypass mode grants immediately without touching the
94
+ * semaphore; reserve mode first tries the reserved slot with a bounded wait
95
+ * and falls back to bypass overflow. Both modes enforce the maxDepth cap.
96
+ * Returns "skip" when the item was terminated (depth exceeded / cancelled).
97
+ */
98
+ private admitNested;
99
+ /**
100
+ * Terminal `stopped` outcome for a queued task that was never admitted.
101
+ * Mirrors the cancelTask terminal+notify sequence but never releases a slot
102
+ * (none was taken) and routes through the same parent-notification pipeline.
103
+ */
104
+ private terminateQueuedTask;
105
+ /**
106
+ * Decrement the nested bypass count for a task exactly once. Idempotent:
107
+ * repeated calls after the first are no-ops and can never underflow.
108
+ */
109
+ private decrementNestedActive;
68
110
  private startTask;
69
111
  getTask(id: string): BackgroundTask | undefined;
70
112
  getTasksByParentSession(sessionID: string): BackgroundTask[];
@@ -85,6 +127,17 @@ export declare class BackgroundManager {
85
127
  concurrencyKey?: string;
86
128
  }): Promise<BackgroundTask>;
87
129
  resume(input: ResumeInput): Promise<BackgroundTask>;
130
+ /** Revive a terminal task with a new prompt, from memory or disk. Bounded admission; saturated queue fails truthfully. */
131
+ revive(input: ReviveInput): Promise<BackgroundTask>;
132
+ /** Revivable terminal tasks: in-memory first (wins on taskId), then disk; newest-first. */
133
+ listRevivable(parentSessionID?: string): Array<{
134
+ taskId: string;
135
+ description: string;
136
+ agent: string;
137
+ status: string;
138
+ sessionID: string;
139
+ terminalReason?: string;
140
+ }>;
88
141
  private checkSessionTodos;
89
142
  handleEvent(event: Event): void;
90
143
  markForNotification(task: BackgroundTask): void;
@@ -100,6 +153,7 @@ export declare class BackgroundManager {
100
153
  /**
101
154
  * Validates that a session has actual assistant/tool output before marking complete.
102
155
  * Prevents premature completion when session.idle fires before agent responds.
156
+ * Delegates to the shared `session-output` helper (also used by reconciliation).
103
157
  */
104
158
  private validateSessionHasOutput;
105
159
  private clearNotificationsForTask;
@@ -108,6 +162,7 @@ export declare class BackgroundManager {
108
162
  * Cleans up the parent entry if no pending tasks remain.
109
163
  */
110
164
  private cleanupPendingByParent;
165
+ private refreshParentWake;
111
166
  /**
112
167
  * Fire-and-forget session abort. Logs failures at debug level instead of
113
168
  * swallowing errors silently — useful for diagnosing zombie sessions.
@@ -15,3 +15,4 @@ export declare function resolveAgentAndModel(client: {
15
15
  modelID: string;
16
16
  } | undefined;
17
17
  }>;
18
+ export declare function buildJobBoardNotification(snapshot: import("./task-history").JobBoardSnapshot): string;
@@ -0,0 +1,33 @@
1
+ import type { BgHandle } from "./handle-index";
2
+ import type { BackgroundTerminalReason } from "./types";
3
+ export type ReconcileOutcome = {
4
+ status: "completed" | "error" | "running" | "stopped" | "statusUncertain";
5
+ terminalReason?: BackgroundTerminalReason;
6
+ };
7
+ export interface ReconcileProbeClient {
8
+ session: {
9
+ status: () => Promise<unknown>;
10
+ messages: (args: {
11
+ path: {
12
+ id: string;
13
+ };
14
+ }) => Promise<unknown>;
15
+ todo: (args: {
16
+ path: {
17
+ id: string;
18
+ };
19
+ }) => Promise<unknown>;
20
+ };
21
+ }
22
+ export interface ReconcileDeps {
23
+ validateOutput?: (sessionID: string) => Promise<boolean>;
24
+ sleep?: (ms: number) => Promise<void>;
25
+ }
26
+ /**
27
+ * Classify a persisted `running|pending` handle against the live host.
28
+ *
29
+ * Deterministic order: unprobeable → uncertain; non-idle → running; recorded
30
+ * error → error; awaiting-user → running; no output → stopped; output with
31
+ * incomplete todos → running; otherwise completed. Never throws.
32
+ */
33
+ export declare function reconcileHandle(client: ReconcileProbeClient, handle: BgHandle, deps?: ReconcileDeps): Promise<ReconcileOutcome>;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Revive eligibility classification for background tasks.
3
+ *
4
+ * Pure logic: decides whether a persisted handle may be revived into a new
5
+ * session. No I/O, no manager access, no client imports.
6
+ */
7
+ import type { BgHandle } from "./handle-index";
8
+ import type { BackgroundTask } from "./types";
9
+ export declare const REVIVABLE_STATUSES: readonly ["cancelled", "stopped", "interrupt", "error", "completed"];
10
+ export declare function isRevivableStatus(status: string): boolean;
11
+ export type ReviveBlockReason = "active" | "uncertain" | "no-session" | "unknown-task" | "expired";
12
+ export type ReviveEligibility = {
13
+ eligible: true;
14
+ } | {
15
+ eligible: false;
16
+ reason: ReviveBlockReason;
17
+ };
18
+ export declare function classifyRevivable(handle: {
19
+ status: string;
20
+ sessionID?: string;
21
+ terminalReason?: string;
22
+ }, opts?: {
23
+ force?: boolean;
24
+ }): ReviveEligibility;
25
+ /**
26
+ * Locate a revivable handle by task id or session id. `taskId` wins when
27
+ * both are supplied. Returns `undefined` when neither matches.
28
+ */
29
+ export declare function findRevivableHandle(handles: BgHandle[], opts: {
30
+ taskId?: string;
31
+ sessionId?: string;
32
+ }): BgHandle | undefined;
33
+ /**
34
+ * Rehydrate a pre-admission `BackgroundTask` from a persisted handle with a
35
+ * NEW prompt. Mirrors `restoreTaskFromHandle` except `prompt` comes from the
36
+ * caller and `status` restarts at `"pending"`; `startedAt` is left unset (it
37
+ * is assigned on admission) and `completedAt`/`error` are cleared.
38
+ */
39
+ export declare function toReviveTask(handle: BgHandle, prompt: string): BackgroundTask;
@@ -0,0 +1,40 @@
1
+ export interface SessionOutputClient {
2
+ session: {
3
+ messages: (args: {
4
+ path: {
5
+ id: string;
6
+ };
7
+ }) => Promise<unknown>;
8
+ };
9
+ }
10
+ interface SessionMessagePart {
11
+ type?: string;
12
+ text?: string;
13
+ content?: string | unknown[];
14
+ }
15
+ export interface SessionMessage {
16
+ info?: {
17
+ role?: string;
18
+ error?: unknown;
19
+ };
20
+ parts?: SessionMessagePart[];
21
+ }
22
+ /**
23
+ * Fetch the raw messages for a session. Throws on transport failure so callers
24
+ * can decide between fail-open (legacy) and fail-safe (reconciliation).
25
+ */
26
+ export declare function fetchSessionMessages(client: SessionOutputClient, sessionID: string): Promise<SessionMessage[]>;
27
+ /**
28
+ * True when the session produced real assistant/tool output with content.
29
+ * Shared by `validateSessionHasOutput` (manager) and `reconcileHandle`.
30
+ */
31
+ export declare function messagesHaveAssistantOutput(messages: SessionMessage[], sessionID?: string): boolean;
32
+ /** True when any assistant message carries a recorded provider/abort error. */
33
+ export declare function messagesHaveRecordedError(messages: SessionMessage[]): boolean;
34
+ /**
35
+ * Validate that a session has actual assistant/tool output before marking
36
+ * complete. Fail-open: transport errors return true so a flaky lookup cannot
37
+ * block the existing polling/idle completion path.
38
+ */
39
+ export declare function validateSessionHasOutput(client: SessionOutputClient, sessionID: string): Promise<boolean>;
40
+ export {};
@@ -1,4 +1,22 @@
1
1
  import type { BackgroundTaskStatus } from "./types";
2
+ export type JobBoardStrategy = "latest" | "checkpoint-compatible";
3
+ export interface JobBoardRow {
4
+ agent: string;
5
+ category?: string;
6
+ status: BackgroundTaskStatus;
7
+ description: string;
8
+ session?: string;
9
+ }
10
+ export interface JobBoardSnapshot {
11
+ strategy: JobBoardStrategy;
12
+ block: string;
13
+ retained?: string[];
14
+ }
15
+ export interface BuildJobBoardSnapshotOpts {
16
+ strategy?: JobBoardStrategy;
17
+ maxRetained?: number;
18
+ previous?: string[];
19
+ }
2
20
  export interface TaskHistoryEntry {
3
21
  id: string;
4
22
  sessionID?: string;
@@ -15,4 +33,6 @@ export declare class TaskHistory {
15
33
  getByParentSession(parentSessionID: string): TaskHistoryEntry[];
16
34
  clearSession(parentSessionID: string): void;
17
35
  formatForCompaction(parentSessionID: string): string | null;
36
+ getJobBoardEntries(parentSessionID: string): JobBoardRow[];
37
+ buildJobBoardSnapshot(parentSessionID: string, opts?: BuildJobBoardSnapshotOpts): JobBoardSnapshot | null;
18
38
  }
@@ -1,4 +1,6 @@
1
- export type BackgroundTaskStatus = "pending" | "running" | "completed" | "error" | "cancelled" | "interrupt";
1
+ export type BackgroundTaskStatus = "pending" | "running" | "completed" | "error" | "cancelled" | "interrupt" | "stopped" | "statusUncertain";
2
+ /** Why a background task reached a terminal state (persisted on the handle). */
3
+ export type BackgroundTerminalReason = "queue-saturated" | "no-output" | "uncertain" | "aborted" | "stale" | "nested-depth-exceeded" | "wall-clock-timeout";
2
4
  export interface ToolCallWindow {
3
5
  lastSignature: string;
4
6
  consecutiveCount: number;
@@ -54,6 +56,10 @@ export interface BackgroundTask {
54
56
  lastMsgCount?: number;
55
57
  /** Number of consecutive polls with stable message count */
56
58
  stablePolls?: number;
59
+ /** Why the task reached a terminal state (e.g. stopped/statusUncertain) */
60
+ terminalReason?: BackgroundTerminalReason;
61
+ /** Compressed result payload for handoff to parent session (set by tryCompleteTask) */
62
+ compactedResult?: string;
57
63
  }
58
64
  export interface LaunchInput {
59
65
  description: string;
@@ -90,4 +96,18 @@ export interface ResumeInput {
90
96
  parentAgent?: string;
91
97
  parentTools?: Record<string, boolean>;
92
98
  }
99
+ export interface ReviveInput {
100
+ taskId?: string;
101
+ sessionId?: string;
102
+ prompt: string;
103
+ parentSessionID: string;
104
+ parentMessageID: string;
105
+ parentModel?: {
106
+ providerID: string;
107
+ modelID: string;
108
+ };
109
+ parentAgent?: string;
110
+ parentTools?: Record<string, boolean>;
111
+ force?: boolean;
112
+ }
93
113
  export {};