opencode-matrixx-v2 1.2.2 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/README.md +5 -5
  2. package/dist/agents/{cipher.d.ts → definitions/cipher.d.ts} +2 -2
  3. package/dist/agents/{construct.d.ts → definitions/construct.d.ts} +2 -2
  4. package/dist/agents/definitions/index.d.ts +14 -0
  5. package/dist/agents/{keymaker.d.ts → definitions/keymaker.d.ts} +2 -2
  6. package/dist/agents/{merovingian.d.ts → definitions/merovingian.d.ts} +3 -3
  7. package/dist/agents/{morpheus.d.ts → definitions/morpheus.d.ts} +2 -2
  8. package/dist/agents/{mouse → definitions/mouse}/agent.d.ts +2 -2
  9. package/dist/agents/{niobe → definitions/niobe}/agent.d.ts +4 -4
  10. package/dist/agents/{niobe → definitions/niobe}/index.d.ts +1 -1
  11. package/dist/agents/{niobe → definitions/niobe}/prompt-section-builder.d.ts +2 -2
  12. package/dist/agents/{operator.d.ts → definitions/operator.d.ts} +2 -2
  13. package/dist/agents/{oracle → definitions/oracle}/system-prompt.d.ts +1 -1
  14. package/dist/agents/{sati.d.ts → definitions/sati.d.ts} +2 -2
  15. package/dist/agents/{sentinel.d.ts → definitions/sentinel.d.ts} +2 -2
  16. package/dist/agents/{seraph.d.ts → definitions/seraph.d.ts} +2 -2
  17. package/dist/agents/{smith.d.ts → definitions/smith.d.ts} +2 -2
  18. package/dist/agents/{trinity.d.ts → definitions/trinity.d.ts} +2 -2
  19. package/dist/agents/index.d.ts +14 -14
  20. package/dist/agents/{builtin-agents → registry}/agent-overrides.d.ts +2 -2
  21. package/dist/agents/{builtin-agents → registry}/available-skills.d.ts +1 -1
  22. package/dist/agents/{builtin-agents → registry}/general-agents.d.ts +4 -4
  23. package/dist/agents/{builtin-agents.d.ts → registry/index.d.ts} +4 -4
  24. package/dist/agents/{builtin-agents → registry}/keymaker-agent.d.ts +3 -3
  25. package/dist/agents/{builtin-agents → registry}/morpheus-agent.d.ts +3 -3
  26. package/dist/agents/{builtin-agents → registry}/niobe-agent.d.ts +3 -3
  27. package/dist/agents/{agent-builder.d.ts → shared/agent-builder.d.ts} +1 -1
  28. package/dist/agents/{agent-config.d.ts → shared/agent-config.d.ts} +3 -3
  29. package/dist/agents/{agents.transform.d.ts → shared/agents.transform.d.ts} +1 -1
  30. package/dist/agents/{dynamic-agent-prompt-builder.d.ts → shared/dynamic-agent-prompt-builder.d.ts} +2 -2
  31. package/dist/cli.js +22 -9
  32. package/dist/config/schema/agent-names.d.ts +1 -1
  33. package/dist/config/schema/categories.d.ts +4 -4
  34. package/dist/config/schema/commands.d.ts +3 -3
  35. package/dist/config/schema/dcp.d.ts +13 -0
  36. package/dist/config/schema/hooks.d.ts +1 -0
  37. package/dist/config/schema/matrixx-config.d.ts +11 -4
  38. package/dist/features/background-agent/handle-index.d.ts +31 -0
  39. package/dist/features/background-agent/index.d.ts +1 -1
  40. package/dist/features/background-agent/manager/lifecycle.d.ts +2 -1
  41. package/dist/features/background-agent/manager/manager.d.ts +10 -1
  42. package/dist/features/background-agent/manager/reconcile.d.ts +9 -0
  43. package/dist/features/background-agent/manager/store.d.ts +13 -1
  44. package/dist/features/background-agent/message-dir.d.ts +3 -0
  45. package/dist/features/background-agent/revive.d.ts +54 -0
  46. package/dist/features/background-agent/state.d.ts +2 -5
  47. package/dist/features/background-agent/task-map.d.ts +31 -0
  48. package/dist/features/background-agent/types.d.ts +3 -1
  49. package/dist/features/background-agent/wallclock.d.ts +15 -20
  50. package/dist/features/builtin-commands/templates/end-redpill.d.ts +1 -0
  51. package/dist/features/builtin-commands/templates/init-deep.d.ts +1 -1
  52. package/dist/features/builtin-commands/templates/redpill.d.ts +1 -0
  53. package/dist/features/builtin-commands/templates/research.d.ts +1 -1
  54. package/dist/features/builtin-commands/types.d.ts +1 -1
  55. package/dist/features/redpill-state/index.d.ts +1 -0
  56. package/dist/features/redpill-state/manager.d.ts +6 -0
  57. package/dist/features/session-memory/types.d.ts +1 -1
  58. package/dist/features/task-storage/generation.d.ts +13 -0
  59. package/dist/features/task-storage/index.d.ts +2 -1
  60. package/dist/features/task-storage/read-errors.d.ts +16 -0
  61. package/dist/features/task-storage/storage.d.ts +29 -1
  62. package/dist/features/task-storage/types.d.ts +1 -0
  63. package/dist/hooks/category-skill-reminder/formatter.d.ts +1 -1
  64. package/dist/hooks/category-skill-reminder/hook.d.ts +1 -1
  65. package/dist/hooks/keyword-detector/constants.d.ts +1 -1
  66. package/dist/hooks/keyword-detector/detector.d.ts +1 -1
  67. package/dist/hooks/keyword-detector/redpill/deepseek.d.ts +2 -0
  68. package/dist/hooks/keyword-detector/redpill/default.d.ts +2 -0
  69. package/dist/hooks/keyword-detector/redpill/gemini.d.ts +2 -0
  70. package/dist/hooks/keyword-detector/redpill/glm.d.ts +2 -0
  71. package/dist/hooks/keyword-detector/redpill/gpt5.2.d.ts +2 -0
  72. package/dist/hooks/keyword-detector/redpill/index.d.ts +26 -0
  73. package/dist/hooks/keyword-detector/redpill/manifesto.d.ts +17 -0
  74. package/dist/hooks/keyword-detector/redpill/mimo.d.ts +2 -0
  75. package/dist/hooks/keyword-detector/redpill/planner.d.ts +2 -0
  76. package/dist/hooks/keyword-detector/{ultrawork → redpill}/source-detector.d.ts +8 -8
  77. package/dist/hooks/matrix-loop/loop-state-controller.d.ts +1 -1
  78. package/dist/hooks/matrix-loop/matrix-loop-event-handler.d.ts +1 -0
  79. package/dist/hooks/matrix-loop/matrix-loop-hook.d.ts +1 -1
  80. package/dist/hooks/matrix-loop/types.d.ts +1 -1
  81. package/dist/hooks/niobe/event-handler.d.ts +14 -0
  82. package/dist/hooks/niobe/types.d.ts +1 -0
  83. package/dist/hooks/runtime-fallback/fallback-state.d.ts +6 -1
  84. package/dist/hooks/stop-continuation-guard/hook.d.ts +17 -0
  85. package/dist/hooks/stop-continuation-guard/index.d.ts +1 -0
  86. package/dist/hooks/stop-continuation-guard/stop-deadline.d.ts +27 -0
  87. package/dist/index.js +6125 -5903
  88. package/dist/matrixx.schema.json +47 -5
  89. package/dist/plugin/handlers/oracle-agent-config-builder.d.ts +2 -2
  90. package/dist/plugin/hooks/create-skill-hooks.d.ts +1 -1
  91. package/dist/plugin/message-hooks/compress-watchdog.d.ts +36 -0
  92. package/dist/plugin/message-hooks/index.d.ts +2 -0
  93. package/dist/plugin/setup-domains/assemble.d.ts +2 -0
  94. package/dist/plugin/setup-domains/tools.d.ts +1 -1
  95. package/dist/plugin/setup-domains.d.ts +2 -0
  96. package/dist/plugin/tool/available-categories.d.ts +1 -1
  97. package/dist/plugin/tool/skill-context.d.ts +1 -1
  98. package/dist/plugin/tool/tool-catalog.d.ts +1 -1
  99. package/dist/shared/agent/agent-display-names.d.ts +1 -1
  100. package/dist/shared/policy/compress-watchdog.d.ts +86 -0
  101. package/dist/shared/runtime/delay.d.ts +1 -1
  102. package/dist/skills/builtin/core/index.d.ts +1 -1
  103. package/dist/tools/delegate-task/constants.d.ts +8 -1
  104. package/dist/tools/delegate-task/timing.d.ts +2 -0
  105. package/dist/tools/delegate-task/types.d.ts +1 -1
  106. package/dist/tools/task/types.d.ts +2 -0
  107. package/dist/tools.js +15 -2
  108. package/package.json +1 -1
  109. package/dist/features/background-agent/manager.bench.d.ts +0 -1
  110. package/dist/features/builtin-commands/templates/end-ultrawork.d.ts +0 -1
  111. package/dist/features/builtin-commands/templates/ultrawork.d.ts +0 -1
  112. package/dist/features/ultrawork-state/index.d.ts +0 -1
  113. package/dist/features/ultrawork-state/manager.d.ts +0 -6
  114. package/dist/hooks/keyword-detector/ultrawork/deepseek.d.ts +0 -16
  115. package/dist/hooks/keyword-detector/ultrawork/default.d.ts +0 -6
  116. package/dist/hooks/keyword-detector/ultrawork/gemini.d.ts +0 -12
  117. package/dist/hooks/keyword-detector/ultrawork/glm.d.ts +0 -11
  118. package/dist/hooks/keyword-detector/ultrawork/gpt5.2.d.ts +0 -12
  119. package/dist/hooks/keyword-detector/ultrawork/index.d.ts +0 -25
  120. package/dist/hooks/keyword-detector/ultrawork/mimo.d.ts +0 -16
  121. package/dist/hooks/keyword-detector/ultrawork/planner.d.ts +0 -6
  122. /package/dist/agents/{mouse → definitions/mouse}/deepseek.d.ts +0 -0
  123. /package/dist/agents/{mouse → definitions/mouse}/default.d.ts +0 -0
  124. /package/dist/agents/{mouse → definitions/mouse}/gpt.d.ts +0 -0
  125. /package/dist/agents/{mouse → definitions/mouse}/index.d.ts +0 -0
  126. /package/dist/agents/{mouse → definitions/mouse}/mimo.d.ts +0 -0
  127. /package/dist/agents/{mouse → definitions/mouse}/qwen.d.ts +0 -0
  128. /package/dist/agents/{mouse → definitions/mouse}/shared.d.ts +0 -0
  129. /package/dist/agents/{niobe → definitions/niobe}/default.d.ts +0 -0
  130. /package/dist/agents/{niobe → definitions/niobe}/gpt.d.ts +0 -0
  131. /package/dist/agents/{oracle → definitions/oracle}/behavioral-summary.d.ts +0 -0
  132. /package/dist/agents/{oracle → definitions/oracle}/high-accuracy-mode.d.ts +0 -0
  133. /package/dist/agents/{oracle → definitions/oracle}/identity-constraints.d.ts +0 -0
  134. /package/dist/agents/{oracle → definitions/oracle}/index.d.ts +0 -0
  135. /package/dist/agents/{oracle → definitions/oracle}/interview-mode.d.ts +0 -0
  136. /package/dist/agents/{oracle → definitions/oracle}/plan-generation.d.ts +0 -0
  137. /package/dist/agents/{oracle → definitions/oracle}/plan-template.d.ts +0 -0
  138. /package/dist/agents/{builtin-agents → registry}/model-resolution.d.ts +0 -0
  139. /package/dist/agents/{builtin-agents → registry}/resolve-file-uri.d.ts +0 -0
  140. /package/dist/agents/{custom-agent-summaries.d.ts → shared/custom-agent-summaries.d.ts} +0 -0
  141. /package/dist/agents/{env-context.d.ts → shared/env-context.d.ts} +0 -0
  142. /package/dist/agents/{model-directives.d.ts → shared/model-directives.d.ts} +0 -0
  143. /package/dist/agents/{types.d.ts → shared/types.d.ts} +0 -0
  144. /package/dist/skills/builtin/core/{ulw-research.d.ts → rp-research.d.ts} +0 -0
