orbital-command 0.3.0 → 1.0.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.
- package/README.md +67 -42
- package/bin/commands/config.js +19 -0
- package/bin/commands/events.js +40 -0
- package/bin/commands/launch.js +126 -0
- package/bin/commands/manifest.js +283 -0
- package/bin/commands/registry.js +104 -0
- package/bin/commands/update.js +24 -0
- package/bin/lib/helpers.js +229 -0
- package/bin/orbital.js +95 -870
- package/dist/assets/Landing-CfQdHR0N.js +11 -0
- package/dist/assets/PrimitivesConfig-DThSipFy.js +32 -0
- package/dist/assets/QualityGates-B4kxM5UU.js +26 -0
- package/dist/assets/SessionTimeline-Bz1iZnmg.js +1 -0
- package/dist/assets/Settings-DLcZwbCT.js +12 -0
- package/dist/assets/SourceControl-BMNIz7Lt.js +36 -0
- package/dist/assets/WorkflowVisualizer-CxuSBOYu.js +69 -0
- package/dist/assets/{arrow-down-CPy85_J6.js → arrow-down-DVPp6_qp.js} +1 -1
- package/dist/assets/bot-NFaJBDn_.js +6 -0
- package/dist/assets/{charts-DbDg0Psc.js → charts-LGLb8hyU.js} +1 -1
- package/dist/assets/{circle-x-Cwz6ZQDV.js → circle-x-IsFCkBZu.js} +1 -1
- package/dist/assets/{file-text-C46Xr65c.js → file-text-J1cebZXF.js} +1 -1
- package/dist/assets/{globe-Cn2yNZUD.js → globe-WzeyHsUc.js} +1 -1
- package/dist/assets/index-BdJ57EhC.css +1 -0
- package/dist/assets/index-o4ScMAuR.js +349 -0
- package/dist/assets/{key-OPaNTWJ5.js → key-CKR8JJSj.js} +1 -1
- package/dist/assets/{minus-GMsbpKym.js → minus-CHBsJyjp.js} +1 -1
- package/dist/assets/radio-xqZaR-Uk.js +6 -0
- package/dist/assets/rocket-D_xvvNG6.js +6 -0
- package/dist/assets/{shield-DwAFkDYI.js → shield-TdB1yv_a.js} +1 -1
- package/dist/assets/useSocketListener-0L5yiN5i.js +1 -0
- package/dist/assets/useWorkflowEditor-CqeRWVQX.js +11 -0
- package/dist/assets/workflow-constants-Rw-GmgHZ.js +6 -0
- package/dist/assets/zap-C9wqYMpl.js +6 -0
- package/dist/index.html +3 -3
- package/dist/server/server/__tests__/data-routes.test.js +2 -0
- package/dist/server/server/__tests__/scope-routes.test.js +1 -0
- package/dist/server/server/config-migrator.js +0 -3
- package/dist/server/server/config.js +35 -6
- package/dist/server/server/database.js +0 -22
- package/dist/server/server/index.js +26 -814
- package/dist/server/server/init.js +32 -399
- package/dist/server/server/launch.js +1 -1
- package/dist/server/server/parsers/event-parser.js +4 -1
- package/dist/server/server/project-context.js +19 -9
- package/dist/server/server/project-manager.js +6 -6
- package/dist/server/server/routes/aggregate-routes.js +871 -0
- package/dist/server/server/routes/config-routes.js +41 -88
- package/dist/server/server/routes/data-routes.js +5 -15
- package/dist/server/server/routes/dispatch-routes.js +24 -8
- package/dist/server/server/routes/manifest-routes.js +1 -1
- package/dist/server/server/routes/scope-routes.js +10 -7
- package/dist/server/server/schema.js +1 -0
- package/dist/server/server/services/batch-orchestrator.js +17 -3
- package/dist/server/server/services/config-service.js +10 -1
- package/dist/server/server/services/scope-service.js +7 -7
- package/dist/server/server/services/sprint-orchestrator.js +24 -11
- package/dist/server/server/services/sprint-service.js +2 -2
- package/dist/server/server/uninstall.js +195 -0
- package/dist/server/server/update.js +212 -0
- package/dist/server/server/utils/dispatch-utils.js +8 -6
- package/dist/server/server/utils/flag-builder.js +54 -0
- package/dist/server/server/utils/json-fields.js +14 -0
- package/dist/server/server/utils/json-fields.test.js +73 -0
- package/dist/server/server/utils/route-helpers.js +37 -0
- package/dist/server/server/utils/route-helpers.test.js +115 -0
- package/dist/server/server/watchers/event-watcher.js +28 -13
- package/dist/server/server/wizard/config-editor.js +4 -4
- package/dist/server/server/wizard/doctor.js +2 -2
- package/dist/server/server/wizard/index.js +224 -39
- package/dist/server/server/wizard/phases/welcome.js +1 -4
- package/dist/server/server/wizard/ui.js +6 -7
- package/dist/server/shared/api-types.js +80 -1
- package/dist/server/shared/workflow-engine.js +1 -1
- package/package.json +20 -20
- package/schemas/orbital.config.schema.json +1 -19
- package/scripts/postinstall.js +6 -42
- package/scripts/release.sh +53 -0
- package/server/__tests__/data-routes.test.ts +2 -0
- package/server/__tests__/scope-routes.test.ts +1 -0
- package/server/config-migrator.ts +0 -3
- package/server/config.ts +39 -11
- package/server/database.ts +0 -26
- package/server/global-config.ts +4 -0
- package/server/index.ts +29 -894
- package/server/init.ts +32 -443
- package/server/launch.ts +1 -1
- package/server/parsers/event-parser.ts +4 -1
- package/server/project-context.ts +26 -10
- package/server/project-manager.ts +5 -6
- package/server/routes/aggregate-routes.ts +968 -0
- package/server/routes/config-routes.ts +41 -81
- package/server/routes/data-routes.ts +7 -16
- package/server/routes/dispatch-routes.ts +29 -8
- package/server/routes/manifest-routes.ts +1 -1
- package/server/routes/scope-routes.ts +12 -7
- package/server/schema.ts +1 -0
- package/server/services/batch-orchestrator.ts +18 -2
- package/server/services/config-service.ts +10 -1
- package/server/services/scope-service.ts +6 -6
- package/server/services/sprint-orchestrator.ts +24 -9
- package/server/services/sprint-service.ts +2 -2
- package/server/uninstall.ts +214 -0
- package/server/update.ts +263 -0
- package/server/utils/dispatch-utils.ts +8 -6
- package/server/utils/flag-builder.ts +56 -0
- package/server/utils/json-fields.test.ts +83 -0
- package/server/utils/json-fields.ts +14 -0
- package/server/utils/route-helpers.test.ts +144 -0
- package/server/utils/route-helpers.ts +38 -0
- package/server/watchers/event-watcher.ts +24 -12
- package/server/wizard/config-editor.ts +4 -4
- package/server/wizard/doctor.ts +2 -2
- package/server/wizard/index.ts +291 -40
- package/server/wizard/phases/welcome.ts +1 -5
- package/server/wizard/ui.ts +6 -7
- package/shared/api-types.ts +106 -0
- package/shared/workflow-engine.ts +1 -1
- package/templates/agents/QUICK-REFERENCE.md +1 -0
- package/templates/agents/README.md +1 -0
- package/templates/agents/SKILL-TRIGGERS.md +11 -0
- package/templates/agents/green-team/deep-dive.md +361 -0
- package/templates/hooks/end-session.sh +1 -0
- package/templates/hooks/init-session.sh +1 -0
- package/templates/hooks/scope-commit-logger.sh +2 -2
- package/templates/hooks/scope-create-gate.sh +2 -4
- package/templates/hooks/scope-gate.sh +4 -6
- package/templates/hooks/scope-helpers.sh +10 -1
- package/templates/hooks/scope-lifecycle-gate.sh +14 -5
- package/templates/hooks/scope-prepare.sh +1 -1
- package/templates/hooks/scope-transition.sh +14 -6
- package/templates/hooks/time-tracker.sh +2 -5
- package/templates/orbital.config.json +1 -4
- package/templates/presets/development.json +4 -4
- package/templates/presets/gitflow.json +7 -0
- package/templates/prompts/README.md +23 -0
- package/templates/prompts/deep-dive-audit.md +94 -0
- package/templates/quick/rules.md +56 -5
- package/templates/skills/git-commit/SKILL.md +21 -6
- package/templates/skills/git-dev/SKILL.md +8 -4
- package/templates/skills/git-main/SKILL.md +8 -4
- package/templates/skills/git-production/SKILL.md +6 -3
- package/templates/skills/git-staging/SKILL.md +6 -3
- package/templates/skills/scope-fix-review/SKILL.md +8 -4
- package/templates/skills/scope-implement/SKILL.md +13 -5
- package/templates/skills/scope-post-review/SKILL.md +16 -4
- package/templates/skills/scope-pre-review/SKILL.md +6 -2
- package/dist/assets/PrimitivesConfig-CrmQXYh4.js +0 -32
- package/dist/assets/QualityGates-BbasOsF3.js +0 -21
- package/dist/assets/SessionTimeline-CGeJsVvy.js +0 -1
- package/dist/assets/Settings-oiM496mc.js +0 -12
- package/dist/assets/SourceControl-B1fP2nJL.js +0 -41
- package/dist/assets/WorkflowVisualizer-CWLYf-f0.js +0 -74
- package/dist/assets/formatDistanceToNow-BMqsSP44.js +0 -1
- package/dist/assets/index-Aj4sV8Al.css +0 -1
- package/dist/assets/index-Bc9dK3MW.js +0 -354
- package/dist/assets/useWorkflowEditor-BJkTX_NR.js +0 -16
- package/dist/assets/zap-DfbUoOty.js +0 -11
- package/dist/server/server/services/telemetry-service.js +0 -143
- package/server/services/telemetry-service.ts +0 -195
- /package/{shared/default-workflow.json → templates/presets/default.json} +0 -0
|
@@ -2,4 +2,83 @@
|
|
|
2
2
|
//
|
|
3
3
|
// Types shared between server and client. Single source of truth for
|
|
4
4
|
// enums/unions that were previously duplicated across layers.
|
|
5
|
-
export {
|
|
5
|
+
export const DEFAULT_DISPATCH_FLAGS = {
|
|
6
|
+
permissionMode: 'bypass',
|
|
7
|
+
verbose: true,
|
|
8
|
+
allowedTools: [],
|
|
9
|
+
disallowedTools: [],
|
|
10
|
+
appendSystemPrompt: '',
|
|
11
|
+
outputFormat: '',
|
|
12
|
+
noMarkdown: false,
|
|
13
|
+
printMode: false,
|
|
14
|
+
};
|
|
15
|
+
export const DEFAULT_DISPATCH_CONFIG = {
|
|
16
|
+
staleTimeoutMinutes: 10,
|
|
17
|
+
maxBatchSize: 20,
|
|
18
|
+
maxConcurrent: 0,
|
|
19
|
+
envVars: {},
|
|
20
|
+
};
|
|
21
|
+
// ─── Validation ─────────────────────────────────────────────
|
|
22
|
+
export const VALID_PERMISSION_MODES = ['bypass', 'default', 'plan', 'acceptEdits'];
|
|
23
|
+
export const VALID_OUTPUT_FORMATS = ['', 'text', 'json', 'stream-json'];
|
|
24
|
+
export const VALID_TERMINAL_ADAPTERS = ['auto', 'iterm2', 'subprocess', 'none'];
|
|
25
|
+
const SAFE_TOOL_NAME = /^[a-zA-Z0-9_:.-]+$/;
|
|
26
|
+
const SAFE_ENV_KEY = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
27
|
+
export function validateToolName(name) {
|
|
28
|
+
return SAFE_TOOL_NAME.test(name);
|
|
29
|
+
}
|
|
30
|
+
export function validateEnvKey(key) {
|
|
31
|
+
return SAFE_ENV_KEY.test(key);
|
|
32
|
+
}
|
|
33
|
+
export function validateDispatchFlags(flags) {
|
|
34
|
+
if (flags.permissionMode !== undefined && !VALID_PERMISSION_MODES.includes(flags.permissionMode)) {
|
|
35
|
+
return `Invalid permissionMode: ${flags.permissionMode}`;
|
|
36
|
+
}
|
|
37
|
+
if (flags.outputFormat !== undefined && !VALID_OUTPUT_FORMATS.includes(flags.outputFormat)) {
|
|
38
|
+
return `Invalid outputFormat: ${flags.outputFormat}`;
|
|
39
|
+
}
|
|
40
|
+
if (flags.allowedTools !== undefined) {
|
|
41
|
+
if (!Array.isArray(flags.allowedTools))
|
|
42
|
+
return 'allowedTools must be an array';
|
|
43
|
+
for (const t of flags.allowedTools) {
|
|
44
|
+
if (typeof t !== 'string' || !validateToolName(t))
|
|
45
|
+
return `Invalid tool name: ${t}`;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (flags.disallowedTools !== undefined) {
|
|
49
|
+
if (!Array.isArray(flags.disallowedTools))
|
|
50
|
+
return 'disallowedTools must be an array';
|
|
51
|
+
for (const t of flags.disallowedTools) {
|
|
52
|
+
if (typeof t !== 'string' || !validateToolName(t))
|
|
53
|
+
return `Invalid tool name: ${t}`;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (flags.appendSystemPrompt !== undefined && typeof flags.appendSystemPrompt !== 'string') {
|
|
57
|
+
return 'appendSystemPrompt must be a string';
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
export function validateDispatchConfig(config) {
|
|
62
|
+
if (config.terminalAdapter !== undefined && !VALID_TERMINAL_ADAPTERS.includes(config.terminalAdapter)) {
|
|
63
|
+
return `Invalid terminalAdapter: ${config.terminalAdapter}`;
|
|
64
|
+
}
|
|
65
|
+
if (config.staleTimeoutMinutes !== undefined && (typeof config.staleTimeoutMinutes !== 'number' || config.staleTimeoutMinutes < 1)) {
|
|
66
|
+
return 'staleTimeoutMinutes must be a positive number';
|
|
67
|
+
}
|
|
68
|
+
if (config.maxBatchSize !== undefined && (typeof config.maxBatchSize !== 'number' || config.maxBatchSize < 1)) {
|
|
69
|
+
return 'maxBatchSize must be a positive number';
|
|
70
|
+
}
|
|
71
|
+
if (config.maxConcurrent !== undefined && (typeof config.maxConcurrent !== 'number' || config.maxConcurrent < 0)) {
|
|
72
|
+
return 'maxConcurrent must be a non-negative number';
|
|
73
|
+
}
|
|
74
|
+
if (config.envVars !== undefined) {
|
|
75
|
+
if (typeof config.envVars !== 'object' || config.envVars === null || Array.isArray(config.envVars)) {
|
|
76
|
+
return 'envVars must be an object';
|
|
77
|
+
}
|
|
78
|
+
for (const key of Object.keys(config.envVars)) {
|
|
79
|
+
if (!validateEnvKey(key))
|
|
80
|
+
return `Invalid env var key: ${key}`;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
@@ -313,7 +313,7 @@ export class WorkflowEngine {
|
|
|
313
313
|
continue;
|
|
314
314
|
// Generate aliases for deployment-group targets (dev, staging, production)
|
|
315
315
|
const group = targetList.group;
|
|
316
|
-
if (group
|
|
316
|
+
if (group?.startsWith('deploy')) {
|
|
317
317
|
const sessionKey = targetList.sessionKey ?? '';
|
|
318
318
|
lines.push(` "to-${edge.to}:${edge.from}:${edge.to}:${sessionKey}"`);
|
|
319
319
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "orbital-command",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Orbital Command — mission control dashboard for Claude Code projects",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -47,8 +47,10 @@
|
|
|
47
47
|
"build": "./node_modules/.bin/vite build",
|
|
48
48
|
"build:server": "./node_modules/.bin/tsc -p tsconfig.server.json",
|
|
49
49
|
"typecheck": "./node_modules/.bin/tsc --noEmit && ./node_modules/.bin/tsc --noEmit -p tsconfig.server.json",
|
|
50
|
+
"validate": "npm run typecheck && npm run test && npm run build && npm run build:server",
|
|
51
|
+
"release": "./scripts/release.sh",
|
|
50
52
|
"postinstall": "node scripts/postinstall.js",
|
|
51
|
-
"prepublishOnly": "npm run
|
|
53
|
+
"prepublishOnly": "npm run validate",
|
|
52
54
|
"preview": "vite preview",
|
|
53
55
|
"test": "vitest run",
|
|
54
56
|
"test:unit": "vitest run --project unit",
|
|
@@ -58,31 +60,38 @@
|
|
|
58
60
|
},
|
|
59
61
|
"dependencies": {
|
|
60
62
|
"@clack/prompts": "^1.2.0",
|
|
63
|
+
"better-sqlite3": "^12.0.0",
|
|
64
|
+
"chokidar": "^4.0.3",
|
|
65
|
+
"express": "^4.21.2",
|
|
66
|
+
"gray-matter": "^4.0.3",
|
|
67
|
+
"picocolors": "^1.1.1",
|
|
68
|
+
"socket.io": "^4.8.1"
|
|
69
|
+
},
|
|
70
|
+
"devDependencies": {
|
|
61
71
|
"@dnd-kit/core": "^6.3.1",
|
|
62
72
|
"@dnd-kit/sortable": "^10.0.0",
|
|
63
73
|
"@dnd-kit/utilities": "^3.2.2",
|
|
64
74
|
"@radix-ui/react-dialog": "^1.1.4",
|
|
65
|
-
"@radix-ui/react-dropdown-menu": "^2.1.4",
|
|
66
75
|
"@radix-ui/react-popover": "^1.1.15",
|
|
67
76
|
"@radix-ui/react-scroll-area": "^1.2.2",
|
|
68
|
-
"@radix-ui/react-select": "^2.1.4",
|
|
69
77
|
"@radix-ui/react-separator": "^1.1.1",
|
|
70
78
|
"@radix-ui/react-slot": "^1.1.1",
|
|
71
79
|
"@radix-ui/react-tabs": "^1.1.2",
|
|
72
80
|
"@radix-ui/react-tooltip": "^1.1.6",
|
|
81
|
+
"@types/better-sqlite3": "^7.6.12",
|
|
82
|
+
"@types/express": "^5.0.0",
|
|
83
|
+
"@types/react": "^18.3.18",
|
|
84
|
+
"@types/react-dom": "^18.3.5",
|
|
85
|
+
"@types/supertest": "^7.2.0",
|
|
73
86
|
"@vitejs/plugin-react": "^4.7.0",
|
|
74
87
|
"@xyflow/react": "^12.10.1",
|
|
75
88
|
"autoprefixer": "^10.4.27",
|
|
76
|
-
"better-sqlite3": "^12.0.0",
|
|
77
|
-
"chokidar": "^4.0.3",
|
|
78
89
|
"class-variance-authority": "^0.7.1",
|
|
79
90
|
"clsx": "^2.1.1",
|
|
91
|
+
"concurrently": "^9.2.1",
|
|
80
92
|
"date-fns": "^4.1.0",
|
|
81
|
-
"express": "^4.21.2",
|
|
82
93
|
"framer-motion": "^11.15.0",
|
|
83
|
-
"gray-matter": "^4.0.3",
|
|
84
94
|
"lucide-react": "^0.577.0",
|
|
85
|
-
"picocolors": "^1.1.1",
|
|
86
95
|
"postcss": "^8.5.8",
|
|
87
96
|
"react": "^18.3.1",
|
|
88
97
|
"react-dom": "^18.3.1",
|
|
@@ -90,23 +99,14 @@
|
|
|
90
99
|
"react-router-dom": "^6.30.2",
|
|
91
100
|
"recharts": "^2.15.0",
|
|
92
101
|
"remark-gfm": "^4.0.1",
|
|
93
|
-
"socket.io": "^4.8.1",
|
|
94
102
|
"socket.io-client": "^4.8.1",
|
|
103
|
+
"supertest": "^7.2.2",
|
|
95
104
|
"tailwind-merge": "^2.6.0",
|
|
96
105
|
"tailwindcss": "^3.4.19",
|
|
97
106
|
"tailwindcss-animate": "^1.0.7",
|
|
98
107
|
"tsx": "^4.19.2",
|
|
99
|
-
"vite": "^6.0.7"
|
|
100
|
-
},
|
|
101
|
-
"devDependencies": {
|
|
102
|
-
"@types/better-sqlite3": "^7.6.12",
|
|
103
|
-
"@types/express": "^5.0.0",
|
|
104
|
-
"@types/react": "^18.3.18",
|
|
105
|
-
"@types/react-dom": "^18.3.5",
|
|
106
|
-
"@types/supertest": "^7.2.0",
|
|
107
|
-
"concurrently": "^9.2.1",
|
|
108
|
-
"supertest": "^7.2.2",
|
|
109
108
|
"typescript": "^5.7.3",
|
|
109
|
+
"vite": "^6.0.7",
|
|
110
110
|
"vitest": "^4.1.3"
|
|
111
111
|
},
|
|
112
112
|
"engines": {
|
|
@@ -35,10 +35,7 @@
|
|
|
35
35
|
"typeCheck": { "type": ["string", "null"], "default": null },
|
|
36
36
|
"lint": { "type": ["string", "null"], "default": null },
|
|
37
37
|
"build": { "type": ["string", "null"], "default": null },
|
|
38
|
-
"test": { "type": ["string", "null"], "default": null }
|
|
39
|
-
"validateTemplates": { "type": ["string", "null"], "default": null },
|
|
40
|
-
"validateDocs": { "type": ["string", "null"], "default": null },
|
|
41
|
-
"checkRules": { "type": ["string", "null"], "default": null }
|
|
38
|
+
"test": { "type": ["string", "null"], "default": null }
|
|
42
39
|
},
|
|
43
40
|
"additionalProperties": false
|
|
44
41
|
},
|
|
@@ -77,21 +74,6 @@
|
|
|
77
74
|
"production": { "type": "string", "format": "uri" }
|
|
78
75
|
},
|
|
79
76
|
"additionalProperties": { "type": "string", "format": "uri" }
|
|
80
|
-
},
|
|
81
|
-
"telemetry": {
|
|
82
|
-
"type": "object",
|
|
83
|
-
"description": "Session telemetry — uploads Claude session JSONL files to a remote endpoint. Can also be disabled via ORBITAL_TELEMETRY=false env var.",
|
|
84
|
-
"properties": {
|
|
85
|
-
"enabled": { "type": "boolean", "default": true, "description": "Enable session telemetry upload" },
|
|
86
|
-
"url": { "type": "string", "description": "Base URL of the telemetry receiver (Cloudflare Worker)" },
|
|
87
|
-
"headers": {
|
|
88
|
-
"type": "object",
|
|
89
|
-
"additionalProperties": { "type": "string" },
|
|
90
|
-
"default": {},
|
|
91
|
-
"description": "Custom headers sent with upload requests (e.g. Authorization)"
|
|
92
|
-
}
|
|
93
|
-
},
|
|
94
|
-
"additionalProperties": false
|
|
95
77
|
}
|
|
96
78
|
},
|
|
97
79
|
"additionalProperties": false
|
package/scripts/postinstall.js
CHANGED
|
@@ -9,14 +9,13 @@
|
|
|
9
9
|
* 3. Otherwise, prints a banner with next steps.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import { existsSync
|
|
12
|
+
import { existsSync } from 'fs';
|
|
13
13
|
import { execFileSync } from 'child_process';
|
|
14
14
|
import path from 'path';
|
|
15
15
|
import { fileURLToPath } from 'url';
|
|
16
16
|
|
|
17
17
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
18
18
|
const packageRoot = path.resolve(__dirname, '..');
|
|
19
|
-
const orbitalHome = path.join(process.env.HOME || process.env.USERPROFILE || '~', '.orbital');
|
|
20
19
|
|
|
21
20
|
// ─── 1. Esbuild safety net ─────────────────────────────────────
|
|
22
21
|
|
|
@@ -29,44 +28,9 @@ if (existsSync(esbuildInstall)) {
|
|
|
29
28
|
}
|
|
30
29
|
}
|
|
31
30
|
|
|
32
|
-
// ─── 2.
|
|
31
|
+
// ─── 2. Post-install banner ─────────────────────────────────────
|
|
33
32
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
// Launch the Phase 1 setup wizard
|
|
39
|
-
try {
|
|
40
|
-
const pkg = JSON.parse(readFileSync(path.join(packageRoot, 'package.json'), 'utf8'));
|
|
41
|
-
const version = pkg.version || '0.0.0';
|
|
42
|
-
|
|
43
|
-
let wizard;
|
|
44
|
-
try {
|
|
45
|
-
wizard = await import('../dist/server/server/wizard/index.js');
|
|
46
|
-
} catch {
|
|
47
|
-
try {
|
|
48
|
-
wizard = await import('../server/wizard/index.js');
|
|
49
|
-
} catch {
|
|
50
|
-
// Wizard module not available — fall through to banner
|
|
51
|
-
wizard = null;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
if (wizard) {
|
|
56
|
-
await wizard.runSetupWizard(version);
|
|
57
|
-
} else {
|
|
58
|
-
printBanner();
|
|
59
|
-
}
|
|
60
|
-
} catch {
|
|
61
|
-
printBanner();
|
|
62
|
-
}
|
|
63
|
-
} else if (!alreadySetUp) {
|
|
64
|
-
printBanner();
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function printBanner() {
|
|
68
|
-
console.log('');
|
|
69
|
-
console.log(' Orbital Command installed.');
|
|
70
|
-
console.log(' Run `orbital` in your project directory to get started.');
|
|
71
|
-
console.log('');
|
|
72
|
-
}
|
|
33
|
+
console.log('');
|
|
34
|
+
console.log(' Orbital Command installed.');
|
|
35
|
+
console.log(' Run \x1b[36morbital\x1b[0m in your project directory to get started.');
|
|
36
|
+
console.log('');
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Release Orbital Command
|
|
3
|
+
# Usage: ./scripts/release.sh [patch|minor|major]
|
|
4
|
+
#
|
|
5
|
+
# Runs the full validation pipeline, bumps version, tags, and pushes.
|
|
6
|
+
# The tag push triggers publish.yml which publishes to npm.
|
|
7
|
+
|
|
8
|
+
set -e
|
|
9
|
+
|
|
10
|
+
BUMP="${1:-patch}"
|
|
11
|
+
|
|
12
|
+
if [[ "$BUMP" != "patch" && "$BUMP" != "minor" && "$BUMP" != "major" ]]; then
|
|
13
|
+
echo "Usage: ./scripts/release.sh [patch|minor|major]"
|
|
14
|
+
echo " Default: patch"
|
|
15
|
+
exit 1
|
|
16
|
+
fi
|
|
17
|
+
|
|
18
|
+
# Ensure clean working tree
|
|
19
|
+
if [[ -n "$(git status --porcelain)" ]]; then
|
|
20
|
+
echo "Error: working tree is dirty. Commit or stash changes first."
|
|
21
|
+
exit 1
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
# Ensure we're on main
|
|
25
|
+
BRANCH="$(git branch --show-current)"
|
|
26
|
+
if [[ "$BRANCH" != "main" ]]; then
|
|
27
|
+
echo "Error: releases must be cut from main (currently on $BRANCH)"
|
|
28
|
+
exit 1
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
# Pull latest
|
|
32
|
+
echo "Pulling latest from origin/main..."
|
|
33
|
+
git pull --ff-only origin main
|
|
34
|
+
|
|
35
|
+
# Validate
|
|
36
|
+
echo ""
|
|
37
|
+
echo "Running full validation pipeline..."
|
|
38
|
+
echo ""
|
|
39
|
+
npm run validate
|
|
40
|
+
|
|
41
|
+
# Bump version and create tag
|
|
42
|
+
echo ""
|
|
43
|
+
echo "Bumping $BUMP version..."
|
|
44
|
+
npm version "$BUMP"
|
|
45
|
+
|
|
46
|
+
# Push commit and tag
|
|
47
|
+
echo ""
|
|
48
|
+
echo "Pushing to origin..."
|
|
49
|
+
git push origin main --follow-tags
|
|
50
|
+
|
|
51
|
+
VERSION="$(node -p "require('./package.json').version")"
|
|
52
|
+
echo ""
|
|
53
|
+
echo "Released v$VERSION — publish.yml will handle npm publish."
|
|
@@ -9,6 +9,7 @@ import { WorkflowEngine } from '../../shared/workflow-engine.js';
|
|
|
9
9
|
import { createTestDb } from './helpers/db.js';
|
|
10
10
|
import { createMockEmitter } from './helpers/mock-emitter.js';
|
|
11
11
|
import { DEFAULT_CONFIG } from '../../shared/__fixtures__/workflow-configs.js';
|
|
12
|
+
import { loadConfig } from '../config.js';
|
|
12
13
|
import type Database from 'better-sqlite3';
|
|
13
14
|
|
|
14
15
|
describe('data-routes', () => {
|
|
@@ -42,6 +43,7 @@ describe('data-routes', () => {
|
|
|
42
43
|
engine,
|
|
43
44
|
projectRoot: '/tmp/test-project',
|
|
44
45
|
inferScopeStatus: vi.fn(),
|
|
46
|
+
config: loadConfig('/tmp/test-project'),
|
|
45
47
|
});
|
|
46
48
|
|
|
47
49
|
app = express();
|
|
@@ -69,6 +69,7 @@ describe('scope-routes', () => {
|
|
|
69
69
|
projectRoot: '/tmp/test-project',
|
|
70
70
|
projectName: 'Test',
|
|
71
71
|
engine,
|
|
72
|
+
config: { claude: { dispatchFlags: { permissionMode: 'bypass', verbose: false, noMarkdown: false, printMode: false, outputFormat: null, allowedTools: [], disallowedTools: [], appendSystemPrompt: '' } }, dispatch: { envVars: {}, maxConcurrent: 5, maxBatchSize: 20, staleTimeoutMinutes: 10 } } as any,
|
|
72
73
|
});
|
|
73
74
|
|
|
74
75
|
app = express();
|
package/server/config.ts
CHANGED
|
@@ -14,6 +14,7 @@ export interface TerminalConfig {
|
|
|
14
14
|
export interface ClaudeConfig {
|
|
15
15
|
executable: string;
|
|
16
16
|
flags: string[];
|
|
17
|
+
dispatchFlags: DispatchFlags;
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
export interface CommandsConfig {
|
|
@@ -21,13 +22,12 @@ export interface CommandsConfig {
|
|
|
21
22
|
lint: string | null;
|
|
22
23
|
build: string | null;
|
|
23
24
|
test: string | null;
|
|
24
|
-
validateTemplates: string | null;
|
|
25
|
-
validateDocs: string | null;
|
|
26
|
-
checkRules: string | null;
|
|
27
25
|
}
|
|
28
26
|
|
|
29
|
-
export type { AgentConfig } from '../shared/api-types.js';
|
|
30
|
-
import type { AgentConfig } from '../shared/api-types.js';
|
|
27
|
+
export type { AgentConfig, DispatchFlags, DispatchConfig } from '../shared/api-types.js';
|
|
28
|
+
import type { AgentConfig, DispatchFlags, DispatchConfig } from '../shared/api-types.js';
|
|
29
|
+
import { DEFAULT_DISPATCH_FLAGS, DEFAULT_DISPATCH_CONFIG } from '../shared/api-types.js';
|
|
30
|
+
import { loadGlobalConfig as loadGlobal } from './global-config.js';
|
|
31
31
|
|
|
32
32
|
export interface TelemetryConfig {
|
|
33
33
|
enabled: boolean;
|
|
@@ -55,6 +55,9 @@ export interface OrbitalConfig {
|
|
|
55
55
|
// Claude Code CLI
|
|
56
56
|
claude: ClaudeConfig;
|
|
57
57
|
|
|
58
|
+
// Dispatch operational settings
|
|
59
|
+
dispatch: DispatchConfig;
|
|
60
|
+
|
|
58
61
|
// Build/test commands
|
|
59
62
|
commands: CommandsConfig;
|
|
60
63
|
|
|
@@ -86,19 +89,18 @@ const DEFAULT_CONFIG: Omit<OrbitalConfig, 'projectRoot'> = {
|
|
|
86
89
|
claude: {
|
|
87
90
|
executable: 'claude',
|
|
88
91
|
flags: ['--dangerously-skip-permissions'],
|
|
92
|
+
dispatchFlags: DEFAULT_DISPATCH_FLAGS,
|
|
89
93
|
},
|
|
94
|
+
dispatch: DEFAULT_DISPATCH_CONFIG,
|
|
90
95
|
commands: {
|
|
91
96
|
typeCheck: null,
|
|
92
97
|
lint: null,
|
|
93
98
|
build: null,
|
|
94
99
|
test: null,
|
|
95
|
-
validateTemplates: null,
|
|
96
|
-
validateDocs: null,
|
|
97
|
-
checkRules: null,
|
|
98
100
|
},
|
|
99
101
|
logLevel: 'info' as const,
|
|
100
102
|
telemetry: {
|
|
101
|
-
enabled:
|
|
103
|
+
enabled: false,
|
|
102
104
|
url: '',
|
|
103
105
|
headers: {},
|
|
104
106
|
},
|
|
@@ -106,7 +108,6 @@ const DEFAULT_CONFIG: Omit<OrbitalConfig, 'projectRoot'> = {
|
|
|
106
108
|
agents: [
|
|
107
109
|
{ id: 'attacker', label: 'Attacker', emoji: '\u{1F5E1}\u{FE0F}', color: '#ff1744' },
|
|
108
110
|
{ id: 'chaos', label: 'Chaos', emoji: '\u{1F4A5}', color: '#F97316' },
|
|
109
|
-
{ id: 'solana-expert', label: 'Solana Expert', emoji: '\u{26D3}\u{FE0F}', color: '#8B5CF6' },
|
|
110
111
|
{ id: 'frontend-designer', label: 'Frontend Designer', emoji: '\u{1F3A8}', color: '#EC4899' },
|
|
111
112
|
{ id: 'architect', label: 'Architect', emoji: '\u{1F3D7}\u{FE0F}', color: '#536dfe' },
|
|
112
113
|
{ id: 'rules-enforcer', label: 'Rules Enforcer', emoji: '\u{1F4CB}', color: '#6B7280' },
|
|
@@ -168,6 +169,15 @@ export function getClaudeSessionsDir(projectRoot: string): string {
|
|
|
168
169
|
export function loadConfig(projectRoot?: string): OrbitalConfig {
|
|
169
170
|
const root = projectRoot ?? resolveProjectRoot();
|
|
170
171
|
|
|
172
|
+
// Try loading edition overrides (e.g. edition.json at repo root)
|
|
173
|
+
const editionPath = path.join(root, 'edition.json');
|
|
174
|
+
let editionConfig: Record<string, unknown> = {};
|
|
175
|
+
if (fs.existsSync(editionPath)) {
|
|
176
|
+
try {
|
|
177
|
+
editionConfig = JSON.parse(fs.readFileSync(editionPath, 'utf-8'));
|
|
178
|
+
} catch { /* malformed edition.json — ignore */ }
|
|
179
|
+
}
|
|
180
|
+
|
|
171
181
|
// Try loading user config
|
|
172
182
|
const configPath = path.join(root, '.claude', 'orbital.config.json');
|
|
173
183
|
let userConfig: Record<string, unknown> = {};
|
|
@@ -201,11 +211,26 @@ export function loadConfig(projectRoot?: string): OrbitalConfig {
|
|
|
201
211
|
...(userConfig.terminal as Partial<TerminalConfig> ?? {}),
|
|
202
212
|
};
|
|
203
213
|
|
|
214
|
+
// Global settings — seed from ~/.orbital/config.json
|
|
215
|
+
let globalDispatchFlags = DEFAULT_DISPATCH_FLAGS;
|
|
216
|
+
let globalDispatch = DEFAULT_DISPATCH_CONFIG;
|
|
217
|
+
let globalTelemetry: Partial<TelemetryConfig> = {};
|
|
218
|
+
try {
|
|
219
|
+
const global = loadGlobal();
|
|
220
|
+
if (global.dispatchFlags) globalDispatchFlags = { ...DEFAULT_DISPATCH_FLAGS, ...global.dispatchFlags };
|
|
221
|
+
if (global.dispatch) globalDispatch = { ...DEFAULT_DISPATCH_CONFIG, ...global.dispatch };
|
|
222
|
+
if (global.telemetry) globalTelemetry = global.telemetry;
|
|
223
|
+
} catch { /* global config may not exist yet */ }
|
|
224
|
+
|
|
225
|
+
const userClaude = (userConfig.claude as Partial<ClaudeConfig>) ?? {};
|
|
204
226
|
const claude: ClaudeConfig = {
|
|
205
227
|
...DEFAULT_CONFIG.claude,
|
|
206
|
-
...
|
|
228
|
+
...userClaude,
|
|
229
|
+
dispatchFlags: globalDispatchFlags,
|
|
207
230
|
};
|
|
208
231
|
|
|
232
|
+
const dispatch: DispatchConfig = globalDispatch;
|
|
233
|
+
|
|
209
234
|
const commands: CommandsConfig = {
|
|
210
235
|
...DEFAULT_CONFIG.commands,
|
|
211
236
|
...(userConfig.commands as Partial<CommandsConfig> ?? {}),
|
|
@@ -217,6 +242,8 @@ export function loadConfig(projectRoot?: string): OrbitalConfig {
|
|
|
217
242
|
|
|
218
243
|
const telemetry: TelemetryConfig = {
|
|
219
244
|
...DEFAULT_CONFIG.telemetry,
|
|
245
|
+
...globalTelemetry,
|
|
246
|
+
...(editionConfig.telemetry as Partial<TelemetryConfig> ?? {}),
|
|
220
247
|
...(userConfig.telemetry as Partial<TelemetryConfig> ?? {}),
|
|
221
248
|
};
|
|
222
249
|
if (process.env.ORBITAL_TELEMETRY === 'false') telemetry.enabled = false;
|
|
@@ -232,6 +259,7 @@ export function loadConfig(projectRoot?: string): OrbitalConfig {
|
|
|
232
259
|
clientPort,
|
|
233
260
|
terminal,
|
|
234
261
|
claude,
|
|
262
|
+
dispatch,
|
|
235
263
|
commands,
|
|
236
264
|
logLevel,
|
|
237
265
|
categories,
|
package/server/database.ts
CHANGED
|
@@ -2,7 +2,6 @@ import Database from 'better-sqlite3';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import fs from 'fs';
|
|
4
4
|
import { SCHEMA_DDL } from './schema.js';
|
|
5
|
-
import { getConfig } from './config.js';
|
|
6
5
|
import { createLogger } from './utils/logger.js';
|
|
7
6
|
|
|
8
7
|
const log = createLogger('database');
|
|
@@ -14,7 +13,6 @@ const log = createLogger('database');
|
|
|
14
13
|
* Creates the directory if needed, applies schema DDL and migrations.
|
|
15
14
|
*
|
|
16
15
|
* Each call returns a NEW connection — callers manage their own lifecycle.
|
|
17
|
-
* This is the multi-project replacement for the getDatabase() singleton.
|
|
18
16
|
*/
|
|
19
17
|
export function openProjectDatabase(dbDir: string): Database.Database {
|
|
20
18
|
fs.mkdirSync(dbDir, { recursive: true });
|
|
@@ -33,22 +31,6 @@ export function openProjectDatabase(dbDir: string): Database.Database {
|
|
|
33
31
|
return database;
|
|
34
32
|
}
|
|
35
33
|
|
|
36
|
-
// ─── Singleton (backward compat, used by index.ts) ──────────
|
|
37
|
-
|
|
38
|
-
function getDbPaths(): { dir: string; file: string } {
|
|
39
|
-
const config = getConfig();
|
|
40
|
-
return { dir: config.dbDir, file: path.join(config.dbDir, 'orbital.db') };
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
let db: Database.Database | null = null;
|
|
44
|
-
|
|
45
|
-
/** @deprecated Use openProjectDatabase() for multi-project support. */
|
|
46
|
-
export function getDatabase(): Database.Database {
|
|
47
|
-
if (db) return db;
|
|
48
|
-
db = openProjectDatabase(getDbPaths().dir);
|
|
49
|
-
return db;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
34
|
/** Check if a table exists in the database */
|
|
53
35
|
function tableExists(database: Database.Database, tableName: string): boolean {
|
|
54
36
|
const row = database.prepare(
|
|
@@ -114,11 +96,3 @@ function runMigrations(database: Database.Database): void {
|
|
|
114
96
|
`);
|
|
115
97
|
}
|
|
116
98
|
}
|
|
117
|
-
|
|
118
|
-
export function closeDatabase(): void {
|
|
119
|
-
if (db) {
|
|
120
|
-
db.close();
|
|
121
|
-
db = null;
|
|
122
|
-
log.debug('Database closed');
|
|
123
|
-
}
|
|
124
|
-
}
|
package/server/global-config.ts
CHANGED
|
@@ -27,6 +27,10 @@ export interface OrbitalGlobalConfig {
|
|
|
27
27
|
version: 1;
|
|
28
28
|
projects: ProjectRegistration[];
|
|
29
29
|
privateMode?: boolean;
|
|
30
|
+
dispatchFlags?: import('../shared/api-types.js').DispatchFlags;
|
|
31
|
+
dispatch?: import('../shared/api-types.js').DispatchConfig;
|
|
32
|
+
telemetry?: import('./config.js').TelemetryConfig;
|
|
33
|
+
terminalAdapter?: string;
|
|
30
34
|
}
|
|
31
35
|
|
|
32
36
|
// ─── Constants ──────────────────────────────────────────────
|