gm-orchestrator 0.2.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 (94) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +289 -0
  3. package/dist/cli/index.d.ts +3 -0
  4. package/dist/cli/index.d.ts.map +1 -0
  5. package/dist/cli/index.js +215 -0
  6. package/dist/cli/index.js.map +1 -0
  7. package/dist/core/orchestrator.d.ts +23 -0
  8. package/dist/core/orchestrator.d.ts.map +1 -0
  9. package/dist/core/orchestrator.js +173 -0
  10. package/dist/core/orchestrator.js.map +1 -0
  11. package/dist/core/permissions.d.ts +18 -0
  12. package/dist/core/permissions.d.ts.map +1 -0
  13. package/dist/core/permissions.js +42 -0
  14. package/dist/core/permissions.js.map +1 -0
  15. package/dist/core/prompt-builder.d.ts +25 -0
  16. package/dist/core/prompt-builder.d.ts.map +1 -0
  17. package/dist/core/prompt-builder.js +84 -0
  18. package/dist/core/prompt-builder.js.map +1 -0
  19. package/dist/core/task-utils.d.ts +5 -0
  20. package/dist/core/task-utils.d.ts.map +1 -0
  21. package/dist/core/task-utils.js +27 -0
  22. package/dist/core/task-utils.js.map +1 -0
  23. package/dist/core/types.d.ts +150 -0
  24. package/dist/core/types.d.ts.map +1 -0
  25. package/dist/core/types.js +5 -0
  26. package/dist/core/types.js.map +1 -0
  27. package/dist/index.d.ts +11 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +12 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/infra/claude-runner.d.ts +14 -0
  32. package/dist/infra/claude-runner.d.ts.map +1 -0
  33. package/dist/infra/claude-runner.js +42 -0
  34. package/dist/infra/claude-runner.js.map +1 -0
  35. package/dist/infra/config.d.ts +7 -0
  36. package/dist/infra/config.d.ts.map +1 -0
  37. package/dist/infra/config.js +61 -0
  38. package/dist/infra/config.js.map +1 -0
  39. package/dist/infra/gm-client.d.ts +32 -0
  40. package/dist/infra/gm-client.d.ts.map +1 -0
  41. package/dist/infra/gm-client.js +70 -0
  42. package/dist/infra/gm-client.js.map +1 -0
  43. package/dist/infra/gm-discovery.d.ts +16 -0
  44. package/dist/infra/gm-discovery.d.ts.map +1 -0
  45. package/dist/infra/gm-discovery.js +53 -0
  46. package/dist/infra/gm-discovery.js.map +1 -0
  47. package/dist/infra/logger.d.ts +13 -0
  48. package/dist/infra/logger.d.ts.map +1 -0
  49. package/dist/infra/logger.js +44 -0
  50. package/dist/infra/logger.js.map +1 -0
  51. package/dist/infra/notifications/desktop.d.ts +6 -0
  52. package/dist/infra/notifications/desktop.d.ts.map +1 -0
  53. package/dist/infra/notifications/desktop.js +18 -0
  54. package/dist/infra/notifications/desktop.js.map +1 -0
  55. package/dist/infra/notifications/index.d.ts +9 -0
  56. package/dist/infra/notifications/index.d.ts.map +1 -0
  57. package/dist/infra/notifications/index.js +40 -0
  58. package/dist/infra/notifications/index.js.map +1 -0
  59. package/dist/infra/notifications/telegram.d.ts +9 -0
  60. package/dist/infra/notifications/telegram.d.ts.map +1 -0
  61. package/dist/infra/notifications/telegram.js +41 -0
  62. package/dist/infra/notifications/telegram.js.map +1 -0
  63. package/dist/infra/notifications/types.d.ts +30 -0
  64. package/dist/infra/notifications/types.d.ts.map +1 -0
  65. package/dist/infra/notifications/types.js +3 -0
  66. package/dist/infra/notifications/types.js.map +1 -0
  67. package/dist/infra/notifications/webhook.d.ts +9 -0
  68. package/dist/infra/notifications/webhook.d.ts.map +1 -0
  69. package/dist/infra/notifications/webhook.js +39 -0
  70. package/dist/infra/notifications/webhook.js.map +1 -0
  71. package/dist/infra/task-poller.d.ts +9 -0
  72. package/dist/infra/task-poller.d.ts.map +1 -0
  73. package/dist/infra/task-poller.js +42 -0
  74. package/dist/infra/task-poller.js.map +1 -0
  75. package/dist/server/api.d.ts +23 -0
  76. package/dist/server/api.d.ts.map +1 -0
  77. package/dist/server/api.js +143 -0
  78. package/dist/server/api.js.map +1 -0
  79. package/dist/server/index.d.ts +18 -0
  80. package/dist/server/index.d.ts.map +1 -0
  81. package/dist/server/index.js +73 -0
  82. package/dist/server/index.js.map +1 -0
  83. package/dist/server/runner-service.d.ts +15 -0
  84. package/dist/server/runner-service.d.ts.map +1 -0
  85. package/dist/server/runner-service.js +193 -0
  86. package/dist/server/runner-service.js.map +1 -0
  87. package/dist/server/ws.d.ts +9 -0
  88. package/dist/server/ws.d.ts.map +1 -0
  89. package/dist/server/ws.js +30 -0
  90. package/dist/server/ws.js.map +1 -0
  91. package/dist/ui/assets/index-BYPkFAEX.css +1 -0
  92. package/dist/ui/assets/index-CEQTkIqE.js +60 -0
  93. package/dist/ui/index.html +13 -0
  94. package/package.json +70 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Vachick
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,289 @@
1
+ # gm-orchestrator
2
+
3
+ Autonomous AI sprint runner for [GraphMemory](https://github.com/graph-memory/graphmemory).
4
+
5
+ Spawns Claude Code sessions to work through your tasks automatically — one task at a time,
6
+ fresh context each session, no token bleed. You define the work in GraphMemory, hit Run, go do something else.
7
+
8
+ ```bash
9
+ npm install -g gm-orchestrator
10
+ gm-orchestrator
11
+ ```
12
+
13
+ → Opens `http://localhost:4242` in your browser. That's it.
14
+
15
+ ---
16
+
17
+ ## How it works
18
+
19
+ ```
20
+ gm-orchestrator
21
+
22
+ Reads tasks from GraphMemory (priority order, blockers respected)
23
+
24
+ For each task:
25
+ spawn → claude --print "<task prompt>"
26
+ wait → Claude calls tasks_move("done") when finished
27
+ next → kill session, start fresh, repeat
28
+
29
+ Notify you when sprint/epic is complete
30
+ ```
31
+
32
+ Each Claude Code session gets a clean context window. No accumulation, no drift.
33
+
34
+ ---
35
+
36
+ ## Prerequisites
37
+
38
+ - **Node.js** >= 18
39
+ - **[GraphMemory](https://github.com/graph-memory/graphmemory)** running locally (`graphmemory serve`)
40
+ - **[Claude Code](https://docs.anthropic.com/en/docs/claude-code)** installed (`npm install -g @anthropic-ai/claude-code`)
41
+ - Claude Code connected to your GraphMemory instance via MCP
42
+
43
+ ---
44
+
45
+ ## Installation
46
+
47
+ ```bash
48
+ npm install -g gm-orchestrator
49
+ ```
50
+
51
+ ---
52
+
53
+ ## Quick Start
54
+
55
+ ```bash
56
+ # 1. Start GraphMemory in your project
57
+ cd /path/to/your-project
58
+ graphmemory serve
59
+
60
+ # 2. Start gm-orchestrator
61
+ gm-orchestrator
62
+ # → opens http://localhost:4242
63
+ ```
64
+
65
+ On first run, the wizard walks you through selecting a project and configuring permissions.
66
+
67
+ ---
68
+
69
+ ## Browser UI
70
+
71
+ The primary interface. Opens automatically at `http://localhost:4242`.
72
+
73
+ ### Dashboard
74
+ Overview of your project: task queue sorted by priority, epics, done count for today.
75
+ One click to start a sprint or select an epic.
76
+
77
+ ### Sprint Runner
78
+ Live view while work is in progress:
79
+ - Task queue with status (queued / running / done / cancelled)
80
+ - Real-time Claude log stream — see exactly what Claude is doing
81
+ - Progress bar and elapsed time per task
82
+ - Stop button
83
+
84
+ ### Settings
85
+ - GraphMemory connection (URL, project ID, API key)
86
+ - Permissions — what Claude is allowed to do per session
87
+ - Notifications — Telegram, webhook, desktop
88
+ - Timeout and retry configuration
89
+
90
+ ---
91
+
92
+ ## Permissions
93
+
94
+ Control what Claude Code can do in each session:
95
+
96
+ ```json
97
+ {
98
+ "permissions": {
99
+ "writeFiles": true,
100
+ "runCommands": ["npm test", "npm run build", "git add", "git commit"],
101
+ "blockedCommands": ["git push", "npm publish"]
102
+ }
103
+ }
104
+ ```
105
+
106
+ Translates directly to `--allowedTools` flags passed to `claude --print`.
107
+ Claude cannot run blocked commands even if it tries.
108
+
109
+ ---
110
+
111
+ ## Notifications
112
+
113
+ Get notified when work is done — useful for long sprints.
114
+
115
+ **Telegram:**
116
+ ```json
117
+ {
118
+ "notifications": {
119
+ "telegram": {
120
+ "botToken": "...",
121
+ "chatId": "..."
122
+ },
123
+ "on": ["sprint_complete", "task_failed"]
124
+ }
125
+ }
126
+ ```
127
+
128
+ **Webhook** (generic POST — works with Slack, Discord, custom endpoints):
129
+ ```json
130
+ {
131
+ "notifications": {
132
+ "webhook": {
133
+ "url": "https://your-endpoint.com/notify",
134
+ "headers": { "Authorization": "Bearer ..." }
135
+ }
136
+ }
137
+ }
138
+ ```
139
+
140
+ **Desktop** — native OS notification (macOS, Linux, Windows).
141
+
142
+ ---
143
+
144
+ ## Configuration
145
+
146
+ Resolved in order — later sources override earlier:
147
+
148
+ 1. Defaults
149
+ 2. `.gm-orchestrator.json` in current directory
150
+ 3. Environment variables
151
+ 4. CLI flags
152
+
153
+ ### Config file
154
+
155
+ ```json
156
+ {
157
+ "baseUrl": "http://localhost:3000",
158
+ "projectId": "my-app",
159
+ "apiKey": "",
160
+ "timeoutMs": 900000,
161
+ "pauseMs": 2000,
162
+ "maxRetries": 1,
163
+ "claudeArgs": [],
164
+ "permissions": {
165
+ "writeFiles": true,
166
+ "runCommands": ["npm test", "git commit"],
167
+ "blockedCommands": ["git push", "npm publish"]
168
+ },
169
+ "notifications": {
170
+ "telegram": {
171
+ "botToken": "",
172
+ "chatId": ""
173
+ }
174
+ }
175
+ }
176
+ ```
177
+
178
+ ### Environment variables
179
+
180
+ | Variable | Maps to |
181
+ |-----------------|--------------|
182
+ | `GM_BASE_URL` | `baseUrl` |
183
+ | `GM_PROJECT_ID` | `projectId` |
184
+ | `GM_API_KEY` | `apiKey` |
185
+ | `GM_TIMEOUT_MS` | `timeoutMs` |
186
+ | `GM_PORT` | server port (default: 4242) |
187
+
188
+ ### All config options
189
+
190
+ | Option | Type | Default | Description |
191
+ |--------------|------------|-------------------|----------------------------------|
192
+ | `baseUrl` | `string` | `http://localhost:3000` | GraphMemory server URL |
193
+ | `projectId` | `string` | *(required)* | GraphMemory project ID |
194
+ | `apiKey` | `string` | | API key (if GM auth is enabled) |
195
+ | `timeoutMs` | `number` | `900000` (15 min) | Per-task timeout in ms |
196
+ | `pauseMs` | `number` | `2000` | Pause between tasks |
197
+ | `maxRetries` | `number` | `1` | Retries on timeout/error |
198
+ | `claudeArgs` | `string[]` | `[]` | Extra args for `claude --print` |
199
+ | `dryRun` | `boolean` | `false` | Preview prompts, don't run |
200
+
201
+ ---
202
+
203
+ ## CLI (advanced)
204
+
205
+ The browser UI is the primary interface. CLI commands are available for scripting and CI.
206
+
207
+ ```bash
208
+ # Start UI (default)
209
+ gm-orchestrator
210
+
211
+ # Run sprint headless (no browser)
212
+ gm-orchestrator sprint --project my-app
213
+
214
+ # Run specific epic headless
215
+ gm-orchestrator epic <epicId> --project my-app
216
+
217
+ # Check task counts
218
+ gm-orchestrator status --project my-app
219
+
220
+ # Preview prompts without spawning Claude
221
+ gm-orchestrator sprint --project my-app --dry-run
222
+ ```
223
+
224
+ | Flag | Description | Default |
225
+ |------|-------------|---------|
226
+ | `--project`, `-p` | GraphMemory project ID | env / config |
227
+ | `--tag`, `-t` | Filter tasks by tag | |
228
+ | `--timeout <min>` | Per-task timeout in minutes | 15 |
229
+ | `--retries <n>` | Retries on timeout/error | 1 |
230
+ | `--dry-run` | Preview prompts, don't spawn Claude | |
231
+ | `--config` | Print resolved config and exit | |
232
+
233
+ ---
234
+
235
+ ## Programmatic API
236
+
237
+ ```ts
238
+ import {
239
+ runSprint,
240
+ runEpic,
241
+ GraphMemoryClient,
242
+ ClaudeRunner,
243
+ TaskPoller,
244
+ consoleLogger,
245
+ loadConfig,
246
+ } from 'gm-orchestrator';
247
+
248
+ const config = loadConfig({ projectId: 'my-app' });
249
+ const gm = new GraphMemoryClient({ baseUrl: config.baseUrl, projectId: config.projectId });
250
+
251
+ const ports = {
252
+ gm,
253
+ runner: new ClaudeRunner(),
254
+ poller: new TaskPoller(gm),
255
+ logger: consoleLogger,
256
+ };
257
+
258
+ await runSprint(ports, config);
259
+ await runEpic('epic-id', ports, config);
260
+ ```
261
+
262
+ ### Core functions
263
+ - **`runSprint(ports, config)`** — run all todo/in_progress tasks by priority
264
+ - **`runEpic(epicId, ports, config)`** — run all tasks in an epic
265
+ - **`buildPrompt(task)`** — generate autonomous-execution prompt for a task
266
+
267
+ ### Utilities
268
+ - **`sortByPriority(tasks)`** — sort by priority order
269
+ - **`isTerminal(status)`** — check if status is done/cancelled
270
+ - **`areBlockersResolved(task)`** — check all blockers are done
271
+ - **`loadConfig(overrides?)`** — load and merge config
272
+ - **`validateConfig(config)`** — validate (throws on missing projectId)
273
+
274
+ ### Infrastructure
275
+ - **`GraphMemoryClient`** — GraphMemory REST client
276
+ - **`ClaudeRunner`** — spawns claude --print sessions
277
+ - **`TaskPoller`** — polls task status until completion
278
+ - **`consoleLogger` / `silentLogger`** — logger implementations
279
+
280
+ ### Types
281
+ `Task`, `Epic`, `TaskStatus`, `TaskPriority`, `EpicStatus`, `TaskRef`,
282
+ `OrchestratorConfig`, `TaskRunResult`, `SprintStats`,
283
+ `GraphMemoryPort`, `ClaudeRunnerPort`, `TaskPollerPort`, `Logger`
284
+
285
+ ---
286
+
287
+ ## License
288
+
289
+ MIT
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,215 @@
1
+ #!/usr/bin/env node
2
+ import { GraphMemoryClient } from '../infra/gm-client.js';
3
+ import { ClaudeRunner } from '../infra/claude-runner.js';
4
+ import { TaskPoller } from '../infra/task-poller.js';
5
+ import { consoleLogger } from '../infra/logger.js';
6
+ import { loadConfig, validateConfig, saveConfig } from '../infra/config.js';
7
+ import { runSprint, runEpic } from '../core/orchestrator.js';
8
+ import { createServer } from '../server/index.js';
9
+ import { createApiRouter } from '../server/api.js';
10
+ import { createWebSocketServer } from '../server/ws.js';
11
+ import { createRunnerService } from '../server/runner-service.js';
12
+ import { discoverServers } from '../infra/gm-discovery.js';
13
+ function parseArgs(argv) {
14
+ const args = argv.slice(2);
15
+ const result = {
16
+ command: null,
17
+ epicId: null,
18
+ overrides: {},
19
+ printConfig: false,
20
+ headless: false,
21
+ };
22
+ for (let i = 0; i < args.length; i++) {
23
+ const a = args[i];
24
+ if (!result.command && !a.startsWith('-')) {
25
+ result.command = a;
26
+ continue;
27
+ }
28
+ if (result.command === 'epic' && !result.epicId && !a.startsWith('-')) {
29
+ result.epicId = a;
30
+ continue;
31
+ }
32
+ switch (a) {
33
+ case '--dry-run':
34
+ result.overrides.dryRun = true;
35
+ break;
36
+ case '--config':
37
+ result.printConfig = true;
38
+ break;
39
+ case '--headless':
40
+ result.headless = true;
41
+ break;
42
+ case '--help':
43
+ case '-h':
44
+ printHelp();
45
+ process.exit(0);
46
+ break;
47
+ case '--project':
48
+ case '-p':
49
+ result.overrides.projectId = args[++i];
50
+ break;
51
+ case '--tag':
52
+ case '-t':
53
+ result.overrides.tag = args[++i];
54
+ break;
55
+ case '--timeout':
56
+ result.overrides.timeoutMs = Number(args[++i]) * 60_000;
57
+ break;
58
+ case '--retries':
59
+ result.overrides.maxRetries = Number(args[++i]);
60
+ break;
61
+ }
62
+ }
63
+ return result;
64
+ }
65
+ function printHelp() {
66
+ console.log(`
67
+ gm-orchestrator — tokenless Claude Code orchestrator for GraphMemory
68
+
69
+ USAGE
70
+ gm-orchestrator [command] [options]
71
+
72
+ COMMANDS
73
+ serve Start the web UI + API server on :4242 (default)
74
+ sprint Run all todo/in_progress tasks sorted by priority
75
+ epic <epicId> Run all tasks in an epic
76
+ status Show task counts (no Claude sessions spawned)
77
+
78
+ OPTIONS
79
+ --project, -p <id> GraphMemory project ID (or GM_PROJECT_ID env)
80
+ --tag, -t <tag> Filter tasks by tag
81
+ --timeout <min> Per-task timeout in minutes (default: 15)
82
+ --retries <n> Retries on timeout/error (default: 1)
83
+ --dry-run Preview prompts, don't spawn Claude
84
+ --headless Run in CLI-only mode (skip server, require command)
85
+ --config Print resolved config and exit
86
+
87
+ CONFIG FILE (.gm-orchestrator.json)
88
+ {
89
+ "baseUrl": "http://localhost:3000",
90
+ "projectId": "my-app",
91
+ "apiKey": "mgm-key-...",
92
+ "timeoutMs": 900000,
93
+ "maxRetries": 1,
94
+ "claudeArgs": []
95
+ }
96
+
97
+ ENV VARS
98
+ GM_BASE_URL / GM_PROJECT_ID / GM_API_KEY / GM_TIMEOUT_MS
99
+ `);
100
+ }
101
+ // ── Main ──────────────────────────────────────────────────────────────────
102
+ async function main() {
103
+ const { command, epicId, overrides, printConfig, headless } = parseArgs(process.argv);
104
+ const config = loadConfig(overrides);
105
+ if (printConfig) {
106
+ const display = { ...config, apiKey: config.apiKey ? '***' : undefined };
107
+ console.log(JSON.stringify(display, null, 2));
108
+ return;
109
+ }
110
+ if (command === 'help') {
111
+ printHelp();
112
+ return;
113
+ }
114
+ // Default to server mode when no command given (unless --headless)
115
+ const effectiveCommand = command ?? (headless ? null : 'serve');
116
+ if (!effectiveCommand) {
117
+ printHelp();
118
+ return;
119
+ }
120
+ if (effectiveCommand === 'serve') {
121
+ const port = Number(process.env['GM_PORT']) || 4242;
122
+ consoleLogger.info(`gm-orchestrator v1.0.0 → http://localhost:${port}`);
123
+ // Server mode doesn't require projectId upfront — it's set via the UI
124
+ const { app, start, mountStaticUI } = createServer({ logger: consoleLogger });
125
+ const gmClient = new GraphMemoryClient({
126
+ baseUrl: config.baseUrl,
127
+ projectId: config.projectId || 'default',
128
+ });
129
+ // Create a no-op WS bus for now — replaced after server starts
130
+ const wsBusHolder = {
131
+ current: { broadcast() { }, get clientCount() { return 0; }, close: async () => { } },
132
+ };
133
+ const runner = createRunnerService({
134
+ config,
135
+ gm: gmClient,
136
+ runner: new ClaudeRunner(),
137
+ poller: new TaskPoller(gmClient),
138
+ logger: consoleLogger,
139
+ wsBus: { broadcast(e) { wsBusHolder.current.broadcast(e); }, get clientCount() { return wsBusHolder.current.clientCount; }, close() { return wsBusHolder.current.close(); } },
140
+ });
141
+ const apiRouter = createApiRouter({
142
+ config,
143
+ logger: consoleLogger,
144
+ gmDiscovery: { discoverServers },
145
+ gmClient,
146
+ runner,
147
+ saveConfig: (partial) => saveConfig(partial),
148
+ });
149
+ // Mount API routes before the catch-all static handler
150
+ app.use(apiRouter);
151
+ mountStaticUI();
152
+ const server = await start();
153
+ wsBusHolder.current = createWebSocketServer(server);
154
+ return;
155
+ }
156
+ validateConfig(config);
157
+ const gm = new GraphMemoryClient({
158
+ baseUrl: config.baseUrl,
159
+ projectId: config.projectId,
160
+ ...(config.apiKey !== undefined && { apiKey: config.apiKey }),
161
+ });
162
+ const ports = {
163
+ gm,
164
+ runner: new ClaudeRunner(),
165
+ poller: new TaskPoller(gm),
166
+ logger: consoleLogger,
167
+ };
168
+ if (effectiveCommand === 'status') {
169
+ const [todo, inProgress, done] = await Promise.all([
170
+ gm.listTasks({ status: 'todo' }),
171
+ gm.listTasks({ status: 'in_progress' }),
172
+ gm.listTasks({ status: 'done' }),
173
+ ]);
174
+ const epics = await gm.listEpics().catch(() => []);
175
+ consoleLogger.section(`Status — ${config.projectId}`);
176
+ console.log(` todo: ${todo.length}`);
177
+ console.log(` in_progress: ${inProgress.length}`);
178
+ console.log(` done: ${done.length}`);
179
+ console.log(` epics: ${epics.length}`);
180
+ if (todo.length) {
181
+ consoleLogger.section('Next up');
182
+ todo.slice(0, 5).forEach((t) => consoleLogger.task(t));
183
+ if (todo.length > 5)
184
+ console.log(` ... and ${todo.length - 5} more`);
185
+ }
186
+ return;
187
+ }
188
+ if (effectiveCommand === 'sprint') {
189
+ await runSprint(ports, config);
190
+ return;
191
+ }
192
+ if (effectiveCommand === 'epic') {
193
+ if (!epicId) {
194
+ consoleLogger.error('epic command requires an ID: gm-orchestrator epic <epicId>');
195
+ process.exit(1);
196
+ }
197
+ await runEpic(epicId, ports, config);
198
+ return;
199
+ }
200
+ consoleLogger.error(`Unknown command: ${effectiveCommand}`);
201
+ printHelp();
202
+ process.exit(1);
203
+ }
204
+ process.on('SIGINT', () => {
205
+ console.log('');
206
+ consoleLogger.warn('Interrupted — current Claude session may still be running');
207
+ consoleLogger.skip('Check GraphMemory UI for task status before resuming');
208
+ process.exit(0);
209
+ });
210
+ process.on('unhandledRejection', (err) => {
211
+ consoleLogger.error(`Unhandled: ${err instanceof Error ? err.message : String(err)}`);
212
+ process.exit(1);
213
+ });
214
+ void main();
215
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { GraphMemoryPort, ClaudeRunnerPort, TaskPollerPort, OrchestratorConfig, SprintStats } from './types.js';
2
+ import type { Logger } from '../infra/logger.js';
3
+ interface Ports {
4
+ gm: GraphMemoryPort;
5
+ runner: ClaudeRunnerPort;
6
+ poller: TaskPollerPort;
7
+ logger: Logger;
8
+ }
9
+ /**
10
+ * Orchestrates a full sprint: runs all todo/in_progress tasks in priority
11
+ * order, respecting blockers, retrying on failure, until none remain.
12
+ *
13
+ * Pure orchestration logic — all side effects go through injected ports.
14
+ * This makes the core fully testable without spawning Claude or hitting GM.
15
+ */
16
+ export declare function runSprint(ports: Ports, config: OrchestratorConfig): Promise<SprintStats>;
17
+ /**
18
+ * Runs all tasks belonging to an epic, in priority order with blocker checks.
19
+ * Marks the epic done when all tasks complete.
20
+ */
21
+ export declare function runEpic(epicId: string, ports: Ports, config: OrchestratorConfig): Promise<SprintStats>;
22
+ export {};
23
+ //# sourceMappingURL=orchestrator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../src/core/orchestrator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,WAAW,EAGZ,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAEjD,UAAU,KAAK;IACb,EAAE,EAAE,eAAe,CAAC;IACpB,MAAM,EAAE,gBAAgB,CAAC;IACzB,MAAM,EAAE,cAAc,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;GAMG;AACH,wBAAsB,SAAS,CAC7B,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,WAAW,CAAC,CAiDtB;AAED;;;GAGG;AACH,wBAAsB,OAAO,CAC3B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,WAAW,CAAC,CAyDtB"}