@@ -10,6 +10,12 @@ import type { BackgroundTask } from "./types";
10
10
  *
11
11
  * This lets a freshly-created `BackgroundManager` recover previously-created
12
12
  * `bg_*` handles after a plugin/process restart.
13
+ *
14
+ * Stale-handle guard: every handle carries a `generation` counter. Removing a
15
+ * handle (explicit delete or TTL sweep) bumps a per-task tombstone
16
+ * (`<taskId>.gen`), and the next write for that id embeds the bumped value.
17
+ * `readHandle` with an expected generation rejects mismatches, so a handle
18
+ * captured before removal can never resolve to a new task reusing the id.
13
19
  */
14
20
  export declare const BG_HANDLE_DIR_NAME = "bg-handles";
15
21
  export declare const BG_HANDLE_FILE_PREFIX = "bg_";
@@ -52,21 +58,34 @@ export declare const BgHandleSchema: z.ZodObject<{
52
58
  queuedAt: z.ZodOptional<z.ZodNumber>;
53
59
  startedAt: z.ZodOptional<z.ZodNumber>;
54
60
  completedAt: z.ZodOptional<z.ZodNumber>;
61
+ generation: z.ZodDefault<z.ZodNumber>;
55
62
  }, z.core.$strict>;
56
63
  export type BgHandle = z.infer<typeof BgHandleSchema>;
57
64
  /** Project-scoped handle directory: `<project>/.matrixx/bg-handles`. */
58
65
  export declare function getBgHandleDir(directory: string): string;
59
66
  /** One file per handle id: `<project>/.matrixx/bg-handles/<taskId>.json`. */
60
67
  export declare function getHandlePath(directory: string, taskId: string): string;
68
+ /** Tombstone holding the bumped generation after a handle is removed. Never ends in `.json`, so index scans skip it. */
69
+ export declare function getGenerationPath(directory: string, taskId: string): string;
61
70
  /** Single source of truth for the OpenCode subagent session title format. */
62
71
  export declare function buildSubagentTitle(description: unknown, agent: unknown, category?: unknown): string;
63
72
  /** Project a full task onto the lightweight, persistable handle index. */
64
73
  export declare function toHandle(task: BackgroundTask): BgHandle;
74
+ export declare function currentGeneration(directory: string, taskId: string): number;
75
+ export declare function bumpGeneration(directory: string, taskId: string): void;
65
76
  /**
66
77
  * Atomically persist a handle: write to a temp file then rename into place.
78
+ * The embedded generation is the current counter for the id, so a handle
79
+ * recreated after removal carries a strictly greater value than the removed one.
67
80
  * Throws on write failure; callers decide how to surface it.
68
81
  */
69
82
  export declare function writeHandle(directory: string, task: BackgroundTask): void;
83
+ /**
84
+ * Read one handle by id. When `expectedGeneration` is given, a handle whose
85
+ * embedded generation differs (stale reference, or a new task reusing the id
86
+ * after removal) is rejected with a log line and `null` is returned.
87
+ */
88
+ export declare function readHandle(directory: string, taskId: string, expectedGeneration?: number): BgHandle | null;
70
89
  /** Read and validate every persisted handle. Invalid/corrupt files are skipped. */
71
90
  export declare function readHandles(directory: string): BgHandle[];
72
91
  /** Remove the handle file for a task id. Returns true when a file was deleted. */
@@ -77,3 +96,15 @@ export declare function deleteHandleFile(directory: string, taskId: string): boo
77
96
  * directory cannot grow without bound. Returns the number of files removed.
78
97
  */
79
98
  export declare function sweepStaleHandles(directory: string, ttlMs?: number, now?: number): number;
99
+ /**
100
+ * Single-pass sweep + read: one `readdirSync` and one `readHandleFile` per
101
+ * handle file. Semantics match `sweepStaleHandles` followed by `readHandles`:
102
+ * corrupt/unparseable files are swept (never bump generation for them — there
103
+ * is no taskId), stale or timestamp-less readable handles are swept with a
104
+ * generation bump, fresh handles are returned. Files swept here never appear
105
+ * in `handles`. Missing directory yields an empty result without throwing.
106
+ */
107
+ export declare function sweepAndReadHandles(directory: string, ttlMs?: number, now?: number): {
108
+ handles: BgHandle[];
109
+ removed: number;
110
+ };
@@ -4,7 +4,7 @@
4
4
  * - `hooks/background-task-blocker/` guards tool execution while background tasks run.
5
5
  * - `tools/background-task/` exposes agent-callable task controls (cancel/output/revive).
6
6
  */
7
- export { BG_HANDLE_FILE_PREFIX, type BgHandle, BgHandleSchema, deleteHandleFile, getBgHandleDir, getHandlePath, readHandles, sweepStaleHandles, toHandle, writeHandle, } from "./handle-index";
7
+ export { BG_HANDLE_FILE_PREFIX, type BgHandle, BgHandleSchema, deleteHandleFile, getBgHandleDir, getHandlePath, readHandles, sweepAndReadHandles, sweepStaleHandles, toHandle, writeHandle, } from "./handle-index";
8
8
  export { BackgroundManager, type OnSubagentSessionCreated, type SubagentSessionCreatedEvent } from "./manager";
9
9
  export { TaskStateManager } from "./state";
10
10
  export { TaskHistory, type TaskHistoryEntry } from "./task-history";
@@ -1,5 +1,5 @@
1
1
  import type { NativeDomains } from "../../../shared/session/session-context-source";
2
- import type { BackgroundTask, LaunchInput, ResumeInput } from "../types";
2
+ import type { BackgroundTask, BackgroundTaskStatus, LaunchInput, ResumeInput } from "../types";
3
3
  import type { ManagerRuntime } from "./types";
4
4
  /**
5
5
  * Task lifecycle: restore, launch, track, resume, prompt.
@@ -8,6 +8,7 @@ import type { ManagerRuntime } from "./types";
8
8
  * `BackgroundManager` receiver — same statements, no `this`. Thin
9
9
  * delegating methods on `BackgroundManager` preserve the public API.
10
10
  */
11
+ export declare function isSettled(status: BackgroundTaskStatus): boolean;
11
12
  export declare function restoreHandles(rt: ManagerRuntime): Promise<void>;
