ndomo 0.1.0 → 0.2.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.
- package/.env.example +4 -0
- package/README.es.md +29 -23
- package/README.md +64 -24
- package/bun.lock +447 -0
- package/docs/configuration.md +4 -4
- package/docs/installation.md +53 -34
- package/docs/installer.md +164 -0
- package/docs/integrations.md +1 -1
- package/docs/web-ui.md +124 -0
- package/package.json +43 -4
- package/scripts/install.sh +28 -0
- package/scripts/smoke-install.sh +47 -0
- package/scripts/smoke-web.sh +335 -0
- package/src/cli/__tests__/install.test.ts +733 -0
- package/src/cli/index.ts +8 -0
- package/src/cli/install.ts +1273 -0
- package/src/config/__tests__/schema.test.ts +223 -0
- package/src/config/schema.ts +129 -16
- package/src/http/__tests__/auth.test.ts +10 -10
- package/src/http/__tests__/spa.test.ts +296 -0
- package/src/http/auth.ts +8 -1
- package/src/http/server.ts +71 -2
- package/.bun-version +0 -1
- package/.dockerignore +0 -79
- package/.editorconfig +0 -18
- package/.github/CODEOWNERS +0 -8
- package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -62
- package/.github/ISSUE_TEMPLATE/config.yml +0 -2
- package/.github/ISSUE_TEMPLATE/feature_request.yml +0 -34
- package/.github/dependabot.yml +0 -36
- package/.github/pull_request_template.md +0 -24
- package/.github/release.yml +0 -30
- package/.github/workflows/gitleaks.yml +0 -28
- package/.github/workflows/release-please.yml +0 -27
- package/.github/workflows/smoke.yml +0 -29
- package/.husky/commit-msg +0 -1
- package/CHANGELOG.md +0 -114
- package/Dockerfile +0 -32
- package/bin/ndomo-analyses.ts +0 -4
- package/bin/ndomo-status.ts +0 -4
- package/biome.json +0 -57
- package/commitlint.config.js +0 -3
- package/opencode.json +0 -5
- package/release-please-config.json +0 -11
- package/scripts/dev-bust-cache.sh +0 -164
- package/scripts/smoke-e2e.ts +0 -704
- package/scripts/smoke-hot.ts +0 -417
- package/scripts/smoke-v4.ts +0 -256
- package/scripts/smoke-v5.ts +0 -397
- package/scripts/uninstall.sh +0 -224
- package/src/index.ts +0 -37
- package/src/lib.ts +0 -65
- package/src/mem/scoped.ts +0 -65
- package/src/orchestrator/background.test.ts +0 -268
- package/src/orchestrator/background.ts +0 -293
- package/src/orchestrator/memory-hook.ts +0 -182
- package/src/orchestrator/reconciler.ts +0 -123
- package/src/orchestrator/scheduler.test.ts +0 -300
- package/src/orchestrator/scheduler.ts +0 -243
- package/src/plugin.test.ts +0 -2574
- package/src/plugin.ts +0 -1690
- package/src/worktrees/manager.ts +0 -236
- package/src/worktrees/state.ts +0 -87
- package/tests/integration/ranger-flow.test.ts +0 -257
- package/tsconfig.json +0 -31
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Agent routing logic for the ndomo orchestrator.
|
|
3
|
-
* Pure functions that determine which specialist agent handles a task.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
/** Decision returned by the scheduler after routing a task. */
|
|
7
|
-
export interface RoutingDecision {
|
|
8
|
-
/** Target agent identifier (e.g. "scout", "go-smith", "sage"). */
|
|
9
|
-
agent: string;
|
|
10
|
-
/** Human-readable reason for the routing choice. */
|
|
11
|
-
reason: string;
|
|
12
|
-
/** Whether this task can run alongside other parallel tasks. */
|
|
13
|
-
parallel: boolean;
|
|
14
|
-
/** Task IDs that must complete before this one starts. */
|
|
15
|
-
dependencies: string[];
|
|
16
|
-
/** Agent that should review output before merge (advisory, not blocking). */
|
|
17
|
-
requiresReview?: string;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/** Incoming task request from the foreman. */
|
|
21
|
-
export interface TaskRequest {
|
|
22
|
-
/** Natural language description of what to do. */
|
|
23
|
-
description: string;
|
|
24
|
-
/** Detected or declared tech stack. */
|
|
25
|
-
stack?: "go" | "vue" | "js" | "python" | "zig" | "generic" | "unknown";
|
|
26
|
-
/** Category of work. */
|
|
27
|
-
type: "implement" | "explore" | "research" | "design" | "debug" | "audit" | "document" | "debate";
|
|
28
|
-
/** Files targeted by this task (for conflict detection). */
|
|
29
|
-
files?: string[];
|
|
30
|
-
/** Risk assessment from the foreman. */
|
|
31
|
-
risk: "low" | "medium" | "high";
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/** Maps known tech stacks to their specialist agent IDs. */
|
|
35
|
-
const STACK_AGENTS: Record<string, string> = {
|
|
36
|
-
go: "go-smith",
|
|
37
|
-
vue: "vue-smith",
|
|
38
|
-
js: "js-smith",
|
|
39
|
-
python: "python-smith",
|
|
40
|
-
zig: "zig-smith",
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Route a task to the appropriate specialist agent.
|
|
45
|
-
*
|
|
46
|
-
* Priority order:
|
|
47
|
-
* 1. Explore → scout
|
|
48
|
-
* 2. Research → scribe
|
|
49
|
-
* 3. Design + vue stack → painter
|
|
50
|
-
* 4. Audit → inspector
|
|
51
|
-
* 5. Document → chronicler
|
|
52
|
-
* 6. Debate → guild
|
|
53
|
-
* 7. Debug + high risk → sage
|
|
54
|
-
* 8. Implement + known stack → stack-smith
|
|
55
|
-
* 9. Implement + generic/unknown → smith
|
|
56
|
-
* 10. High risk + implement → sage (advisory) + stack-smith
|
|
57
|
-
* 11. Default → smith
|
|
58
|
-
*/
|
|
59
|
-
export function routeTask(task: TaskRequest): RoutingDecision {
|
|
60
|
-
const { type, stack, risk } = task;
|
|
61
|
-
|
|
62
|
-
// 1. Explore → scout
|
|
63
|
-
if (type === "explore") {
|
|
64
|
-
return {
|
|
65
|
-
agent: "scout",
|
|
66
|
-
reason: "Exploration task delegated to scout for codebase reconnaissance.",
|
|
67
|
-
parallel: true,
|
|
68
|
-
dependencies: [],
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// 2. Research → scribe
|
|
73
|
-
if (type === "research") {
|
|
74
|
-
return {
|
|
75
|
-
agent: "scribe",
|
|
76
|
-
reason: "Research task delegated to scribe for documentation and investigation.",
|
|
77
|
-
parallel: true,
|
|
78
|
-
dependencies: [],
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// 3. Design + vue → painter
|
|
83
|
-
if (type === "design" && stack === "vue") {
|
|
84
|
-
return {
|
|
85
|
-
agent: "painter",
|
|
86
|
-
reason: "Vue design task delegated to painter for UI/UX composition.",
|
|
87
|
-
parallel: true,
|
|
88
|
-
dependencies: [],
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// 4. Audit → inspector
|
|
93
|
-
if (type === "audit") {
|
|
94
|
-
return {
|
|
95
|
-
agent: "inspector",
|
|
96
|
-
reason: "Audit task delegated to inspector for code quality review.",
|
|
97
|
-
parallel: true,
|
|
98
|
-
dependencies: [],
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// 5. Document → chronicler
|
|
103
|
-
if (type === "document") {
|
|
104
|
-
return {
|
|
105
|
-
agent: "chronicler",
|
|
106
|
-
reason: "Documentation task delegated to chronicler.",
|
|
107
|
-
parallel: true,
|
|
108
|
-
dependencies: [],
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// 6. Debate → guild
|
|
113
|
-
if (type === "debate") {
|
|
114
|
-
return {
|
|
115
|
-
agent: "guild",
|
|
116
|
-
reason: "Debate task delegated to guild for multi-perspective analysis.",
|
|
117
|
-
parallel: false,
|
|
118
|
-
dependencies: [],
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// 7. Debug + high risk → sage
|
|
123
|
-
if (type === "debug" && risk === "high") {
|
|
124
|
-
return {
|
|
125
|
-
agent: "sage",
|
|
126
|
-
reason: "High-risk debug task escalated to sage for careful analysis.",
|
|
127
|
-
parallel: false,
|
|
128
|
-
dependencies: [],
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// 8. Implement + known stack → stack-smith
|
|
133
|
-
if (type === "implement" && stack && stack in STACK_AGENTS) {
|
|
134
|
-
const stackAgent = STACK_AGENTS[stack];
|
|
135
|
-
if (!stackAgent) {
|
|
136
|
-
// Should never happen due to the check above, but satisfies strict nulls
|
|
137
|
-
return {
|
|
138
|
-
agent: "smith",
|
|
139
|
-
reason: "Stack lookup failed, falling back to generic smith.",
|
|
140
|
-
parallel: true,
|
|
141
|
-
dependencies: [],
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// 10. High risk implement → sage advisory + stack-smith
|
|
146
|
-
if (risk === "high") {
|
|
147
|
-
return {
|
|
148
|
-
agent: stackAgent,
|
|
149
|
-
reason: `High-risk ${stack} implementation. Sage should review before merge.`,
|
|
150
|
-
parallel: true,
|
|
151
|
-
dependencies: [],
|
|
152
|
-
requiresReview: "sage",
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
return {
|
|
157
|
-
agent: stackAgent,
|
|
158
|
-
reason: `${stack} implementation delegated to ${stackAgent}.`,
|
|
159
|
-
parallel: true,
|
|
160
|
-
dependencies: [],
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// 9. Implement + generic/unknown → smith
|
|
165
|
-
if (type === "implement") {
|
|
166
|
-
return {
|
|
167
|
-
agent: "smith",
|
|
168
|
-
reason: "Generic implementation task delegated to smith.",
|
|
169
|
-
parallel: true,
|
|
170
|
-
dependencies: [],
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// 11. Default → smith
|
|
175
|
-
return {
|
|
176
|
-
agent: "smith",
|
|
177
|
-
reason: "No specific routing rule matched, defaulting to smith.",
|
|
178
|
-
parallel: true,
|
|
179
|
-
dependencies: [],
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* A routing decision paired with its task ID, used for parallel conflict checks.
|
|
185
|
-
*/
|
|
186
|
-
export interface RoutedTask {
|
|
187
|
-
/** Unique task identifier. */
|
|
188
|
-
id: string;
|
|
189
|
-
/** The routing decision for this task. */
|
|
190
|
-
decision: RoutingDecision;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* Check if a set of tasks can run in parallel without file conflicts.
|
|
195
|
-
*
|
|
196
|
-
* Two tasks conflict when:
|
|
197
|
-
* - They target the same file (write race).
|
|
198
|
-
* - One task's dependency ID matches another task in the batch (ordering violation).
|
|
199
|
-
*
|
|
200
|
-
* Tasks with no explicit file list are assumed non-conflicting (unknown paths,
|
|
201
|
-
* benefit of the doubt).
|
|
202
|
-
*
|
|
203
|
-
* Accepts either:
|
|
204
|
-
* - `RoutedTask[]` (preferred) — checks task ID dependencies.
|
|
205
|
-
* - `RoutingDecision[]` (legacy) — checks agent-name dependencies.
|
|
206
|
-
*
|
|
207
|
-
* @param tasks - Array of routed tasks or routing decisions to evaluate.
|
|
208
|
-
* @returns `true` if no two tasks share a target file or have inter-batch dependencies.
|
|
209
|
-
*/
|
|
210
|
-
export function canRunParallel(tasks: RoutedTask[] | RoutingDecision[]): boolean {
|
|
211
|
-
if (tasks.length === 0) return true;
|
|
212
|
-
|
|
213
|
-
// Detect shape: RoutedTask has `id` + `decision`, RoutingDecision has `agent` + `parallel`
|
|
214
|
-
const isRoutedTask = (t: unknown): t is RoutedTask =>
|
|
215
|
-
typeof t === "object" && t !== null && "id" in t && "decision" in t;
|
|
216
|
-
|
|
217
|
-
if (isRoutedTask(tasks[0])) {
|
|
218
|
-
const routed = tasks as RoutedTask[];
|
|
219
|
-
const allParallel = routed.every((t) => t.decision.parallel);
|
|
220
|
-
if (!allParallel) return false;
|
|
221
|
-
|
|
222
|
-
const taskIds = new Set(routed.map((t) => t.id));
|
|
223
|
-
for (const task of routed) {
|
|
224
|
-
for (const dep of task.decision.dependencies) {
|
|
225
|
-
if (taskIds.has(dep)) return false;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
return true;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
// Legacy path: RoutingDecision[] — dependencies are agent names
|
|
232
|
-
const decisions = tasks as RoutingDecision[];
|
|
233
|
-
const allParallel = decisions.every((t) => t.parallel);
|
|
234
|
-
if (!allParallel) return false;
|
|
235
|
-
|
|
236
|
-
const taskAgents = new Set(decisions.map((t) => t.agent));
|
|
237
|
-
for (const task of decisions) {
|
|
238
|
-
for (const dep of task.dependencies) {
|
|
239
|
-
if (taskAgents.has(dep)) return false;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
return true;
|
|
243
|
-
}
|