@exla/rudder 0.0.0-stage → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (181) hide show
  1. package/LICENSE +100 -0
  2. package/README.md +733 -2
  3. package/assets/rudder.icns +0 -0
  4. package/assets/sounds/NOTICE.md +8 -0
  5. package/assets/sounds/ping.mp3 +0 -0
  6. package/dist/agent-attention.d.ts +5 -0
  7. package/dist/agent-attention.js +54 -0
  8. package/dist/agent-attention.js.map +1 -0
  9. package/dist/analytics.d.ts +36 -0
  10. package/dist/analytics.js +178 -0
  11. package/dist/analytics.js.map +1 -0
  12. package/dist/attach-session.d.ts +91 -0
  13. package/dist/attach-session.js +290 -0
  14. package/dist/attach-session.js.map +1 -0
  15. package/dist/auth.d.ts +36 -0
  16. package/dist/auth.js +392 -0
  17. package/dist/auth.js.map +1 -0
  18. package/dist/backends.d.ts +3 -0
  19. package/dist/backends.js +638 -0
  20. package/dist/backends.js.map +1 -0
  21. package/dist/board/board.css +1 -0
  22. package/dist/board/board.js +2 -0
  23. package/dist/board/daemon.d.ts +39 -0
  24. package/dist/board/daemon.js +1510 -0
  25. package/dist/board/daemon.js.map +1 -0
  26. package/dist/brain.d.ts +24 -0
  27. package/dist/brain.js +244 -0
  28. package/dist/brain.js.map +1 -0
  29. package/dist/bus.d.ts +9 -0
  30. package/dist/bus.js +23 -0
  31. package/dist/bus.js.map +1 -0
  32. package/dist/checkout-sync.d.ts +35 -0
  33. package/dist/checkout-sync.js +247 -0
  34. package/dist/checkout-sync.js.map +1 -0
  35. package/dist/cloud.d.ts +48 -0
  36. package/dist/cloud.js +4596 -0
  37. package/dist/cloud.js.map +1 -0
  38. package/dist/codex-binary.d.ts +12 -0
  39. package/dist/codex-binary.js +184 -0
  40. package/dist/codex-binary.js.map +1 -0
  41. package/dist/context-audit.d.ts +21 -0
  42. package/dist/context-audit.js +109 -0
  43. package/dist/context-audit.js.map +1 -0
  44. package/dist/daemon.d.ts +27 -0
  45. package/dist/daemon.js +203 -0
  46. package/dist/daemon.js.map +1 -0
  47. package/dist/effort.d.ts +9 -0
  48. package/dist/effort.js +72 -0
  49. package/dist/effort.js.map +1 -0
  50. package/dist/feedback.d.ts +46 -0
  51. package/dist/feedback.js +173 -0
  52. package/dist/feedback.js.map +1 -0
  53. package/dist/gc.d.ts +3 -0
  54. package/dist/gc.js +262 -0
  55. package/dist/gc.js.map +1 -0
  56. package/dist/git.d.ts +31 -0
  57. package/dist/git.js +455 -0
  58. package/dist/git.js.map +1 -0
  59. package/dist/goal.d.ts +33 -0
  60. package/dist/goal.js +95 -0
  61. package/dist/goal.js.map +1 -0
  62. package/dist/graph.d.ts +93 -0
  63. package/dist/graph.js +372 -0
  64. package/dist/graph.js.map +1 -0
  65. package/dist/handoff.d.ts +110 -0
  66. package/dist/handoff.js +565 -0
  67. package/dist/handoff.js.map +1 -0
  68. package/dist/improve/advisor.d.ts +10 -0
  69. package/dist/improve/advisor.js +115 -0
  70. package/dist/improve/advisor.js.map +1 -0
  71. package/dist/improve/collect.d.ts +49 -0
  72. package/dist/improve/collect.js +274 -0
  73. package/dist/improve/collect.js.map +1 -0
  74. package/dist/improve/gate.d.ts +17 -0
  75. package/dist/improve/gate.js +60 -0
  76. package/dist/improve/gate.js.map +1 -0
  77. package/dist/improve/index.d.ts +9 -0
  78. package/dist/improve/index.js +376 -0
  79. package/dist/improve/index.js.map +1 -0
  80. package/dist/improve/judge.d.ts +32 -0
  81. package/dist/improve/judge.js +114 -0
  82. package/dist/improve/judge.js.map +1 -0
  83. package/dist/improve/mine.d.ts +31 -0
  84. package/dist/improve/mine.js +192 -0
  85. package/dist/improve/mine.js.map +1 -0
  86. package/dist/improve/propose.d.ts +51 -0
  87. package/dist/improve/propose.js +150 -0
  88. package/dist/improve/propose.js.map +1 -0
  89. package/dist/improve/rank.d.ts +16 -0
  90. package/dist/improve/rank.js +49 -0
  91. package/dist/improve/rank.js.map +1 -0
  92. package/dist/improve/schedule.d.ts +1 -0
  93. package/dist/improve/schedule.js +95 -0
  94. package/dist/improve/schedule.js.map +1 -0
  95. package/dist/improve/ship.d.ts +25 -0
  96. package/dist/improve/ship.js +82 -0
  97. package/dist/improve/ship.js.map +1 -0
  98. package/dist/improve/state.d.ts +157 -0
  99. package/dist/improve/state.js +264 -0
  100. package/dist/improve/state.js.map +1 -0
  101. package/dist/index.d.ts +2 -0
  102. package/dist/index.js +88 -0
  103. package/dist/index.js.map +1 -0
  104. package/dist/jj-binary.d.ts +36 -0
  105. package/dist/jj-binary.js +143 -0
  106. package/dist/jj-binary.js.map +1 -0
  107. package/dist/jj.d.ts +163 -0
  108. package/dist/jj.js +926 -0
  109. package/dist/jj.js.map +1 -0
  110. package/dist/logger.d.ts +22 -0
  111. package/dist/logger.js +110 -0
  112. package/dist/logger.js.map +1 -0
  113. package/dist/main.d.ts +3 -0
  114. package/dist/main.js +1366 -0
  115. package/dist/main.js.map +1 -0
  116. package/dist/migration.d.ts +82 -0
  117. package/dist/migration.js +198 -0
  118. package/dist/migration.js.map +1 -0
  119. package/dist/models.d.ts +9 -0
  120. package/dist/models.js +623 -0
  121. package/dist/models.js.map +1 -0
  122. package/dist/move-home.d.ts +82 -0
  123. package/dist/move-home.js +472 -0
  124. package/dist/move-home.js.map +1 -0
  125. package/dist/native/darwin-arm64/rudder-native +0 -0
  126. package/dist/native/darwin-x64/rudder-native +0 -0
  127. package/dist/native/linux-x64/rudder-native +0 -0
  128. package/dist/native-agents.d.ts +8 -0
  129. package/dist/native-agents.js +178 -0
  130. package/dist/native-agents.js.map +1 -0
  131. package/dist/native-binary.d.ts +4 -0
  132. package/dist/native-binary.js +140 -0
  133. package/dist/native-binary.js.map +1 -0
  134. package/dist/paste-bridge.d.ts +36 -0
  135. package/dist/paste-bridge.js +279 -0
  136. package/dist/paste-bridge.js.map +1 -0
  137. package/dist/plan-mode.d.ts +2 -0
  138. package/dist/plan-mode.js +22 -0
  139. package/dist/plan-mode.js.map +1 -0
  140. package/dist/planner.d.ts +27 -0
  141. package/dist/planner.js +587 -0
  142. package/dist/planner.js.map +1 -0
  143. package/dist/predict.d.ts +67 -0
  144. package/dist/predict.js +369 -0
  145. package/dist/predict.js.map +1 -0
  146. package/dist/report.d.ts +74 -0
  147. package/dist/report.js +412 -0
  148. package/dist/report.js.map +1 -0
  149. package/dist/rudder-md.d.ts +33 -0
  150. package/dist/rudder-md.js +142 -0
  151. package/dist/rudder-md.js.map +1 -0
  152. package/dist/run-manager.d.ts +62 -0
  153. package/dist/run-manager.js +1400 -0
  154. package/dist/run-manager.js.map +1 -0
  155. package/dist/scheduler.d.ts +128 -0
  156. package/dist/scheduler.js +955 -0
  157. package/dist/scheduler.js.map +1 -0
  158. package/dist/state.d.ts +127 -0
  159. package/dist/state.js +704 -0
  160. package/dist/state.js.map +1 -0
  161. package/dist/surfaces.d.ts +91 -0
  162. package/dist/surfaces.js +460 -0
  163. package/dist/surfaces.js.map +1 -0
  164. package/dist/task-summary.d.ts +30 -0
  165. package/dist/task-summary.js +472 -0
  166. package/dist/task-summary.js.map +1 -0
  167. package/dist/types.d.ts +492 -0
  168. package/dist/types.js +2 -0
  169. package/dist/types.js.map +1 -0
  170. package/dist/usage.d.ts +198 -0
  171. package/dist/usage.js +830 -0
  172. package/dist/usage.js.map +1 -0
  173. package/dist/util.d.ts +73 -0
  174. package/dist/util.js +399 -0
  175. package/dist/util.js.map +1 -0
  176. package/dist/version-check.d.ts +16 -0
  177. package/dist/version-check.js +269 -0
  178. package/dist/version-check.js.map +1 -0
  179. package/package.json +68 -4
  180. package/scripts/copy-native.mjs +89 -0
  181. package/scripts/postinstall.mjs +34 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paste-bridge.js","sourceRoot":"","sources":["../src/paste-bridge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const PLAN_MODE_CONTRACT: string;