12
13
  export declare function launchTask(rt: ManagerRuntime, input: LaunchInput & {
13
14
  sessionId?: string;
@@ -98,6 +98,7 @@ export declare class BackgroundManager implements ManagerRuntime {
98
98
  handleEvent(event: V2Event): void;
99
99
  getKnownSessionIds(): Set<string>;
100
100
  getTask(id: string): BackgroundTask | undefined;
101
+ persistHandleFenced(task: BackgroundTask, expectedGeneration: number): void;
101
102
  getTasksByParentSession(sessionID: string): BackgroundTask[];
102
103
  getAllDescendantTasks(sessionID: string): BackgroundTask[];
103
104
  getNativeDescendants(sessionId: string): ReturnType<ManagerStore["getNativeDescendants"]>;
@@ -111,7 +112,9 @@ export declare class BackgroundManager implements ManagerRuntime {
111
112
  }): Promise<boolean>;
112
113
  cancelPendingTask(taskId: string): boolean;
113
114
  cancelAllForSession(parentSessionID: string): number;
114
- waitForAllDescendants(sessionID: string, timeoutMs?: number, pollIntervalMs?: number): Promise<{
115
+ waitForAllDescendants(sessionID: string, timeoutMs?: number, pollIntervalMs?: number, options?: {
116
+ signal?: AbortSignal;
117
+ }): Promise<{
115
118
  completed: Array<{
116
119
  id: string;
117
120
  description: string;
@@ -125,5 +128,11 @@ export declare class BackgroundManager implements ManagerRuntime {
125
128
  status: string;
126
129
  }>;
127
130
  }>;
131
+ waiterCount(): number;
132
+ rejectWaiters(sessionID: string | undefined, err: unknown): void;
128
133
  shutdown(): void;
134
+ shutdownWithDeadline(deadlineMs?: number): {
135
+ forced: boolean;
136
+ abandoned: string[];
137
+ };
129
138
  }
@@ -2,6 +2,15 @@ import type { V2Event } from "../../../plugin/tool/context";
2
2
  import type { BackgroundTask, ReviveInput } from "../types";
3
3
  import type { BackgroundManager } from "./manager";
4
4
  import type { ManagerRuntime, ResolveAnyResult } from "./types";
5
+ /**
6
+ * B11 minimal gate: quarantine corrupt handle files before revival.
7
+ *
8
+ * Links the B7 error contract (`StorageCorruptError` in task-storage):
9
+ * unreadable or shape-invalid `bg_*.json` files are renamed aside to
10
+ * `<name>.corrupt` + logged (never deleted, never crash revival).
11
+ * Best-effort: individual failures are logged and skipped.
12
+ */
13
+ export declare function quarantineCorruptHandles(directory: string): number;
5
14
  export declare function reviveTask(rt: ManagerRuntime, input: ReviveInput): Promise<BackgroundTask>;
6
15
  export declare function listRevivable(rt: ManagerRuntime, parentSessionID?: string): Array<{
7
16
  taskId: string;
@@ -1,5 +1,7 @@
1
1
  import type { BackgroundTaskConfig } from "../../../config/schema";
2
+ import { TaskMap } from "../task-map";
2
3
  import type { BackgroundTask } from "../types";
4
+ import { WallclockSupervisor } from "../wallclock";
3
5
  import type { NativeDescendant } from "./types";
4
6
  /**
5
7
  * In-memory task registry behind `BackgroundManager`.
@@ -11,12 +13,18 @@ import type { NativeDescendant } from "./types";
11
13
  * store through `ManagerRuntime` — they never touch `BackgroundManager`.
12
14
  */
13
15
  export declare class ManagerStore {
14
- readonly tasks: Map<string, BackgroundTask>;
16
+ readonly tasks: TaskMap<BackgroundTask>;
15
17
  readonly knownSessions: Set<string>;
16
18
  readonly nativeDescCache: Map<string, {
17
19
  at: number;
18
20
  rows: NativeDescendant[];
19
21
  }>;
22
+ readonly wallclock: WallclockSupervisor;
23
+ readonly pendingSpawns: Set<string>;
24
+ readonly waiters: Set<{
25
+ sessionID: string;
26
+ reject: (err: unknown) => void;
27
+ }>;
20
28
  directory: string;
21
29
  config?: BackgroundTaskConfig;
22
30
  constructor(directory: string, config?: BackgroundTaskConfig);
@@ -28,6 +36,10 @@ export declare class ManagerStore {
28
36
  getNativeDescendants(sessionId: string): NativeDescendant[];
29
37
  findBySession(sessionID: string): BackgroundTask | undefined;
30
38
  findDiskTaskBySession(sessionID: string): BackgroundTask | undefined;
39
+ disarmWallclock(taskId: string): void;
31
40
  taskTtlMs(): number;
32
41
  persistHandle(task: BackgroundTask): void;
42
+ currentGeneration(taskId: string): number;
43
+ persistHandleFenced(task: BackgroundTask, expectedGeneration: number): void;
44
+ bumpTaskGeneration(taskId: string): number;
33
45
  }
@@ -1,4 +1,7 @@
1
1
  import { type StoredMessage } from "../context-injection/hook-bridge";
2
+ export declare function isValidSessionID(sessionID: string): boolean;
3
+ export declare function assertValidSessionID(sessionID: string): void;
4
+ export declare function resolveSessionDirPath(baseDir: string, sessionID: string): string;
2
5
  export declare function getMessageDir(sessionID: string): string | null;
3
6
  export declare function _resetMessageDirCacheForTesting(): void;
4
7
  export declare function isCompactionAgent(agent: string | undefined): boolean;
@@ -22,6 +22,37 @@ export declare function classifyRevivable(handle: {
22
22
  }, opts?: {
23
23
  force?: boolean;
24
24
  }): ReviveEligibility;
25
+ /**
26
+ * B11: corrupt-handle predicate (pure, no I/O).
27
+ *
28
+ * Links the B7 error contract (`StorageCorruptError` in task-storage):
29
+ * callers quarantine (rename aside + log, never delete) any value for
30
+ * which this returns true instead of letting it crash revival. A handle
31
+ * is corrupt when it is not an object or lacks the required shape
32
+ * (`taskId` string + recognised `status` string). Unknown statuses are
33
+ * NOT corrupt — they are ineligible (`unknown-task`) via
34
+ * `classifyRevivable`, not quarantine candidates.
35
+ */
36
+ export declare function isCorruptHandleValue(value: unknown): boolean;
37
+ export type ReviveSkip = {
38
+ handle: BgHandle;
39
+ reason: ReviveBlockReason;
40
+ };
41
+ /**
42
+ * B11: partition handles into revivable vs skipped (pure, no I/O).
43
+ *
44
+ * Terminal handles WITHOUT a session (`completed`/`error`/`cancelled`
45
+ * with no `sessionID`) are never resurrected — they land in `skipped`
46
+ * with reason `no-session`. Active handles (`pending`/`running`) land
47
+ * in `skipped` with reason `active` (inspect via `background_output`,
48
+ * not revive). Callers MUST log each skip (reason + taskId).
49
+ */
50
+ export declare function filterRevivableHandles(handles: BgHandle[], opts?: {
51
+ force?: boolean;
52
+ }): {
53
+ eligible: BgHandle[];
54
+ skipped: ReviveSkip[];
55
+ };
25
56
  /**
26
57
  * Locate a revivable handle by task id or session id. `taskId` wins when
27
58
  * both are supplied. Returns `undefined` when neither matches.
@@ -36,4 +67,27 @@ export declare function findRevivableHandle(handles: BgHandle[], opts: {
36
67
  * caller and `status` restarts at `"pending"`; `startedAt` is left unset (it
37
68
  * is assigned on admission) and `completedAt`/`error` are cleared.
38
69
  */
70
+ export type DeadTargetReason = "expired" | "stale-generation" | "session-dead";
71
+ export declare class DeadReviveTargetError extends Error {
72
+ kind: "DeadTarget";
73
+ reason: DeadTargetReason;
74
+ taskId: string;
75
+ constructor(taskId: string, reason: DeadTargetReason, detail: string);
76
+ }
77
+ export type ProbeCandidate = {
78
+ taskId: string;
79
+ sessionID?: string;
80
+ generation?: number;
81
+ };
82
+ export type ProbeResult = {
83
+ alive: true;
84
+ } | {
85
+ alive: false;
86
+ reason: DeadTargetReason;
87
+ error: DeadReviveTargetError;
88
+ };
89
+ export declare function probeReviveTarget(directory: string, candidate: ProbeCandidate, opts?: {
90
+ expectedGeneration?: number;
91
+ isSessionLive?: (sessionID: string) => boolean;
92
+ }): ProbeResult;
39
93
  export declare function toReviveTask(handle: BgHandle, prompt: string): BackgroundTask;
@@ -1,12 +1,12 @@
1
1
  import type { QueueItem } from "./constants";
2
+ import { TaskMap } from "./task-map";
2
3
  import type { BackgroundTask, LaunchInput } from "./types";
3
4
  export declare class TaskStateManager {
4
- readonly tasks: Map<string, BackgroundTask>;
5
+ readonly tasks: TaskMap<BackgroundTask>;
5
6
  readonly notifications: Map<string, BackgroundTask[]>;
6
7
  readonly pendingByParent: Map<string, Set<string>>;
7
8
  readonly queuesByKey: Map<string, QueueItem[]>;
8
9
  readonly processingKeys: Set<string>;
9
- readonly completionTimers: Map<string, ReturnType<typeof setTimeout>>;
10
10
  getTask(id: string): BackgroundTask | undefined;
11
11
  findBySession(sessionID: string): BackgroundTask | undefined;
12
12
  getTasksByParentSession(sessionID: string): BackgroundTask[];
@@ -27,9 +27,6 @@ export declare class TaskStateManager {
27
27
  addToQueue(key: string, item: QueueItem): void;
28
28
  getQueue(key: string): QueueItem[] | undefined;
29
29
  removeFromQueue(key: string, taskId: string): boolean;
30
- setCompletionTimer(taskId: string, timer: ReturnType<typeof setTimeout>): void;
31
- clearCompletionTimer(taskId: string): void;
32
- clearAllCompletionTimers(): void;
33
30
  clear(): void;
34
31
  cancelPendingTask(taskId: string): boolean;
35
32
  }
@@ -0,0 +1,31 @@
1
+ import type { BackgroundTask } from "./types";
2
+ type SessionNormalizer = (sessionID: string) => string;
3
+ /**
4
+ * Task registry keyed by task id that also maintains secondary indices for the
5
+ * two lookup shapes the manager performs on every poll/notification:
6
+ *
7
+ * - `sessionID -> taskId` (O(1) `bySession`)
8
+ * - `parentSessionID -> Set<taskId>` (O(k) `byParent`)
9
+ *
10
+ * The map stays a `Map` so every existing `set/get/delete/clear/size/values`
11
+ * call site keeps working. Because tasks are also mutated in place — most
12
+ * notably `task.sessionID` is assigned after insertion (`manager/lifecycle.ts`)
13
+ * — mutations raise `dirty`, and a lookup that misses rebuilds once from the
14
+ * live entries before reporting absence. A hit never pays for a rebuild.
15
+ */
16
+ export declare class TaskMap<T extends BackgroundTask> extends Map<string, T> {
17
+ private readonly sessionIndex;
18
+ private readonly parentIndex;
19
+ private readonly normalizeSessionID;
20
+ dirty: boolean;
21
+ constructor(normalizeSessionID?: SessionNormalizer);
22
+ set(key: string, task: T): this;
23
+ delete(key: string): boolean;
24
+ clear(): void;
25
+ bySession(sessionID: string): T | undefined;
26
+ byParent(parentSessionID: string): T[];
27
+ rebuild(): void;
28
+ private index;
29
+ private unindex;
30
+ }
31
+ export {};
@@ -50,7 +50,7 @@ export interface BackgroundTask {
50
50
  parentTools?: Record<string, boolean>;
51
51
  /** Marks if the task was launched from an unstable agent/category */
52
52
  isUnstableAgent?: boolean;
53
- /** Category used for this task (e.g., 'quick', 'construct') */
53
+ /** Category used for this task (e.g., 'bullet-time', 'construct') */
54
54
  category?: string;
55
55
  /** Last message count for stability detection */
56
56
  lastMsgCount?: number;
@@ -60,6 +60,8 @@ export interface BackgroundTask {
60
60
  terminalReason?: BackgroundTerminalReason;
61
61
  /** Compressed result payload for handoff to parent session (set by tryCompleteTask) */
62
62
  compactedResult?: string;
63
+ /** Monotonic epoch fencing token: bumped on revive/takeover, stale writers are rejected */
64
+ generation?: number;
63
65
  }
64
66
  export interface LaunchInput {
65
67
  description: string;
@@ -1,35 +1,30 @@
1
- /**
2
- * Wall-clock supervisor: fire-once elapsed-time bound for running background tasks.
3
- *
4
- * Staleness is activity-based; this module is elapsed-time-based. Each armed entry
5
- * fires its callback exactly once when `startedAtMs + timeoutMs` passes, no matter
6
- * how busy or productive the task looks. A timeout of `0` or `undefined` means OFF
7
- * and arms nothing.
8
- *
9
- * Grace contract (manager-owned, pinned here): on fire the manager aborts the
10
- * session once, waits `wallClockAbortGraceMs`, then marks the task terminal —
11
- * unless the task completed naturally during grace, in which case the natural
12
- * outcome wins and the pending mark is cancelled.
13
- *
14
- * This module must not import from manager/client/fs — pure timers only. It mirrors
15
- * the settled-flag lifecycle of `acquireWithDeadline` in `concurrency.ts`.
16
- */
17
- /** Maximum delay accepted by `setTimeout` (2^31-1 ms); enforced by schema max too. */
18
1
  export declare const MAX_WALLCLOCK_TIMEOUT_MS = 2147483647;
19
- /** Context delivered to the fire callback exactly once per armed deadline. */
20
2
  export interface WallclockFireContext {
21
3
  taskId: string;
22
4
  elapsedMs: number;
23
5
  limitMs: number;
24
6
  }
25
7
  export type WallclockFireCallback = (ctx: WallclockFireContext) => void;
26
- /** Pure remaining-time math: deadline minus now (negative when already expired). */
8
+ export interface WallclockPersistedDeadline {
9
+ deadlineMono: number;
10
+ wallStart: number;
11
+ limitMs: number;
12
+ }
13
+ export interface WallclockClock {
14
+ nowWall?: () => number;
15
+ nowMono?: () => number;
16
+ }
27
17
  export declare function remainingMs(startedAtMs: number, timeoutMs: number, nowMs?: number): number;
28
- /** OFF (`0`/`undefined`) never arms; any other value is an active elapsed-time bound. */
18
+ export declare function remainingMono(deadlineMono: number, nowMono: number): number;
29
19
  export declare function isWallclockEnabled(timeoutMs: number | undefined): timeoutMs is number;
30
20
  export declare class WallclockSupervisor {
31
21
  private entries;
22
+ private readonly nowWall;
23
+ private readonly nowMono;
24
+ constructor(clock?: WallclockClock);
32
25
  arm(taskId: string, startedAtMs: number, timeoutMs: number | undefined, onFire: WallclockFireCallback): void;
26
+ resume(taskId: string, persisted: WallclockPersistedDeadline, onFire: WallclockFireCallback): void;
27
+ snapshot(taskId: string): WallclockPersistedDeadline | undefined;
33
28
  disarm(taskId: string): boolean;
34
29
  disarmAll(): void;
35
30
  size(): number;
@@ -0,0 +1 @@
1
+ export declare const END_REDPILL_TEMPLATE = "Deactivate redpill mode for the current session.\n\nThis command will:\n1. Remove the <redpill-mode> rules block from the active context\n2. Restore default Matrixx behavior (no enforced certainty protocol, no mandatory plan agent, no required acceptance criteria)\n3. Stop redpill-specific parallel delegation pressure\n\nAfter running this command:\n- The session continues with normal Matrixx rules\n- Existing todos and plans remain unchanged\n- Already-spawned background tasks continue to completion\n- The deactivation is per-session and clears when the session ends\n\nUse this when you want to exit redpill mode explicitly and return to standard behavior. Useful for sub-tasks that should not inherit redpill rules, or when switching from heavy-execution to lighter reasoning.";
@@ -1 +1 @@
1
- export declare const INIT_DEEP_TEMPLATE = "# /init-deep\n\nGenerate hierarchical AGENTS.md files. Root + complexity-scored subdirectories.\n\n## Usage\n\n```\n/init-deep # Update mode: modify existing + create new where warranted\n/init-deep --create-new # Read existing \u2192 remove all \u2192 regenerate from scratch\n/init-deep --max-depth=2 # Limit directory depth (default: 3)\n```\n\n---\n\n## Workflow (High-Level)\n\n1. **Discovery + Analysis** (concurrent)\n - Fire background explore agents immediately\n - Main session: bash structure + LSP codemap + read existing AGENTS.md\n2. **Score & Decide** - Determine AGENTS.md locations from merged findings\n3. **Generate** - Root first, then subdirs in parallel\n4. **Review** - Deduplicate, trim, validate\n\n<critical>\n**task_create ALL phases. Mark in_progress \u2192 completed in real-time.**\n```\ntask_create({ items: [\n { subject: \"discovery\", priority: \"high\", description: \"Fire explore agents + LSP codemap + read existing\" },\n { subject: \"scoring\", priority: \"high\", description: \"Score directories, determine locations\" },\n { subject: \"generate\", priority: \"high\", description: \"Generate AGENTS.md files (root + subdirs)\" },\n { subject: \"review\", priority: \"medium\", description: \"Deduplicate, validate, trim\" }\n]})\n```\n</critical>\n\n---\n\n## Phase 1: Discovery + Analysis (Concurrent)\n\n**Mark \"discovery\" as in_progress.**\n\n### Fire Background Explore Agents IMMEDIATELY\n\nDon't wait\u2014these run async while main session works.\n\n```\n// Fire all at once, collect results later\ntask(subagent_type=\"trinity\", load_skills=[], description=\"Explore project structure\", run_in_background=true, prompt=\"Project structure: PREDICT standard patterns for detected language \u2192 REPORT deviations only\")\ntask(subagent_type=\"trinity\", load_skills=[], description=\"Find entry points\", run_in_background=true, prompt=\"Entry points: FIND main files \u2192 REPORT non-standard organization\")\ntask(subagent_type=\"trinity\", load_skills=[], description=\"Find conventions\", run_in_background=true, prompt=\"Conventions: FIND config files (.eslintrc, pyproject.toml, .editorconfig) \u2192 REPORT project-specific rules\")\ntask(subagent_type=\"trinity\", load_skills=[], description=\"Find anti-patterns\", run_in_background=true, prompt=\"Anti-patterns: FIND 'DO NOT', 'NEVER', 'ALWAYS', 'DEPRECATED' comments \u2192 LIST forbidden patterns\")\ntask(subagent_type=\"trinity\", load_skills=[], description=\"Explore build/CI\", run_in_background=true, prompt=\"Build/CI: FIND .github/workflows, Makefile \u2192 REPORT non-standard patterns\")\ntask(subagent_type=\"trinity\", load_skills=[], description=\"Find test patterns\", run_in_background=true, prompt=\"Test patterns: FIND test configs, test structure \u2192 REPORT unique conventions\")\n```\n\n<dynamic-agents>\n**DYNAMIC AGENT SPAWNING**: After bash analysis, spawn ADDITIONAL explore agents based on project scale:\n\n| Factor | Threshold | Additional Agents |\n|--------|-----------|-------------------|\n| **Total files** | >100 | +1 per 100 files |\n| **Total lines** | >10k | +1 per 10k lines |\n| **Directory depth** | \u22654 | +2 for deep exploration |\n| **Large files (>500 lines)** | >10 files | +1 for complexity hotspots |\n| **Monorepo** | detected | +1 per package/workspace |\n| **Multiple languages** | >1 | +1 per language |\n\n```bash\n# Measure project scale first\ntotal_files=$(find . -type f -not -path '*/node_modules/*' -not -path '*/.git/*' | wc -l)\ntotal_lines=$(find . -type f \\( -name \"*.ts\" -o -name \"*.py\" -o -name \"*.go\" \\) -not -path '*/node_modules/*' -exec wc -l {} + 2>/dev/null | tail -1 | awk '{print $1}')\nlarge_files=$(find . -type f \\( -name \"*.ts\" -o -name \"*.py\" \\) -not -path '*/node_modules/*' -exec wc -l {} + 2>/dev/null | awk '$1 > 500 {count++} END {print count+0}')\nmax_depth=$(find . -type d -not -path '*/node_modules/*' -not -path '*/.git/*' | awk -F/ '{print NF}' | sort -rn | head -1)\n```\n\nExample spawning:\n```\n// 500 files, 50k lines, depth 6, 15 large files \u2192 spawn 5+5+2+1 = 13 additional agents\ntask(subagent_type=\"trinity\", load_skills=[], description=\"Analyze large files\", run_in_background=true, prompt=\"Large file analysis: FIND files >500 lines, REPORT complexity hotspots\")\ntask(subagent_type=\"trinity\", load_skills=[], description=\"Explore deep modules\", run_in_background=true, prompt=\"Deep modules at depth 4+: FIND hidden patterns, internal conventions\")\ntask(subagent_type=\"trinity\", load_skills=[], description=\"Find shared utilities\", run_in_background=true, prompt=\"Cross-cutting concerns: FIND shared utilities across directories\")\n// ... more based on calculation\n```\n</dynamic-agents>\n\n### Main Session: Concurrent Analysis\n\n**While background agents run**, main session does:\n\n#### 1. Bash Structural Analysis\n```bash\n# Directory depth + file counts\nfind . -type d -not -path '*/\\.*' -not -path '*/node_modules/*' -not -path '*/venv/*' -not -path '*/dist/*' -not -path '*/build/*' | awk -F/ '{print NF-1}' | sort -n | uniq -c\n\n# Files per directory (top 30)\nfind . -type f -not -path '*/\\.*' -not -path '*/node_modules/*' | sed 's|/[^/]*$||' | sort | uniq -c | sort -rn | head -30\n\n# Code concentration by extension\nfind . -type f \\( -name \"*.py\" -o -name \"*.ts\" -o -name \"*.tsx\" -o -name \"*.js\" -o -name \"*.go\" -o -name \"*.rs\" \\) -not -path '*/node_modules/*' | sed 's|/[^/]*$||' | sort | uniq -c | sort -rn | head -20\n\n# Existing AGENTS.md / CLAUDE.md\nfind . -type f \\( -name \"AGENTS.md\" -o -name \"CLAUDE.md\" \\) -not -path '*/node_modules/*' 2>/dev/null\n```\n\n#### 2. Read Existing AGENTS.md\n```\nFor each existing file found:\n Read(filePath=file)\n Extract: key insights, conventions, anti-patterns\n Store in EXISTING_AGENTS map\n```\n\nIf `--create-new`: Read all existing first (preserve context) \u2192 then delete all \u2192 regenerate.\n\n#### 3. LSP Codemap (if available)\n```\nLspServers() # Check availability\n\n# Entry points (parallel)\nLspDocumentSymbols(filePath=\"src/index.ts\")\nLspDocumentSymbols(filePath=\"main.py\")\n\n# Key symbols (parallel)\nLspWorkspaceSymbols(filePath=\".\", query=\"class\")\nLspWorkspaceSymbols(filePath=\".\", query=\"interface\")\nLspWorkspaceSymbols(filePath=\".\", query=\"function\")\n\n# Centrality for top exports\nLspFindReferences(filePath=\"...\", line=X, character=Y)\n```\n\n**LSP Fallback**: If unavailable, rely on explore agents + AST-grep.\n\n### Collect Background Results\n\n```\n// After main session analysis done, collect all task results\nfor each task_id: background_output(task_id=\"...\")\n```\n\n**Merge: bash + LSP + existing + explore findings. Mark \"discovery\" as completed.**\n\n---\n\n## Phase 2: Scoring & Location Decision\n\n**Mark \"scoring\" as in_progress.**\n\n### Scoring Matrix\n\n| Factor | Weight | High Threshold | Source |\n|--------|--------|----------------|--------|\n| File count | 3x | >20 | bash |\n| Subdir count | 2x | >5 | bash |\n| Code ratio | 2x | >70% | bash |\n| Unique patterns | 1x | Has own config | explore |\n| Module boundary | 2x | Has index.ts/__init__.py | bash |\n| Symbol density | 2x | >30 symbols | LSP |\n| Export count | 2x | >10 exports | LSP |\n| Reference centrality | 3x | >20 refs | LSP |\n\n### Decision Rules\n\n| Score | Action |\n|-------|--------|\n| **Root (.)** | ALWAYS create |\n| **>15** | Create AGENTS.md |\n| **8-15** | Create if distinct domain |\n| **<8** | Skip (parent covers) |\n\n### Output\n```\nAGENTS_LOCATIONS = [\n { path: \".\", type: \"root\" },\n { path: \"src/hooks\", score: 18, reason: \"high complexity\" },\n { path: \"src/api\", score: 12, reason: \"distinct domain\" }\n]\n```\n\n**Mark \"scoring\" as completed.**\n\n---\n\n## Phase 3: Generate AGENTS.md\n\n**Mark \"generate\" as in_progress.**\n\n<critical>\n**File Writing Rule**: If AGENTS.md already exists at the target path \u2192 use `Edit` tool. If it does NOT exist \u2192 use `Write` tool.\nNEVER use Write to overwrite an existing file. ALWAYS check existence first via `Read` or discovery results.\n</critical>\n\n### Root AGENTS.md (Full Treatment)\n\n```markdown\n# PROJECT KNOWLEDGE BASE\n\n**Generated:** {TIMESTAMP}\n**Commit:** {SHORT_SHA}\n**Branch:** {BRANCH}\n\n## OVERVIEW\n{1-2 sentences: what + core stack}\n\n## STRUCTURE\n\\`\\`\\`\n{root}/\n\u251C\u2500\u2500 {dir}/ # {non-obvious purpose only}\n\u2514\u2500\u2500 {entry}\n\\`\\`\\`\n\n## WHERE TO LOOK\n| Task | Location | Notes |\n|------|----------|-------|\n\n## CODE MAP\n{From LSP - skip if unavailable or project <10 files}\n\n| Symbol | Type | Location | Refs | Role |\n|--------|------|----------|------|------|\n\n## CONVENTIONS\n{ONLY deviations from standard}\n\n## ANTI-PATTERNS (THIS PROJECT)\n{Explicitly forbidden here}\n\n## UNIQUE STYLES\n{Project-specific}\n\n## COMMANDS\n\\`\\`\\`bash\n{dev/test/build}\n\\`\\`\\`\n\n## NOTES\n{Gotchas}\n```\n\n**Quality gates**: 50-150 lines, no generic advice, no obvious info.\n\n### Subdirectory AGENTS.md (Parallel)\n\nLaunch writing tasks for each location:\n\n```\nfor loc in AGENTS_LOCATIONS (except root):\n task(category=\"broadcast\", load_skills=[], run_in_background=false, description=\"Generate AGENTS.md\", prompt=\\`\n Generate AGENTS.md for: ${loc.path}\n - Reason: ${loc.reason}\n - 30-80 lines max\n - NEVER repeat parent content\n - Sections: OVERVIEW (1 line), STRUCTURE (if >5 subdirs), WHERE TO LOOK, CONVENTIONS (if different), ANTI-PATTERNS\n \\`)\n```\n\n**Wait for all. Mark \"generate\" as completed.**\n\n---\n\n## Phase 4: Review & Deduplicate\n\n**Mark \"review\" as in_progress.**\n\nFor each generated file:\n- Remove generic advice\n- Remove parent duplicates\n- Trim to size limits\n- Verify telegraphic style\n\n**Mark \"review\" as completed.**\n\n---\n\n## Final Report\n\n```\n=== init-deep Complete ===\n\nMode: {update | create-new}\n\nFiles:\n [OK] ./AGENTS.md (root, {N} lines)\n [OK] ./src/hooks/AGENTS.md ({N} lines)\n\nDirs Analyzed: {N}\nAGENTS.md Created: {N}\nAGENTS.md Updated: {N}\n\nHierarchy:\n ./AGENTS.md\n \u2514\u2500\u2500 src/hooks/AGENTS.md\n```\n\n---\n\n## Anti-Patterns\n\n- **Static agent count**: MUST vary agents based on project size/depth\n- **Sequential execution**: MUST parallel (explore + LSP concurrent)\n- **Ignoring existing**: ALWAYS read existing first, even with --create-new\n- **Over-documenting**: Not every dir needs AGENTS.md\n- **Redundancy**: Child never repeats parent\n- **Generic content**: Remove anything that applies to ALL projects\n- **Verbose style**: Telegraphic or die";
1
+ export declare const INIT_DEEP_TEMPLATE = "# /init-deep\n\nGenerate hierarchical AGENTS.md files. Root + complexity-scored subdirectories.\n\n## Usage\n\n```\n/init-deep # Update mode: modify existing + create new where warranted\n/init-deep --create-new # Read existing \u2192 remove all \u2192 regenerate from scratch\n/init-deep --max-depth=2 # Limit directory depth (default: 3)\n```\n\n---\n\n## Workflow (High-Level)\n\n1. **Discovery + Analysis** (concurrent)\n - Fire background explore agents immediately\n - Main session: bash structure + LSP codemap + read existing AGENTS.md\n2. **Score & Decide** - Determine AGENTS.md locations from merged findings\n3. **Generate** - Root first, then subdirs in parallel\n4. **Review** - Deduplicate, trim, validate\n\n<critical>\n**task_create ALL phases. Mark in_progress \u2192 completed in real-time.**\n```\ntask_create({ items: [\n { subject: \"discovery\", priority: \"high\", description: \"Fire explore agents + LSP codemap + read existing\" },\n { subject: \"scoring\", priority: \"high\", description: \"Score directories, determine locations\" },\n { subject: \"generate\", priority: \"high\", description: \"Generate AGENTS.md files (root + subdirs)\" },\n { subject: \"review\", priority: \"medium\", description: \"Deduplicate, validate, trim\" }\n]})\n```\n</critical>\n\n---\n\n## Phase 1: Discovery + Analysis (Concurrent)\n\n**Mark \"discovery\" as in_progress.**\n\n### Fire Background Explore Agents IMMEDIATELY\n\nDon't wait\u2014these run async while main session works.\n\n```\n// Fire all at once, collect results later\ntask(subagent_type=\"trinity\", load_skills=[], description=\"Explore project structure\", run_in_background=true, prompt=\"Project structure: PREDICT standard patterns for detected language \u2192 REPORT deviations only\")\ntask(subagent_type=\"trinity\", load_skills=[], description=\"Find entry points\", run_in_background=true, prompt=\"Entry points: FIND main files \u2192 REPORT non-standard organization\")\ntask(subagent_type=\"trinity\", load_skills=[], description=\"Find conventions\", run_in_background=true, prompt=\"Conventions: FIND config files (.eslintrc, pyproject.toml, .editorconfig) \u2192 REPORT project-specific rules\")\ntask(subagent_type=\"trinity\", load_skills=[], description=\"Find anti-patterns\", run_in_background=true, prompt=\"Anti-patterns: FIND 'DO NOT', 'NEVER', 'ALWAYS', 'DEPRECATED' comments \u2192 LIST forbidden patterns\")\ntask(subagent_type=\"trinity\", load_skills=[], description=\"Explore build/CI\", run_in_background=true, prompt=\"Build/CI: FIND .github/workflows, Makefile \u2192 REPORT non-standard patterns\")\ntask(subagent_type=\"trinity\", load_skills=[], description=\"Find test patterns\", run_in_background=true, prompt=\"Test patterns: FIND test configs, test structure \u2192 REPORT unique conventions\")\n```\n\n<dynamic-agents>\n**DYNAMIC AGENT SPAWNING**: After bash analysis, spawn ADDITIONAL explore agents based on project scale:\n\n| Factor | Threshold | Additional Agents |\n|--------|-----------|-------------------|\n| **Total files** | >100 | +1 per 100 files |\n| **Total lines** | >10k | +1 per 10k lines |\n| **Directory depth** | \u22654 | +2 for deep exploration |\n| **Large files (>500 lines)** | >10 files | +1 for complexity hotspots |\n| **Monorepo** | detected | +1 per package/workspace |\n| **Multiple languages** | >1 | +1 per language |\n\n```bash\n# Measure project scale first\ntotal_files=$(find . -type f -not -path '*/node_modules/*' -not -path '*/.git/*' | wc -l)\ntotal_lines=$(find . -type f \\( -name \"*.ts\" -o -name \"*.py\" -o -name \"*.go\" \\) -not -path '*/node_modules/*' -exec wc -l {} + 2>/dev/null | tail -1 | awk '{print $1}')\nlarge_files=$(find . -type f \\( -name \"*.ts\" -o -name \"*.py\" \\) -not -path '*/node_modules/*' -exec wc -l {} + 2>/dev/null | awk '$1 > 500 {count++} END {print count+0}')\nmax_depth=$(find . -type d -not -path '*/node_modules/*' -not -path '*/.git/*' | awk -F/ '{print NF}' | sort -rn | head -1)\n```\n\nExample spawning:\n```\n// 500 files, 50k lines, depth 6, 15 large files \u2192 spawn 5+5+2+1 = 13 additional agents\ntask(subagent_type=\"trinity\", load_skills=[], description=\"Analyze large files\", run_in_background=true, prompt=\"Large file analysis: FIND files >500 lines, REPORT complexity hotspots\")\ntask(subagent_type=\"trinity\", load_skills=[], description=\"Explore deep modules\", run_in_background=true, prompt=\"Deep modules at depth 4+: FIND hidden patterns, internal conventions\")\ntask(subagent_type=\"trinity\", load_skills=[], description=\"Find shared utilities\", run_in_background=true, prompt=\"Cross-cutting concerns: FIND shared utilities across directories\")\n// ... more based on calculation\n```\n</dynamic-agents>\n\n### Main Session: Concurrent Analysis\n\n**While background agents run**, main session does:\n\n#### 1. Bash Structural Analysis\n```bash\n# Directory depth + file counts\nfind . -type d -not -path '*/\\.*' -not -path '*/node_modules/*' -not -path '*/venv/*' -not -path '*/dist/*' -not -path '*/build/*' | awk -F/ '{print NF-1}' | sort -n | uniq -c\n\n# Files per directory (top 30)\nfind . -type f -not -path '*/\\.*' -not -path '*/node_modules/*' | sed 's|/[^/]*$||' | sort | uniq -c | sort -rn | head -30\n\n# Code concentration by extension\nfind . -type f \\( -name \"*.py\" -o -name \"*.ts\" -o -name \"*.tsx\" -o -name \"*.js\" -o -name \"*.go\" -o -name \"*.rs\" \\) -not -path '*/node_modules/*' | sed 's|/[^/]*$||' | sort | uniq -c | sort -rn | head -20\n\n# Existing AGENTS.md / CLAUDE.md\nfind . -type f \\( -name \"AGENTS.md\" -o -name \"CLAUDE.md\" \\) -not -path '*/node_modules/*' 2>/dev/null\n```\n\n#### 2. Read Existing AGENTS.md\n```\nFor each existing file found:\n Read(filePath=file)\n Extract: key insights, conventions, anti-patterns\n Store in EXISTING_AGENTS map\n```\n\nIf `--create-new`: Read all existing first (preserve context) \u2192 then delete all \u2192 regenerate.\n\n#### 3. LSP Codemap (if available)\n```\nLspServers() # Check availability\n\n# Entry points (parallel)\nLspDocumentSymbols(filePath=\"src/index.ts\")\nLspDocumentSymbols(filePath=\"main.py\")\n\n# Key symbols (parallel)\nLspWorkspaceSymbols(filePath=\".\", query=\"class\")\nLspWorkspaceSymbols(filePath=\".\", query=\"interface\")\nLspWorkspaceSymbols(filePath=\".\", query=\"function\")\n\n# Centrality for top exports\nLspFindReferences(filePath=\"...\", line=X, character=Y)\n```\n\n**LSP Fallback**: If unavailable, rely on explore agents + AST-grep.\n\n### Collect Background Results\n\n```\n// After main session analysis done, collect all task results\nfor each task_id: background_output(task_id=\"...\")\n```\n\n**Merge: bash + LSP + existing + explore findings. Mark \"discovery\" as completed.**\n\n---\n\n## Phase 2: Scoring & Location Decision\n\n**Mark \"scoring\" as in_progress.**\n\n### Scoring Matrix\n\n| Factor | Weight | High Threshold | Source |\n|--------|--------|----------------|--------|\n| File count | 3x | >20 | bash |\n| Subdir count | 2x | >5 | bash |\n| Code ratio | 2x | >70% | bash |\n| Unique patterns | 1x | Has own config | explore |\n| Module boundary | 2x | Has index.ts/__init__.py | bash |\n| Symbol density | 2x | >30 symbols | LSP |\n| Export count | 2x | >10 exports | LSP |\n| Reference centrality | 3x | >20 refs | LSP |\n\n### Decision Rules\n\n| Score | Action |\n|-------|--------|\n| **Root (.)** | ALWAYS create |\n| **>15** | Create AGENTS.md |\n| **8-15** | Create if distinct domain |\n| **<8** | Skip (parent covers) |\n\n### Output\n```\nAGENTS_LOCATIONS = [\n { path: \".\", type: \"root\" },\n { path: \"src/hooks\", score: 18, reason: \"high complexity\" },\n { path: \"src/api\", score: 12, reason: \"distinct domain\" }\n]\n```\n\n**Mark \"scoring\" as completed.**\n\n---\n\n## Phase 3: Generate AGENTS.md\n\n**Mark \"generate\" as in_progress.**\n\n<critical>\n**File Writing Rule**: If AGENTS.md already exists at the target path \u2192 use `Edit` tool. If it does NOT exist \u2192 use `Write` tool.\nNEVER use Write to overwrite an existing file. ALWAYS check existence first via `Read` or discovery results.\n</critical>\n\n### Root AGENTS.md (Full Treatment)\n\n```markdown\n# PROJECT KNOWLEDGE BASE\n\n**Generated:** {TIMESTAMP}\n**Commit:** {SHORT_SHA}\n**Branch:** {BRANCH}\n\n## OVERVIEW\n{1-2 sentences: what + core stack}\n\n## STRUCTURE\n\\`\\`\\`\n{root}/\n\u251C\u2500\u2500 {dir}/ # {non-obvious purpose only}\n\u2514\u2500\u2500 {entry}\n\\`\\`\\`\n\n## WHERE TO LOOK\n| Task | Location | Notes |\n|------|----------|-------|\n\n## CODE MAP\n{From LSP - skip if unavailable or project <10 files}\n\n| Symbol | Type | Location | Refs | Role |\n|--------|------|----------|------|------|\n\n## CONVENTIONS\n{ONLY deviations from standard}\n\n## ANTI-PATTERNS (THIS PROJECT)\n{Explicitly forbidden here}\n\n## UNIQUE STYLES\n{Project-specific}\n\n## COMMANDS\n\\`\\`\\`bash\n{dev/test/build}\n\\`\\`\\`\n\n## NOTES\n{Gotchas}\n```\n\n**Quality gates**: 50-150 lines, no generic advice, no obvious info.\n\n### Subdirectory AGENTS.md (Parallel)\n\nLaunch writing tasks for each location:\n\n```\nfor loc in AGENTS_LOCATIONS (except root):\n task(category=\"transmission\", load_skills=[], run_in_background=false, description=\"Generate AGENTS.md\", prompt=\\`\n Generate AGENTS.md for: ${loc.path}\n - Reason: ${loc.reason}\n - 30-80 lines max\n - NEVER repeat parent content\n - Sections: OVERVIEW (1 line), STRUCTURE (if >5 subdirs), WHERE TO LOOK, CONVENTIONS (if different), ANTI-PATTERNS\n \\`)\n```\n\n**Wait for all. Mark \"generate\" as completed.**\n\n---\n\n## Phase 4: Review & Deduplicate\n\n**Mark \"review\" as in_progress.**\n\nFor each generated file:\n- Remove generic advice\n- Remove parent duplicates\n- Trim to size limits\n- Verify telegraphic style\n\n**Mark \"review\" as completed.**\n\n---\n\n## Final Report\n\n```\n=== init-deep Complete ===\n\nMode: {update | create-new}\n\nFiles:\n [OK] ./AGENTS.md (root, {N} lines)\n [OK] ./src/hooks/AGENTS.md ({N} lines)\n\nDirs Analyzed: {N}\nAGENTS.md Created: {N}\nAGENTS.md Updated: {N}\n\nHierarchy:\n ./AGENTS.md\n \u2514\u2500\u2500 src/hooks/AGENTS.md\n```\n\n---\n\n## Anti-Patterns\n\n- **Static agent count**: MUST vary agents based on project size/depth\n- **Sequential execution**: MUST parallel (explore + LSP concurrent)\n- **Ignoring existing**: ALWAYS read existing first, even with --create-new\n- **Over-documenting**: Not every dir needs AGENTS.md\n- **Redundancy**: Child never repeats parent\n- **Generic content**: Remove anything that applies to ALL projects\n- **Verbose style**: Telegraphic or die";
@@ -0,0 +1 @@
1
+ export declare const REDPILL_TEMPLATE = "Toggle redpill mode for the current session.\n\nThis command will:\n1. Enable redpill mode \u2014 injects redpill mode instructions into every message\n2. Disable redpill mode \u2014 prevents redpill mode from activating (even on \"redpill\" keyword)\n3. Show current redpill mode status\n\nUsage:\n /redpill enable \u2014 Force redpill mode on all messages\n /redpill disable \u2014 Block redpill mode (keyword ignored)\n /redpill status \u2014 Show current state\n\nThe change is per-session and clears when the session ends.\nBy default, redpill mode activates when the LLM or user mentions the \"redpill\" keyword.";
@@ -1 +1 @@
1
- export declare const RESEARCH_TEMPLATE = "# /research \u2014 Saturation Research Command\n\nExecute a systematic multi-round research process on the given topic.\n\n## Usage\n\n```\n/research <topic> \u2192 Full research (all directions)\n/research <topic> --scope=code \u2192 Local codebase only\n/research <topic> --scope=docs \u2192 Documentation only\n/research <topic> --scope=web \u2192 Web search only\n/research <topic> --scope=oss \u2192 OSS repos only\n/research <topic> --max-rounds=3 \u2192 Limit to 3 rounds\n```\n\n## What Happens\n\n1. Creates artifact directory: `.matrixx/research-<topic>-<timestamp>/`\n2. Spawns 4 parallel research agents (explore + operator swarms)\n3. Collects findings, identifies new leads\n4. Recursively follows leads until convergence (novelty-based stop, max 5 rounds)\n5. Verifies contested claims by running code\n6. Produces cited synthesis in `final-synthesis.md`\n\n## Output\n\nAll artifacts written to `.matrixx/research-<topic>-<timestamp>/`:\n- `round-N-findings.md` \u2014 per-round findings\n- `leads.md` \u2014 tracked leads\n- `contested-claims.md` \u2014 claims needing verification\n- `final-synthesis.md` \u2014 the final cited synthesis\n\n## Examples\n\n```\n/research how does context window management work in this codebase\n/research React 19 server component patterns --scope=web --max-rounds=3\n/research authentication middleware best practices --scope=all\n```\n\n---\n\nExecute the full research protocol using the ulw-research skill.";
1
+ export declare const RESEARCH_TEMPLATE = "# /research \u2014 Saturation Research Command\n\nExecute a systematic multi-round research process on the given topic.\n\n## Usage\n\n```\n/research <topic> \u2192 Full research (all directions)\n/research <topic> --scope=code \u2192 Local codebase only\n/research <topic> --scope=docs \u2192 Documentation only\n/research <topic> --scope=web \u2192 Web search only\n/research <topic> --scope=oss \u2192 OSS repos only\n/research <topic> --max-rounds=3 \u2192 Limit to 3 rounds\n```\n\n## What Happens\n\n1. Creates artifact directory: `.matrixx/research-<topic>-<timestamp>/`\n2. Spawns 4 parallel research agents (explore + operator swarms)\n3. Collects findings, identifies new leads\n4. Recursively follows leads until convergence (novelty-based stop, max 5 rounds)\n5. Verifies contested claims by running code\n6. Produces cited synthesis in `final-synthesis.md`\n\n## Output\n\nAll artifacts written to `.matrixx/research-<topic>-<timestamp>/`:\n- `round-N-findings.md` \u2014 per-round findings\n- `leads.md` \u2014 tracked leads\n- `contested-claims.md` \u2014 claims needing verification\n- `final-synthesis.md` \u2014 the final cited synthesis\n\n## Examples\n\n```\n/research how does context window management work in this codebase\n/research React 19 server component patterns --scope=web --max-rounds=3\n/research authentication middleware best practices --scope=all\n```\n\n---\n\nExecute the full research protocol using the rp-research skill.";
@@ -1,3 +1,3 @@
1
1
  import type { CommandDefinition } from "../command-loader";
2
- export type BuiltinCommandName = "init-deep" | "matrix-loop" | "cancel-loop" | "ulw-loop" | "refactor" | "start-work" | "stop-continuation" | "handoff" | "pickup" | "remove-deadcode" | "preset" | "end-ultrawork" | "research" | "assembly" | "ultrawork" | "bdd-pipeline" | "evolution" | "cleanup-tasks" | "task-list" | "plan-review" | "quality-audit" | "quality-assurance" | "humanize" | "security-audit";
2
+ export type BuiltinCommandName = "init-deep" | "matrix-loop" | "cancel-loop" | "rp-loop" | "refactor" | "start-work" | "stop-continuation" | "handoff" | "pickup" | "remove-deadcode" | "preset" | "end-redpill" | "research" | "assembly" | "redpill" | "bdd-pipeline" | "evolution" | "cleanup-tasks" | "task-list" | "plan-review" | "quality-audit" | "quality-assurance" | "humanize" | "security-audit";
3
3
  export type BuiltinCommands = Record<string, CommandDefinition>;
@@ -0,0 +1 @@
1
+ export { _resetRedpillStateForTesting, clearRedpillState, disableRedpill, enableRedpill, getRedpillState, } from "./manager";
@@ -0,0 +1,6 @@
1
+ export declare function getRedpillState(sessionID: string): "enabled" | "disabled" | undefined;
2
+ export declare function enableRedpill(sessionID: string): void;
3
+ export declare function disableRedpill(sessionID: string): void;
4
+ export declare function clearRedpillState(sessionID: string): void;
5
+ /** @internal */
6
+ export declare function _resetRedpillStateForTesting(): void;
@@ -32,9 +32,9 @@ export declare const MemoryEntryInputSchema: z.ZodObject<{
32
32
  pinned: z.ZodDefault<z.ZodBoolean>;
33
33
  text: z.ZodString;
34
34
  id: z.ZodString;
35
+ removed: z.ZodDefault<z.ZodBoolean>;
35
36
  sessionId: z.ZodString;
36
37
  messageId: z.ZodString;
37
- removed: z.ZodDefault<z.ZodBoolean>;
38
38
  chars: z.ZodOptional<z.ZodNumber>;
39
39
  tokens: z.ZodOptional<z.ZodNumber>;
40
40
  createdAt: z.ZodOptional<z.ZodNumber>;
@@ -0,0 +1,13 @@
1
+ import { type ReadErrorKind, TypedReadError } from "./read-errors";
2
+ import { type Task } from "./types";
3
+ export declare const STALE_GENERATION_KIND: ReadErrorKind;
4
+ export declare class StaleGenerationError extends TypedReadError {
5
+ expected: number;
6
+ actual: number;
7
+ constructor(path: string, expected: number, actual: number);
8
+ }
9
+ export declare function currentTaskGeneration(task: Partial<Task> | null | undefined): number;
10
+ export declare function assertCurrentGeneration(persistedGeneration: number, expectedGeneration: number, path: string): void;
11
+ export declare function withBumpedGeneration(task: Task): Task;
12
+ export declare function writeTaskFenced(filePath: string, task: Task, expectedGeneration: number): Task;
13
+ export declare function readTaskGeneration(filePath: string): number;
@@ -1,3 +1,4 @@
1
1
  /** task-storage barrel: explicit named re-exports of local modules only. */
2
- export { acquireLock, acquireLockWithRetry, generateTaskId, getProjectTaskDir, getTaskDir, listTaskFiles, migrateLegacyTasksIfNeeded, readJsonSafe, resolveTaskListId, sanitizePathSegment, writeJsonAtomic, } from "./storage";
2
+ export { assertCurrentGeneration, currentTaskGeneration, readTaskGeneration, STALE_GENERATION_KIND, StaleGenerationError, withBumpedGeneration, writeTaskFenced, } from "./generation";
3
+ export { acquireLock, acquireLockWithRetry, generateTaskId, getProjectTaskDir, getTaskDir, type LockHandle, type LockInfo, type LockResult, listTaskFiles, MAX_RETRIES, migrateLegacyTasksIfNeeded, RETRY_DELAY_MS, readJsonSafe, readJsonStrict, readLockFile, refreshLock, releaseLock, resolveTaskListId, StorageCorruptError, sanitizePathSegment, writeJsonAtomic, } from "./storage";
3
4
  export { type Task, TaskSchema, type TaskStatus, TaskStatusSchema, } from "./types";
@@ -0,0 +1,16 @@
1
+ import type { z } from "zod";
2
+ export type ReadErrorKind = "NotFound" | "Corrupt" | "Locked" | "TransientIO" | "StaleGeneration";
3
+ export declare class TypedReadError extends Error {
4
+ kind: ReadErrorKind;
5
+ path: string;
6
+ byteSize: number;
7
+ constructor(kind: ReadErrorKind, path: string, byteSize: number, reason: string);
8
+ }
9
+ export type TypedReadResult<T> = {
10
+ ok: true;
11
+ value: T;
12
+ } | {
13
+ ok: false;
14
+ error: TypedReadError;
15
+ };
16
+ export declare function readJsonTyped<T>(filePath: string, schema: z.ZodType<T>): TypedReadResult<T>;
@@ -1,11 +1,21 @@
1
1
  import type { z } from "zod";
2
2
  import type { MatrixxConfig } from "../../config/schema";
3
+ import { TypedReadError } from "./read-errors";
3
4
  export declare function getProjectTaskDir(directory: string): string;
4
5
  export declare function getTaskDir(config?: Partial<MatrixxConfig>, directory?: string): string;
5
6
  export declare function sanitizePathSegment(value: string): string;
6
7
  export declare function resolveTaskListId(config?: Partial<MatrixxConfig>): string;
8
+ export declare class StorageCorruptError extends Error {
9
+ path: string;
10
+ byteSize: number;
11
+ reason: string;
12
+ constructor(path: string, byteSize: number, reason: string);
13
+ }
7
14
  export declare function readJsonSafe<T>(filePath: string, schema: z.ZodType<T>): T | null;
15
+ export declare function readJsonStrict<T>(filePath: string, schema: z.ZodType<T>): T;
8
16
  export declare function writeJsonAtomic(filePath: string, data: unknown): void;
17
+ export declare const MAX_RETRIES = 4;
18
+ export declare const RETRY_DELAY_MS = 15;
9
19
  export declare function acquireLockWithRetry(dirPath: string, retries?: number): Promise<{
10
20
  acquired: boolean;
11
21
  release: () => void;
@@ -17,7 +27,25 @@ export declare function migrateLegacyTasksIfNeeded(config: Partial<MatrixxConfig
17
27
  legacyDir: string;
18
28
  projectDir: string;
19
29
  };
20
- export declare function acquireLock(dirPath: string): {
30
+ export interface LockInfo {
31
+ id: string;
32
+ ownerId: string;
33
+ pid: number;
34
+ generation: number;
35
+ timestamp: number;
36
+ }
37
+ export interface LockHandle {
21
38
  acquired: boolean;
39
+ ownerId?: string;
22
40
  release: () => void;
41
+ }
42
+ export type LockResult = {
43
+ ok: true;
44
+ } | {
45
+ ok: false;
46
+ error: TypedReadError;
23
47
  };
48
+ export declare function readLockFile(dirPath: string): LockInfo | null;
49
+ export declare function releaseLock(dirPath: string, ownerId: string): LockResult;
50
+ export declare function refreshLock(dirPath: string, ownerId: string): LockResult;
51
+ export declare function acquireLock(dirPath: string): LockHandle;
@@ -25,5 +25,6 @@ export declare const TaskSchema: z.ZodObject<{
25
25
  parentID: z.ZodOptional<z.ZodString>;
26
26
  threadID: z.ZodOptional<z.ZodString>;
27
27
  projectRoot: z.ZodOptional<z.ZodString>;
28
+ generation: z.ZodDefault<z.ZodNumber>;
28
29
  }, z.core.$strict>;
29
30
  export type Task = z.infer<typeof TaskSchema>;
@@ -1,4 +1,4 @@
1
- import type { AvailableSkill } from "../../agents/dynamic-agent-prompt-builder";
1
+ import type { AvailableSkill } from "../../agents/shared/dynamic-agent-prompt-builder";
2
2
  export declare function buildReminderMessage(availableSkills: AvailableSkill[]): string;
3
3
  export interface NudgeMessageEvent {
4
4
  skill: string;
@@ -1,4 +1,4 @@
1
- import type { AvailableSkill } from "../../agents/dynamic-agent-prompt-builder";
1
+ import type { AvailableSkill } from "../../agents/shared/dynamic-agent-prompt-builder";
2
2
  import type { MatrixxContext } from "../../plugin/tool/context";
3
3
  export type { NudgeEvent, NudgeInput } from "./detector";
4
4
  export { detectNudge } from "./detector";
@@ -1,8 +1,8 @@
1
1
  export { CODE_BLOCK_PATTERN, INLINE_CODE_PATTERN } from "../../shared/policy/code-patterns";
2
2
  export { ANALYZE_MESSAGE, ANALYZE_PATTERN } from "./analyze/default";
3
3
  export { DOCS_MESSAGE, DOCS_PATTERN } from "./docs/default";
4
+ export { getRedpillMessage, isPlannerAgent } from "./redpill";
4
5
  export { SEARCH_MESSAGE, SEARCH_PATTERN } from "./search/default";
5
- export { getUltraworkMessage, isPlannerAgent } from "./ultrawork";
6
6
  type KeywordDetector = {
7
7
  pattern: RegExp;
8
8
  message: string | ((agentName?: string, modelID?: string) => string);
@@ -1,5 +1,5 @@
1
1
  interface DetectedKeyword {
2
- type: "ultrawork" | "search" | "analyze" | "docs";
2
+ type: "redpill" | "search" | "analyze" | "docs";
3
3
  message: string;
4
4
  }
5
5
  export declare function removeCodeBlocks(text: string): string;