2
+ export declare function buildPlanPrompt(task: string): string;
@@ -0,0 +1,22 @@
1
+ export const PLAN_MODE_CONTRACT = [
2
+ "[RUDDER PLAN MODE]",
3
+ "You are running inside Rudder's own plan mode, not the backend's native implementation mode.",
4
+ "Your job is to investigate and produce a decision-complete implementation plan.",
5
+ "",
6
+ "Rules:",
7
+ "- Do not write, edit, create, delete, move, rename, install, commit, merge, deploy, migrate, or otherwise mutate local or remote state.",
8
+ "- Use only read-only inspection. It is OK to read files, search the repo, inspect git state or read-only CLI state when the active tool profile permits it, and use web search/fetch when it improves the plan.",
9
+ "- If secrets or environment state matter, inspect only what is needed and do not print secret values. Mention presence, absence, names, or configuration shape instead.",
10
+ "- Ask concise follow-up questions when important product or implementation choices cannot be discovered from the environment.",
11
+ "- When the plan is ready, put the final answer in a single <proposed_plan>...</proposed_plan> block.",
12
+ "[END RUDDER PLAN MODE]",
13
+ ].join("\n");
14
+ export function buildPlanPrompt(task) {
15
+ return [
16
+ "Plan this task before implementation:",
17
+ task,
18
+ "",
19
+ "First inspect the repository and relevant external/read-only context. Ask follow-up questions if the plan cannot be made decision-complete from inspection alone.",
20
+ ].join("\n");
21
+ }
22
+ //# sourceMappingURL=plan-mode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-mode.js","sourceRoot":"","sources":["../src/plan-mode.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,oBAAoB;IACpB,8FAA8F;IAC9F,iFAAiF;IACjF,EAAE;IACF,QAAQ;IACR,yIAAyI;IACzI,iNAAiN;IACjN,yKAAyK;IACzK,+HAA+H;IAC/H,sGAAsG;IACtG,wBAAwB;CACzB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,OAAO;QACL,uCAAuC;QACvC,IAAI;QACJ,EAAE;QACF,mKAAmK;KACpK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
@@ -0,0 +1,27 @@
1
+ import type { BackendId, EffortLevel, PlanDag, PlanNode, ReconcileResult } from "./types.js";
2
+ export { loadInstructionFiles } from "./brain.js";
3
+ export declare const PLANNER_MODEL = "claude-sonnet-5";
4
+ export declare function parsePlanBlock(output: string): PlanDag;
5
+ export declare function gateDecision(dag: PlanDag): {
6
+ autoRun: boolean;
7
+ reason: string;
8
+ };
9
+ export type PlanContext = {
10
+ root: string;
11
+ branch: string;
12
+ };
13
+ export declare function planTask(task: string, ctx: PlanContext): Promise<PlanDag>;
14
+ /**
15
+ * Infer the new node's deps against the current frontier. On any LLM failure
16
+ * (timeout / no model / unparsable), fall back to a SOFT edge to every frontier
17
+ * node: this over-delivers context and never deadlocks. Never a default hard
18
+ * edge.
19
+ */
20
+ export declare function reconcile(task: string, frontierNodes: PlanNode[], ctx: PlanContext): Promise<ReconcileResult>;
21
+ export type FanoutOptions = {
22
+ backend?: BackendId;
23
+ model?: string;
24
+ effort?: EffortLevel;
25
+ };
26
+ export declare function buildFanoutDag(task: string, n: number, opts?: FanoutOptions): PlanDag;
27
+ export declare function scaffoldPlan(repoRoot: string, dag: PlanDag): Promise<void>;
@@ -0,0 +1,587 @@
1
+ import { callTextModel } from "./task-summary.js";
2
+ import { loadInstructionFiles, suggestTests } from "./brain.js";
3
+ import { createEmptyChange, currentJjChangeId } from "./jj.js";
4
+ import { newEdgeId, newNodeId, updateGraph } from "./graph.js";
5
+ import { nowIso } from "./util.js";
6
+ import { DEFAULT_SUCCESS, deriveGoal, formatGoalPrompt, normalizeGoalLine } from "./goal.js";
7
+ import { ensureProjectRuntimeIgnored } from "./state.js";
8
+ export { loadInstructionFiles } from "./brain.js";
9
+ // A sonnet-class model: planning/decomposition is too hard for haiku, which is
10
+ // the task-summary model. Keep this a single constant so it is easy to bump.
11
+ export const PLANNER_MODEL = "claude-sonnet-5";
12
+ const PLAN_START = "RUDDER_PLAN_TASKS_START";
13
+ const PLAN_END = "RUDDER_PLAN_TASKS_END";
14
+ // The dependency rules quoted into the system prompts. The same wording is the
15
+ // contract the native tasks.rs parser enforces, so the model and both parsers
16
+ // agree on what hard vs soft means.
17
+ // The launch-goal convention quoted into the system prompts. Every spawnable task
18
+ // MUST carry a one-line objective (goal) and a verifiable stopping condition
19
+ // (success). Rudder launches workers with a leading `Objective:` line plus a `Done when:`
20
+ // line, so the worker always knows what done means without invoking a slash command.
21
+ const GOAL_RULES = [
22
+ "Goal rules (REQUIRED for every task):",
23
+ "- `goal`: one line naming the single objective the worker should accomplish.",
24
+ "- `success`: the verifiable DONE-WHEN condition (the commands, artifacts, or criteria that mean it is complete).",
25
+ "- Always include both. Never omit them and never leave them empty.",
26
+ ].join("\n");
27
+ // Each worker runs in its OWN isolated jj workspace at a different path than the
28
+ // repository root you inspect. If a task prompt embeds an absolute path (e.g.
29
+ // "in the repository at /Users/.../repo, edit foo.py"), the worker will write to
30
+ // THAT path instead of its own workspace, the workspace stays empty, and the run
31
+ // fails verification with no changes. So prompts MUST be path-agnostic.
32
+ const WORKER_PATH_RULES = [
33
+ "Worker workspace rules (REQUIRED):",
34
+ "- Each task is run by a separate worker in its OWN isolated workspace checkout, at a different filesystem path than the repository root you are inspecting.",
35
+ "- In every `prompt`, `goal`, and `success`, refer to files by REPOSITORY-RELATIVE paths only (e.g. `mathutils.py`, `src/db/schema.ts`). The worker is already cd'd into its workspace; relative paths resolve correctly there.",
36
+ "- NEVER write an absolute filesystem path, the repository's location, or phrases like \"in the repository at <path>\" / \"cd into <path>\". An absolute path sends the worker to the wrong directory and the task fails.",
37
+ ].join("\n");
38
+ const DEP_RULES = [
39
+ "Dependency rules:",
40
+ "- A task with no id and no deps is a 0-dep root.",
41
+ "- hard = ordering: the child's success condition CANNOT be met until the parent has merged. Every hard edge MUST carry a non-empty `why` justifying the ordering; an unjustified hard edge is downgraded to soft.",
42
+ "- A task that CONSUMES another task's produced code is HARD on it. Concretely: tests that import or exercise code another task writes; code that imports a module/function/type another task creates; integration or wiring that calls an API another task defines. The child can technically start, but it cannot SUCCEED (imports resolve, tests pass) until that code exists — so it must wait for the merge. Reading the parent's diff as soft context is NOT enough when the child must execute the parent's code.",
43
+ "- soft = context-sharing (the default): the child runs in parallel and is fed the parent's diff once the parent merges. Use it when the child can succeed on its own and the parent's work is merely informative (parallel features, doc updates, sibling modules that do not import each other).",
44
+ "- Prefer the MINIMAL hard-edge set. Default to soft for independent work, but do NOT under-classify: if the child executes or imports the parent's code, it is hard.",
45
+ // Mirrors PARALLEL_PLAN_RULE in native/src/tasks.rs.
46
+ "- Favor independent nodes joined by soft edges so workers run in parallel; add a hard edge only for a real code dependency, never as a default chain.",
47
+ "- No cycles.",
48
+ ].join("\n");
49
+ export function parsePlanBlock(output) {
50
+ const json = extractPlanJson(output);
51
+ let value;
52
+ try {
53
+ value = JSON.parse(json);
54
+ }
55
+ catch {
56
+ throw new Error("RUDDER_PLAN_TASKS block was not valid JSON.");
57
+ }
58
+ const tasks = value?.tasks;
59
+ if (!Array.isArray(tasks)) {
60
+ throw new Error("RUDDER_PLAN_TASKS block must contain a tasks array.");
61
+ }
62
+ // First pass: build nodes, synthesizing ids n0.. for tasks without one.
63
+ const nodes = [];
64
+ const rawDepsById = new Map();
65
+ const seenIds = new Set();
66
+ tasks.slice(0, 100).forEach((entry, index) => {
67
+ const raw = (entry ?? {});
68
+ const prompt = typeof raw.prompt === "string" ? raw.prompt.trim() : "";
69
+ if (!prompt) {
70
+ return;
71
+ }
72
+ let id = typeof raw.id === "string" && raw.id.trim() ? raw.id.trim() : `n${index}`;
73
+ // Uniquify colliding ids (mirrors the native parser): two tasks sharing an id
74
+ // would otherwise collapse into one graph node + jj change, silently dropping a
75
+ // task. rawDepsById is keyed by id, so a collision must be resolved before use.
76
+ if (seenIds.has(id)) {
77
+ let suffix = 2;
78
+ while (seenIds.has(`${id}-${suffix}`)) {
79
+ suffix += 1;
80
+ }
81
+ id = `${id}-${suffix}`;
82
+ }
83
+ seenIds.add(id);
84
+ const title = typeof raw.title === "string" && raw.title.trim() ? raw.title.trim() : "worker task";
85
+ // goal + success are part of the launch-goal convention: REQUIRED in the system
86
+ // prompt, but we stay backward-compatible by deriving sane defaults when the
87
+ // model omits them (goal = title/first line of the prompt; success = the
88
+ // canonical stopping condition).
89
+ const goal = normalizeGoalLine(typeof raw.goal === "string" && raw.goal.trim() ? raw.goal : deriveGoal(title || prompt), title || prompt);
90
+ const success = normalizeGoalLine(typeof raw.success === "string" && raw.success.trim() ? raw.success : DEFAULT_SUCCESS, DEFAULT_SUCCESS);
91
+ const node = {
92
+ id,
93
+ title,
94
+ prompt,
95
+ goal,
96
+ success,
97
+ deps: [],
98
+ ...(isBackend(raw.backend) ? { backend: raw.backend } : {}),
99
+ ...(typeof raw.model === "string" && raw.model.trim() ? { model: raw.model.trim() } : {}),
100
+ ...(isEffort(raw.effort) ? { effort: raw.effort } : {}),
101
+ ...(parseFileScope(raw.fileScope) ? { fileScope: parseFileScope(raw.fileScope) } : {}),
102
+ };
103
+ nodes.push(node);
104
+ rawDepsById.set(id, parseRawDeps(raw.deps));
105
+ });
106
+ const knownIds = new Set(nodes.map((node) => node.id));
107
+ // Second pass: resolve deps. Drop edges to unknown ids; downgrade hard edges
108
+ // with an empty `why` to soft (forces justification).
109
+ const edges = [];
110
+ for (const node of nodes) {
111
+ const resolved = [];
112
+ for (const dep of rawDepsById.get(node.id) ?? []) {
113
+ if (!knownIds.has(dep.on) || dep.on === node.id) {
114
+ continue; // dangling or self edge
115
+ }
116
+ const why = dep.why?.trim();
117
+ const type = dep.type === "hard" && why ? "hard" : "soft";
118
+ resolved.push({ on: dep.on, type, ...(why ? { why } : {}) });
119
+ edges.push({ from: dep.on, to: node.id, type, ...(why ? { why } : {}) });
120
+ }
121
+ node.deps = resolved;
122
+ }
123
+ if (hasCycle(nodes, edges)) {
124
+ throw new Error("RUDDER_PLAN_TASKS dependency graph has a cycle.");
125
+ }
126
+ return { nodes, edges };
127
+ }
128
+ function extractPlanJson(output) {
129
+ const clean = output.replace(/\r/g, "");
130
+ const start = clean.lastIndexOf(PLAN_START);
131
+ if (start < 0) {
132
+ throw new Error(`missing ${PLAN_START}`);
133
+ }
134
+ const afterStart = clean.slice(start + PLAN_START.length);
135
+ const end = afterStart.indexOf(PLAN_END);
136
+ if (end < 0) {
137
+ throw new Error(`missing ${PLAN_END}`);
138
+ }
139
+ let json = afterStart.slice(0, end).trim();
140
+ if (json.startsWith("```json")) {
141
+ json = json.slice("```json".length).trim();
142
+ }
143
+ else if (json.startsWith("```")) {
144
+ json = json.slice("```".length).trim();
145
+ }
146
+ if (json.endsWith("```")) {
147
+ json = json.slice(0, -3).trim();
148
+ }
149
+ return json;
150
+ }
151
+ function parseRawDeps(value) {
152
+ if (!Array.isArray(value)) {
153
+ return [];
154
+ }
155
+ const deps = [];
156
+ for (const entry of value) {
157
+ if (typeof entry === "string" && entry.trim()) {
158
+ // Bare id string -> soft edge by default.
159
+ deps.push({ on: entry.trim(), type: "soft" });
160
+ continue;
161
+ }
162
+ if (entry && typeof entry === "object") {
163
+ const dep = entry;
164
+ // Models phrase the parent id as either "on" or "from"; accept both.
165
+ const on = typeof dep.on === "string" && dep.on.trim()
166
+ ? dep.on.trim()
167
+ : typeof dep.from === "string"
168
+ ? dep.from.trim()
169
+ : "";
170
+ if (!on) {
171
+ continue;
172
+ }
173
+ const type = dep.type === "hard" ? "hard" : "soft";
174
+ const why = typeof dep.why === "string" ? dep.why.trim() : "";
175
+ deps.push({ on, type, ...(why ? { why } : {}) });
176
+ }
177
+ }
178
+ return deps;
179
+ }
180
+ function parseFileScope(value) {
181
+ if (!Array.isArray(value)) {
182
+ return undefined;
183
+ }
184
+ const scope = value.filter((entry) => typeof entry === "string" && entry.trim().length > 0);
185
+ return scope.length ? scope : undefined;
186
+ }
187
+ function isBackend(value) {
188
+ return value === "claude" || value === "codex" || value === "acpx" || value === "opencode";
189
+ }
190
+ function isEffort(value) {
191
+ return value === "low" || value === "medium" || value === "high" || value === "xhigh" || value === "max";
192
+ }
193
+ /**
194
+ * Kahn topo-sort over hard edges only. Soft edges share context in parallel and
195
+ * never deadlock, so a soft cycle is harmless; only hard cycles are rejected.
196
+ */
197
+ function hasCycle(nodes, edges) {
198
+ const ids = nodes.map((node) => node.id);
199
+ const indegree = new Map(ids.map((id) => [id, 0]));
200
+ const adjacency = new Map(ids.map((id) => [id, []]));
201
+ for (const edge of edges) {
202
+ if (edge.type !== "hard") {
203
+ continue;
204
+ }
205
+ if (!indegree.has(edge.to) || !adjacency.has(edge.from)) {
206
+ continue;
207
+ }
208
+ indegree.set(edge.to, (indegree.get(edge.to) ?? 0) + 1);
209
+ adjacency.get(edge.from)?.push(edge.to);
210
+ }
211
+ const queue = ids.filter((id) => (indegree.get(id) ?? 0) === 0);
212
+ let visited = 0;
213
+ while (queue.length) {
214
+ const id = queue.shift();
215
+ visited += 1;
216
+ for (const next of adjacency.get(id) ?? []) {
217
+ const degree = (indegree.get(next) ?? 0) - 1;
218
+ indegree.set(next, degree);
219
+ if (degree === 0) {
220
+ queue.push(next);
221
+ }
222
+ }
223
+ }
224
+ return visited !== ids.length;
225
+ }
226
+ // ---------------------------------------------------------------------------
227
+ // Adaptive gating. Trivial tasks bypass the gate entirely (today's fast path);
228
+ // anything richer gates for human approval before scaffolding.
229
+ // ---------------------------------------------------------------------------
230
+ const MULTI_STEP_MARKER = /\b(\d\.|first|then|after that|finally)\b/i;
231
+ export function gateDecision(dag) {
232
+ if (dag.nodes.length !== 1) {
233
+ return { autoRun: false, reason: `plan has ${dag.nodes.length} nodes` };
234
+ }
235
+ if (dag.edges.length > 0) {
236
+ return { autoRun: false, reason: "plan has dependencies" };
237
+ }
238
+ const node = dag.nodes[0];
239
+ if (!node) {
240
+ return { autoRun: false, reason: "plan has no nodes" };
241
+ }
242
+ const estTokens = Math.ceil(node.prompt.length / 4);
243
+ if (estTokens >= 1500) {
244
+ return { autoRun: false, reason: `prompt is large (~${estTokens} tokens)` };
245
+ }
246
+ if ((node.fileScope?.length ?? 0) > 3) {
247
+ return { autoRun: false, reason: `file scope spans ${node.fileScope?.length} paths` };
248
+ }
249
+ if (MULTI_STEP_MARKER.test(node.prompt)) {
250
+ return { autoRun: false, reason: "prompt has multi-step markers" };
251
+ }
252
+ return { autoRun: true, reason: "single trivial task" };
253
+ }
254
+ function planSystemPrompt() {
255
+ return [
256
+ "You are Rudder's planning coordinator. Decompose a coding request into the smallest set of",
257
+ "independent implementation tasks that separate worker agents can run in isolated jj workspaces.",
258
+ "",
259
+ DEP_RULES,
260
+ "",
261
+ GOAL_RULES,
262
+ "",
263
+ WORKER_PATH_RULES,
264
+ "",
265
+ "Output rules:",
266
+ "- You run NON-INTERACTIVELY: never ask clarifying questions and never refuse. If the request is ambiguous, pick the most reasonable interpretation, state assumptions, and ALWAYS emit a complete plan.",
267
+ "- Print exactly one block and no other JSON block:",
268
+ `${PLAN_START}`,
269
+ '{"tasks":[{"id":"n0","title":"short title","prompt":"full implementation prompt for one worker","goal":"one-line objective","success":"verifiable done-when condition","deps":[{"on":"n0","type":"hard","why":"why ordering is required"}],"backend":"claude","model":"...","effort":"medium","fileScope":["src/..."]}]}',
270
+ `${PLAN_END}`,
271
+ "- Use 1-4 tasks; more only when the split is clearly independent.",
272
+ "- Keep the hard-edge set minimal and justify every hard edge in its `why`.",
273
+ "- After the block, add a short human summary of why this split is safe.",
274
+ ].join("\n");
275
+ }
276
+ export async function planTask(task, ctx) {
277
+ const instructions = await loadInstructionFiles(ctx.root).catch(() => []);
278
+ const instructionText = instructions.length
279
+ ? `\n\nRepository instructions:\n${instructions.map((file) => `### ${file.path}\n${file.content}`).join("\n\n")}`
280
+ : "";
281
+ // Ground `success` in this repo's REAL check commands; without them the model
282
+ // invents unverifiable prose bars ("its own verification passes").
283
+ const checks = await suggestTests(ctx.root).catch(() => []);
284
+ const checksText = checks.length
285
+ ? `\nVerification commands available in this repository (base each task's \`success\` on the relevant ones): ${checks.join(", ")}`
286
+ : "";
287
+ const user = [
288
+ `Repository root (for your read-only inspection ONLY — do NOT put this path in any task prompt; workers run elsewhere): ${ctx.root}`,
289
+ `Branch: ${ctx.branch}`,
290
+ checksText,
291
+ "",
292
+ `User request:\n${task}`,
293
+ instructionText,
294
+ ].join("\n");
295
+ const output = await callTextModel({
296
+ model: PLANNER_MODEL,
297
+ system: planSystemPrompt(),
298
+ user,
299
+ maxTokens: 4096,
300
+ });
301
+ return parsePlanBlock(output);
302
+ }
303
+ function reconcileSystemPrompt() {
304
+ return [
305
+ "You are Rudder's injection coordinator. A new task is being added to a project that already has",
306
+ "in-flight work (the frontier). Decide how the new task depends on each frontier node.",
307
+ "",
308
+ DEP_RULES,
309
+ "",
310
+ GOAL_RULES,
311
+ "",
312
+ WORKER_PATH_RULES,
313
+ "",
314
+ "Output rules:",
315
+ "- Print exactly one block and no other JSON block. The block holds a single task whose `deps`",
316
+ " reference the frontier node ids you were given:",
317
+ `${PLAN_START}`,
318
+ '{"tasks":[{"id":"new","title":"short title","prompt":"full implementation prompt","goal":"one-line objective","success":"verifiable done-when condition","deps":[{"on":"<frontier id>","type":"soft","why":"..."}]}]}',
319
+ `${PLAN_END}`,
320
+ "- Default every edge to soft. Only make an edge hard when the new task literally cannot start",
321
+ " until that frontier node merges, and justify it in `why`.",
322
+ ].join("\n");
323
+ }
324
+ /**
325
+ * Infer the new node's deps against the current frontier. On any LLM failure
326
+ * (timeout / no model / unparsable), fall back to a SOFT edge to every frontier
327
+ * node: this over-delivers context and never deadlocks. Never a default hard
328
+ * edge.
329
+ */
330
+ export async function reconcile(task, frontierNodes, ctx) {
331
+ const fallback = () => {
332
+ const node = {
333
+ id: "new",
334
+ title: task.slice(0, 72),
335
+ prompt: task,
336
+ goal: deriveGoal(task),
337
+ success: DEFAULT_SUCCESS,
338
+ deps: frontierNodes.map((frontierNode) => ({ on: frontierNode.id, type: "soft" })),
339
+ };
340
+ return {
341
+ node,
342
+ inferredDeps: frontierNodes.map((frontierNode) => ({ node: frontierNode.id, type: "soft" })),
343
+ };
344
+ };
345
+ if (frontierNodes.length === 0) {
346
+ return {
347
+ node: { id: "new", title: task.slice(0, 72), prompt: task, goal: deriveGoal(task), success: DEFAULT_SUCCESS, deps: [] },
348
+ inferredDeps: [],
349
+ };
350
+ }
351
+ const user = [
352
+ `Repository root: ${ctx.root}`,
353
+ `Branch: ${ctx.branch}`,
354
+ "",
355
+ "Frontier nodes (in-flight, not yet merged):",
356
+ ...frontierNodes.map((node) => `- ${node.id}: ${node.title}`),
357
+ "",
358
+ `New task to reconcile:\n${task}`,
359
+ ].join("\n");
360
+ let output;
361
+ try {
362
+ output = await callTextModel({
363
+ model: PLANNER_MODEL,
364
+ system: reconcileSystemPrompt(),
365
+ user,
366
+ maxTokens: 1024,
367
+ timeoutMs: 30000,
368
+ });
369
+ }
370
+ catch {
371
+ return fallback();
372
+ }
373
+ let dag;
374
+ try {
375
+ dag = parsePlanBlock(output);
376
+ }
377
+ catch {
378
+ return fallback();
379
+ }
380
+ const node = dag.nodes[0];
381
+ if (!node) {
382
+ return fallback();
383
+ }
384
+ const frontierIds = new Set(frontierNodes.map((frontierNode) => frontierNode.id));
385
+ // Injection reconciliation only ever produces hard/soft edges; the planner
386
+ // parser never emits judge edges, so coerce any stray non-hard to soft.
387
+ const inferredDeps = node.deps
388
+ .filter((dep) => frontierIds.has(dep.on))
389
+ .map((dep) => ({ node: dep.on, type: dep.type === "hard" ? "hard" : "soft" }));
390
+ return { node, inferredDeps };
391
+ }
392
+ // ---------------------------------------------------------------------------
393
+ // Fan-out-and-judge: N independent variant agents attempt the same task, then a
394
+ // single judge agent compares their diffs and produces the winning
395
+ // implementation. Modeled as a DAG: N variant roots + 1 judge node with a
396
+ // "judge" edge from each variant. The judge becomes ready (isReady) when every
397
+ // variant has reached review; each variant's diff is delivered to the judge on
398
+ // review (treated like a soft edge, but gated on review not merge).
399
+ // ---------------------------------------------------------------------------
400
+ // Short angle hints cycled across variants so the attempts genuinely differ
401
+ // instead of being N identical runs of the same prompt.
402
+ const FANOUT_ANGLES = ["simplicity", "robustness", "minimal-diff", "speed", "clarity"];
403
+ export function buildFanoutDag(task, n, opts = {}) {
404
+ const count = Math.max(2, Math.min(6, Math.floor(Number.isFinite(n) ? n : 3)));
405
+ const trimmed = task.trim();
406
+ const shortTitle = trimmed.slice(0, 56) || "task";
407
+ const nodes = [];
408
+ const variantIds = [];
409
+ for (let index = 0; index < count; index += 1) {
410
+ const angle = FANOUT_ANGLES[index % FANOUT_ANGLES.length] ?? "simplicity";
411
+ const id = `v${index}`;
412
+ variantIds.push(id);
413
+ // Each variant: objective = the task with its angle; success = its approach
414
+ // is implemented and its own verification passes. The objective-format header is
415
+ // applied at scaffold time (scaffoldPlan), so the body stays raw here.
416
+ nodes.push({
417
+ id,
418
+ title: `variant ${index + 1}/${count}: ${shortTitle}`,
419
+ goal: `${trimmed} (favoring ${angle})`,
420
+ success: "your approach is implemented and its own verification passes",
421
+ prompt: [
422
+ trimmed,
423
+ "",
424
+ `Approach variant ${index + 1} of ${count}: favor ${angle}. Implement the task end to end in your workspace; another agent will compare your result against the other variants.`,
425
+ ].join("\n"),
426
+ deps: [],
427
+ ...(opts.backend ? { backend: opts.backend } : {}),
428
+ ...(opts.model ? { model: opts.model } : {}),
429
+ ...(opts.effort ? { effort: opts.effort } : {}),
430
+ });
431
+ }
432
+ // Judge: objective = pick/synthesize the best; success = the final
433
+ // implementation is complete and verified. The objective-format header is applied
434
+ // at scaffold time (scaffoldPlan).
435
+ const judgePrompt = [
436
+ `${count} independent agents each attempted this task: ${trimmed}`,
437
+ "Their diffs will be provided as context below.",
438
+ "Compare them, choose the best approach (you may combine the strongest parts of several),",
439
+ "and produce the final, complete implementation in your workspace.",
440
+ "Note which variant you based it on.",
441
+ ].join(" ");
442
+ const judge = {
443
+ id: "judge",
444
+ title: `judge: ${shortTitle}`,
445
+ goal: `pick or synthesize the best implementation for: ${trimmed}`,
446
+ success: "the final implementation is complete and verified",
447
+ prompt: judgePrompt,
448
+ deps: variantIds.map((variantId) => ({ on: variantId, type: "judge" })),
449
+ ...(opts.backend ? { backend: opts.backend } : {}),
450
+ ...(opts.model ? { model: opts.model } : {}),
451
+ ...(opts.effort ? { effort: opts.effort } : {}),
452
+ };
453
+ nodes.push(judge);
454
+ const edges = variantIds.map((variantId) => ({
455
+ from: variantId,
456
+ to: "judge",
457
+ type: "judge",
458
+ }));
459
+ return { nodes, edges };
460
+ }
461
+ // ---------------------------------------------------------------------------
462
+ // Scaffold: turn a PlanDag into real graph.json nodes + edges, each backed by
463
+ // an empty jj change parented on its hard+soft deps' changes (plan section 3a).
464
+ // Dependents exist as real merge changes before parents do work.
465
+ // ---------------------------------------------------------------------------
466
+ export async function scaffoldPlan(repoRoot, dag) {
467
+ // Install the runtime exclusions before the first jj command snapshots @, so
468
+ // graph.json and worker ledgers can never become parents of task changes.
469
+ await ensureProjectRuntimeIgnored(repoRoot);
470
+ const order = topoOrderHard(dag);
471
+ const trunk = (await currentJjChangeId(repoRoot)) || "@";
472
+ // Map plan id -> created jj change id, filled as we walk in topo order so a
473
+ // child can parent on its already-created parents.
474
+ const changeByPlanId = new Map();
475
+ // Map plan id -> the final graph node id (content-hashed, mergeable).
476
+ const nodeIdByPlanId = new Map();
477
+ for (const node of order) {
478
+ // hard+soft deps contribute jj-change parentage (the change stacks on them).
479
+ // judge deps do NOT: a judge node produces its own implementation off the
480
+ // trunk and the variants it compares are never merged.
481
+ const parentChangeIds = node.deps
482
+ .filter((dep) => dep.type !== "judge")
483
+ .map((dep) => changeByPlanId.get(dep.on))
484
+ .filter((value) => Boolean(value));
485
+ const parents = parentChangeIds.length ? parentChangeIds : [trunk];
486
+ const nodeId = newNodeId(node.title);
487
+ const changeId = await createEmptyChange({
488
+ repoRoot,
489
+ parents,
490
+ description: `rudder-node:${nodeId} ${node.title}`,
491
+ });
492
+ changeByPlanId.set(node.id, changeId);
493
+ nodeIdByPlanId.set(node.id, nodeId);
494
+ }
495
+ const createdAt = nowIso();
496
+ await updateGraph(repoRoot, (graph) => {
497
+ for (const node of dag.nodes) {
498
+ const nodeId = nodeIdByPlanId.get(node.id);
499
+ const changeId = changeByPlanId.get(node.id);
500
+ if (!nodeId) {
501
+ continue;
502
+ }
503
+ const incomingEdgeIds = [];
504
+ for (const dep of node.deps) {
505
+ const fromId = nodeIdByPlanId.get(dep.on);
506
+ if (!fromId) {
507
+ continue;
508
+ }
509
+ const edgeId = newEdgeId(fromId, nodeId);
510
+ incomingEdgeIds.push(edgeId);
511
+ graph.edges[edgeId] = {
512
+ id: edgeId,
513
+ from: fromId,
514
+ to: nodeId,
515
+ type: dep.type,
516
+ ...(dep.why ? { why: dep.why } : {}),
517
+ };
518
+ }
519
+ const goal = normalizeGoalLine(node.goal ?? deriveGoal(node.title || node.prompt), node.title || node.prompt);
520
+ const success = normalizeGoalLine(node.success ?? DEFAULT_SUCCESS, DEFAULT_SUCCESS);
521
+ graph.nodes[nodeId] = {
522
+ id: nodeId,
523
+ title: node.title,
524
+ // Persist the launch prompt already in objective format so every planner-produced
525
+ // worker leads with its objective + verifiable done-when line.
526
+ prompt: formatGoalPrompt({ goal, success, body: node.prompt }),
527
+ goal,
528
+ success,
529
+ backend: node.backend ?? "claude",
530
+ ...(node.model ? { model: node.model } : {}),
531
+ ...(node.effort ? { effort: node.effort } : {}),
532
+ status: "planned",
533
+ ...(changeId ? { jjChangeId: changeId } : {}),
534
+ deps: incomingEdgeIds,
535
+ source: "planner",
536
+ createdAt,
537
+ updatedAt: createdAt,
538
+ };
539
+ }
540
+ return graph;
541
+ });
542
+ }
543
+ /**
544
+ * Topological order over HARD edges (the ones that gate scaffolding parentage).
545
+ * parsePlanBlock already rejected hard cycles, so Kahn's algorithm completes;
546
+ * any node left over (only possible via a soft-only cycle) is appended.
547
+ */
548
+ function topoOrderHard(dag) {
549
+ const byId = new Map(dag.nodes.map((node) => [node.id, node]));
550
+ const indegree = new Map(dag.nodes.map((node) => [node.id, 0]));
551
+ const adjacency = new Map(dag.nodes.map((node) => [node.id, []]));
552
+ for (const edge of dag.edges) {
553
+ if (edge.type !== "hard" || !indegree.has(edge.to) || !adjacency.has(edge.from)) {
554
+ continue;
555
+ }
556
+ indegree.set(edge.to, (indegree.get(edge.to) ?? 0) + 1);
557
+ adjacency.get(edge.from)?.push(edge.to);
558
+ }
559
+ const queue = dag.nodes.filter((node) => (indegree.get(node.id) ?? 0) === 0).map((node) => node.id);
560
+ const ordered = [];
561
+ const seen = new Set();
562
+ while (queue.length) {
563
+ const id = queue.shift();
564
+ if (seen.has(id)) {
565
+ continue;
566
+ }
567
+ seen.add(id);
568
+ const node = byId.get(id);
569
+ if (node) {
570
+ ordered.push(node);
571
+ }
572
+ for (const next of adjacency.get(id) ?? []) {
573
+ const degree = (indegree.get(next) ?? 0) - 1;
574
+ indegree.set(next, degree);
575
+ if (degree === 0) {
576
+ queue.push(next);
577
+ }
578
+ }
579
+ }
580
+ for (const node of dag.nodes) {
581
+ if (!seen.has(node.id)) {
582
+ ordered.push(node);
583
+ }
584
+ }
585
+ return ordered;
586
+ }
587
+ //# sourceMappingURL=planner.js.map