@oxgeneral/orch 0.3.2 → 0.3.4
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/dist/App-RKAPZNZO.js +6682 -0
- package/dist/agent-KBTLGGCT.js +183 -0
- package/dist/agent-shop-YN2BSLHM.js +2 -0
- package/dist/chunk-2C2TFQ7K.js +136 -0
- package/dist/chunk-45K2XID7.js +29 -0
- package/dist/{shell-IH2MMTVP.js → chunk-52BFUGDD.js} +8 -6
- package/dist/chunk-7X2GI5OV.js +181 -0
- package/dist/{chunk-HSBYJ5C5.js → chunk-A36WAF2S.js} +89 -2
- package/dist/chunk-CHIP7O6V.js +83 -0
- package/dist/{claude-RIB3RQS5.js → chunk-D6RFF3KN.js} +12 -9
- package/dist/{chunk-BCPUTULS.js → chunk-DAVHOWGD.js} +188 -16
- package/dist/chunk-FRTKB575.js +87 -0
- package/dist/chunk-HXYAZGLP.js +15 -0
- package/dist/chunk-I3SMISEF.js +29 -0
- package/dist/chunk-K6DMQERQ.js +89 -0
- package/dist/chunk-LV6GDBBI.js +297 -0
- package/dist/chunk-NLQAJ7TW.js +147 -0
- package/dist/chunk-NLQAJ7TW.js.map +1 -0
- package/dist/chunk-P6ATSXGL.js +107 -0
- package/dist/chunk-PNE6LQRF.js +5 -0
- package/dist/{chunk-MGFMVPRD.js → chunk-S3QYSBW4.js} +11 -4
- package/dist/chunk-S3QYSBW4.js.map +1 -0
- package/dist/chunk-U2VDNUZL.js +52 -0
- package/dist/{chunk-QEEM67OA.js → chunk-UIJYU3J7.js} +3 -3
- package/dist/{chunk-QEEM67OA.js.map → chunk-UIJYU3J7.js.map} +1 -1
- package/dist/{chunk-2UC4SVJB.js → chunk-VMDQVRBR.js} +22 -8
- package/dist/chunk-VMDQVRBR.js.map +1 -0
- package/dist/chunk-W6RSVMXR.js +66 -0
- package/dist/claude-INM52PTH.js +88 -0
- package/dist/claude-INM52PTH.js.map +1 -0
- package/dist/claude-NHUNA5RZ.js +5 -0
- package/dist/cli.js +199 -1
- package/dist/clipboard-service-RTDUUQQU.js +200 -0
- package/dist/{codex-VBUSA2GJ.js → codex-DIXT44JR.js} +17 -11
- package/dist/codex-QGH2GRV6.js +125 -0
- package/dist/codex-QGH2GRV6.js.map +1 -0
- package/dist/config-OTAVSMOD.js +75 -0
- package/dist/container-LJU4QNDH.js +1594 -0
- package/dist/context-OL4BVUV5.js +83 -0
- package/dist/{cursor-4QIOTDBW.js → cursor-C3TR2IJC.js} +11 -8
- package/dist/cursor-KQJTQ73D.js +99 -0
- package/dist/cursor-KQJTQ73D.js.map +1 -0
- package/dist/doctor-V2FPS236.js +67 -0
- package/dist/doctor-service-TPOMFAIG.js +2 -0
- package/dist/goal-FMYYN2FR.js +138 -0
- package/dist/index.d.ts +64 -41
- package/dist/index.js +23 -14
- package/dist/index.js.map +1 -1
- package/dist/init-U7MCIOB2.js +165 -0
- package/dist/logs-PHPYWQ6I.js +207 -0
- package/dist/msg-FUWWLEKM.js +95 -0
- package/dist/orchestrator-ADO66XZ3.js +5 -0
- package/dist/{orchestrator-FGGXK3N3.js.map → orchestrator-ADO66XZ3.js.map} +1 -1
- package/dist/orchestrator-E3FQ4SOE.js +1424 -0
- package/dist/process-manager-HUVNAPQV.js +2 -0
- package/dist/registry-PQWRVNF2.js +2 -0
- package/dist/run-N72G5V2H.js +95 -0
- package/dist/shell-3S4VLYEG.js +4 -0
- package/dist/shell-JXOPKDXH.js +221 -0
- package/dist/shell-JXOPKDXH.js.map +1 -0
- package/dist/shop-picker-2HY67UWP.js +79 -0
- package/dist/status-RZWN2C6C.js +56 -0
- package/dist/task-2TJW6Z7O.js +221 -0
- package/dist/team-PFLP4PPL.js +97 -0
- package/dist/template-engine-4IZKRRHG.js +3 -0
- package/dist/tui-IM3YUUVD.js +245 -0
- package/dist/update-YLP7FPNY.js +64 -0
- package/dist/update-check-4YKLGBFB.js +2 -0
- package/dist/{workspace-manager-T6AXG7XL.js → workspace-manager-EVD67GCG.js} +4 -4
- package/dist/{workspace-manager-T6AXG7XL.js.map → workspace-manager-EVD67GCG.js.map} +1 -1
- package/dist/workspace-manager-JM6U7JOH.js +215 -0
- package/package.json +1 -1
- package/readme.md +9 -2
- package/scripts/postinstall.js +44 -2
- package/dist/App-YJM5QGP7.js +0 -19
- package/dist/agent-S4DKSX63.js +0 -9
- package/dist/agent-shop-D2RS4BZK.js +0 -2
- package/dist/chunk-2UC4SVJB.js.map +0 -1
- package/dist/chunk-5AJ4LYO5.js +0 -8
- package/dist/chunk-6MJ7V6VY.js +0 -2
- package/dist/chunk-CDFA4IIQ.js +0 -2
- package/dist/chunk-CHRW4CLD.js +0 -2
- package/dist/chunk-GZ2Q56YZ.js +0 -2
- package/dist/chunk-HMMPM7MF.js +0 -3
- package/dist/chunk-HXOMNULD.js +0 -2
- package/dist/chunk-IQXRQBUK.js +0 -83
- package/dist/chunk-IQXRQBUK.js.map +0 -1
- package/dist/chunk-L26TK7Y5.js +0 -2
- package/dist/chunk-L3FYR45M.js +0 -2
- package/dist/chunk-LXNRCJ22.js +0 -2
- package/dist/chunk-MGFMVPRD.js.map +0 -1
- package/dist/chunk-MNXU3KCD.js +0 -2
- package/dist/chunk-PJ5DKXGR.js +0 -2
- package/dist/chunk-UMZEA3JT.js +0 -5
- package/dist/chunk-UW6GUUE6.js +0 -3
- package/dist/chunk-ZA5Z33GO.js +0 -11
- package/dist/claude-E36EGXUV.js +0 -2
- package/dist/claude-RIB3RQS5.js.map +0 -1
- package/dist/clipboard-service-PDTSZIR5.js +0 -25
- package/dist/codex-OTZKVESD.js +0 -2
- package/dist/codex-VBUSA2GJ.js.map +0 -1
- package/dist/config-CCSS2P7R.js +0 -2
- package/dist/container-OIXLFSX2.js +0 -6
- package/dist/context-GSMQHQES.js +0 -7
- package/dist/cursor-3DJA6LWS.js +0 -2
- package/dist/cursor-4QIOTDBW.js.map +0 -1
- package/dist/doctor-KBK5JZBZ.js +0 -2
- package/dist/doctor-service-PB7YBH3F.js +0 -2
- package/dist/goal-RFKFPR7M.js +0 -8
- package/dist/init-WRDFAFS2.js +0 -53
- package/dist/logs-5QHJWMEG.js +0 -12
- package/dist/msg-4SCLBO4K.js +0 -9
- package/dist/orchestrator-FGGXK3N3.js +0 -5
- package/dist/orchestrator-R7IWZUT6.js +0 -13
- package/dist/process-manager-33H27MQF.js +0 -2
- package/dist/registry-BO2PPRNG.js +0 -2
- package/dist/run-HSHRELOP.js +0 -3
- package/dist/shell-EOJBDWTH.js +0 -2
- package/dist/shell-IH2MMTVP.js.map +0 -1
- package/dist/shop-picker-LE3SKFOX.js +0 -5
- package/dist/status-DLBNWSWM.js +0 -2
- package/dist/task-J6ZN7ALI.js +0 -20
- package/dist/team-MSIBKOQC.js +0 -4
- package/dist/template-engine-ONIDVD4F.js +0 -2
- package/dist/tui-LW7WIDE3.js +0 -2
- package/dist/update-PC2ENCKU.js +0 -2
- package/dist/update-check-HGMBDYHL.js +0 -2
- package/dist/workspace-manager-KOOYTO7E.js +0 -3
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawn } from 'child_process';
|
|
3
|
+
|
|
4
|
+
var ProcessManager = class {
|
|
5
|
+
isAlive(pid) {
|
|
6
|
+
try {
|
|
7
|
+
process.kill(pid, 0);
|
|
8
|
+
return true;
|
|
9
|
+
} catch (err) {
|
|
10
|
+
if (err.code === "EPERM") return true;
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
kill(pid, signal = "SIGTERM") {
|
|
15
|
+
try {
|
|
16
|
+
process.kill(-pid, signal);
|
|
17
|
+
} catch {
|
|
18
|
+
try {
|
|
19
|
+
process.kill(pid, signal);
|
|
20
|
+
} catch {
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
async killWithGrace(pid, graceMs = 1e4) {
|
|
25
|
+
if (!this.isAlive(pid)) return;
|
|
26
|
+
this.kill(pid, "SIGTERM");
|
|
27
|
+
const deadline = Date.now() + graceMs;
|
|
28
|
+
while (Date.now() < deadline) {
|
|
29
|
+
if (!this.isAlive(pid)) return;
|
|
30
|
+
await new Promise((r) => setTimeout(r, 200));
|
|
31
|
+
}
|
|
32
|
+
this.kill(pid, "SIGKILL");
|
|
33
|
+
}
|
|
34
|
+
spawn(command, args, options) {
|
|
35
|
+
const proc = spawn(command, args, {
|
|
36
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
37
|
+
detached: true,
|
|
38
|
+
// Create new process group so killWithGrace(-pid) kills all children
|
|
39
|
+
...options
|
|
40
|
+
});
|
|
41
|
+
if (!proc.pid) {
|
|
42
|
+
throw new Error(`Failed to spawn process: ${command}`);
|
|
43
|
+
}
|
|
44
|
+
proc.unref();
|
|
45
|
+
return { process: proc, pid: proc.pid };
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
var MAX_LINE_LEN = 16384;
|
|
49
|
+
function capLine(s) {
|
|
50
|
+
return s.length > MAX_LINE_LEN ? s.slice(0, MAX_LINE_LEN) : s;
|
|
51
|
+
}
|
|
52
|
+
async function* readLines(stream) {
|
|
53
|
+
const chunks = [];
|
|
54
|
+
let totalLen = 0;
|
|
55
|
+
for await (const chunk of stream) {
|
|
56
|
+
const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf-8");
|
|
57
|
+
if (buf.length === 0) continue;
|
|
58
|
+
chunks.push(buf);
|
|
59
|
+
totalLen += buf.length;
|
|
60
|
+
const buffer = chunks.length === 1 ? chunks[0] : Buffer.concat(chunks, totalLen);
|
|
61
|
+
chunks.length = 0;
|
|
62
|
+
totalLen = 0;
|
|
63
|
+
let offset = 0;
|
|
64
|
+
let newlineIdx;
|
|
65
|
+
while ((newlineIdx = buffer.indexOf(10, offset)) !== -1) {
|
|
66
|
+
if (newlineIdx > offset) {
|
|
67
|
+
yield capLine(buffer.toString("utf-8", offset, newlineIdx));
|
|
68
|
+
}
|
|
69
|
+
offset = newlineIdx + 1;
|
|
70
|
+
}
|
|
71
|
+
if (offset < buffer.length) {
|
|
72
|
+
const remainder = buffer.subarray(offset);
|
|
73
|
+
chunks.push(remainder);
|
|
74
|
+
totalLen = remainder.length;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (totalLen > 0) {
|
|
78
|
+
const final = chunks.length === 1 ? chunks[0] : Buffer.concat(chunks, totalLen);
|
|
79
|
+
yield capLine(final.toString("utf-8"));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export { ProcessManager, readLines };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
import './chunk-
|
|
3
|
-
import './chunk-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createStreamingEvents, extractTokens } from './chunk-W6RSVMXR.js';
|
|
3
|
+
import { classifyAdapterError } from './chunk-2C2TFQ7K.js';
|
|
4
4
|
import { execFile } from 'child_process';
|
|
5
5
|
import { promisify } from 'util';
|
|
6
6
|
|
|
@@ -14,10 +14,12 @@ var ClaudeAdapter = class {
|
|
|
14
14
|
try {
|
|
15
15
|
const { stdout } = await execFileAsync("claude", ["--version"]);
|
|
16
16
|
return { ok: true, version: stdout.trim() };
|
|
17
|
-
} catch {
|
|
17
|
+
} catch (err) {
|
|
18
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
18
19
|
return {
|
|
19
20
|
ok: false,
|
|
20
|
-
error: "Claude Code CLI not found. Install: npm i -g @anthropic-ai/claude-code"
|
|
21
|
+
error: "Claude Code CLI not found. Install: npm i -g @anthropic-ai/claude-code",
|
|
22
|
+
errorKind: classifyAdapterError(msg)
|
|
21
23
|
};
|
|
22
24
|
}
|
|
23
25
|
}
|
|
@@ -63,8 +65,11 @@ function parseClaudeEvent(line) {
|
|
|
63
65
|
return { type: "tool_call", timestamp, data: parsed };
|
|
64
66
|
case "tool_result":
|
|
65
67
|
return { type: "output", timestamp, data: parsed };
|
|
66
|
-
case "error":
|
|
67
|
-
|
|
68
|
+
case "error": {
|
|
69
|
+
const errData = parsed.error ?? parsed;
|
|
70
|
+
const errMsg = typeof errData === "string" ? errData : JSON.stringify(errData);
|
|
71
|
+
return { type: "error", timestamp, data: errData, errorKind: classifyAdapterError(errMsg) };
|
|
72
|
+
}
|
|
68
73
|
case "result": {
|
|
69
74
|
const tokens = extractTokens(parsed, { statsFallback: true });
|
|
70
75
|
return { type: "done", timestamp, data: parsed, tokens };
|
|
@@ -78,5 +83,3 @@ function parseClaudeEvent(line) {
|
|
|
78
83
|
}
|
|
79
84
|
|
|
80
85
|
export { ClaudeAdapter };
|
|
81
|
-
//# sourceMappingURL=claude-RIB3RQS5.js.map
|
|
82
|
-
//# sourceMappingURL=claude-RIB3RQS5.js.map
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
2
|
+
// src/domain/agent-shop.ts
|
|
3
|
+
var BACKEND_DEV_ROLE = `Backend engineer \u2014 builds APIs, services, database layers, and server-side business logic.
|
|
3
4
|
|
|
4
5
|
## WORKFLOW
|
|
5
6
|
|
|
@@ -18,7 +19,8 @@ var n=`Backend engineer \u2014 builds APIs, services, database layers, and serve
|
|
|
18
19
|
- Every public function must have at least one test.
|
|
19
20
|
- Never store secrets or credentials in code \u2014 use environment variables.
|
|
20
21
|
- Keep functions under 40 lines; extract helpers when complexity grows.
|
|
21
|
-
- If the task is ambiguous, set context with your questions before coding
|
|
22
|
+
- If the task is ambiguous, set context with your questions before coding.`;
|
|
23
|
+
var FRONTEND_DEV_ROLE = `Frontend engineer \u2014 builds React UI components, pages, styles, and client-side interactions.
|
|
22
24
|
|
|
23
25
|
## WORKFLOW
|
|
24
26
|
|
|
@@ -37,7 +39,8 @@ var n=`Backend engineer \u2014 builds APIs, services, database layers, and serve
|
|
|
37
39
|
- Use semantic HTML elements (nav, main, section, button) \u2014 not div soup.
|
|
38
40
|
- Keep components under 150 lines; extract sub-components when they grow.
|
|
39
41
|
- Never hardcode colors or spacing \u2014 use design tokens / theme variables.
|
|
40
|
-
- Ensure keyboard navigation and ARIA labels for interactive elements
|
|
42
|
+
- Ensure keyboard navigation and ARIA labels for interactive elements.`;
|
|
43
|
+
var QA_ENGINEER_ROLE = `QA engineer \u2014 writes tests, analyzes coverage, and ensures code quality across the project.
|
|
41
44
|
|
|
42
45
|
## WORKFLOW
|
|
43
46
|
|
|
@@ -55,7 +58,8 @@ var n=`Backend engineer \u2014 builds APIs, services, database layers, and serve
|
|
|
55
58
|
- Never test implementation details \u2014 test behavior and contracts.
|
|
56
59
|
- Mock external dependencies at the boundary, not deep inside the code.
|
|
57
60
|
- Coverage targets: aim for >80% line coverage on new code, >90% on critical paths.
|
|
58
|
-
- Flag any untestable code as a design smell and suggest refactoring
|
|
61
|
+
- Flag any untestable code as a design smell and suggest refactoring.`;
|
|
62
|
+
var CODE_REVIEWER_ROLE = `Senior code reviewer \u2014 performs thorough PR reviews focused on correctness, security, maintainability, and adherence to project standards.
|
|
59
63
|
|
|
60
64
|
## WORKFLOW
|
|
61
65
|
|
|
@@ -77,7 +81,8 @@ var n=`Backend engineer \u2014 builds APIs, services, database layers, and serve
|
|
|
77
81
|
- Never approve code with known security issues, even if the task is urgent.
|
|
78
82
|
- Be respectful \u2014 critique code, not the author.
|
|
79
83
|
- If the change is too large to review safely, request it be split.
|
|
80
|
-
- Check that tests exist for new logic; flag untested paths
|
|
84
|
+
- Check that tests exist for new logic; flag untested paths.`;
|
|
85
|
+
var ARCHITECT_ROLE = `Software architect and technical leader \u2014 makes system-level design decisions, defines architecture, and ensures technical coherence across the project.
|
|
81
86
|
|
|
82
87
|
## WORKFLOW
|
|
83
88
|
|
|
@@ -96,7 +101,8 @@ var n=`Backend engineer \u2014 builds APIs, services, database layers, and serve
|
|
|
96
101
|
- Enforce layer boundaries \u2014 domain must not depend on infrastructure.
|
|
97
102
|
- Never introduce a new technology without evaluating operational cost.
|
|
98
103
|
- Think in interfaces first, implementations second.
|
|
99
|
-
- Flag technical debt explicitly; don't let it accumulate silently
|
|
104
|
+
- Flag technical debt explicitly; don't let it accumulate silently.`;
|
|
105
|
+
var DEVOPS_ENGINEER_ROLE = `DevOps engineer \u2014 manages CI/CD pipelines, infrastructure, deployment automation, and cloud configuration.
|
|
100
106
|
|
|
101
107
|
## WORKFLOW
|
|
102
108
|
|
|
@@ -115,7 +121,8 @@ var n=`Backend engineer \u2014 builds APIs, services, database layers, and serve
|
|
|
115
121
|
- Always include health checks and rollback triggers in deployments.
|
|
116
122
|
- Tag all cloud resources with project, environment, and owner.
|
|
117
123
|
- Prefer declarative config over imperative scripts.
|
|
118
|
-
- Monitor cost implications of infrastructure changes
|
|
124
|
+
- Monitor cost implications of infrastructure changes.`;
|
|
125
|
+
var BUG_HUNTER_ROLE = `Bug hunter \u2014 finds, reproduces, and diagnoses bugs through systematic investigation and proposes minimal fixes.
|
|
119
126
|
|
|
120
127
|
## WORKFLOW
|
|
121
128
|
|
|
@@ -134,7 +141,8 @@ var n=`Backend engineer \u2014 builds APIs, services, database layers, and serve
|
|
|
134
141
|
- Keep fixes minimal and focused \u2014 one bug per task, no scope creep.
|
|
135
142
|
- Check for the same bug pattern elsewhere in the codebase.
|
|
136
143
|
- Never suppress errors to hide bugs \u2014 surface them properly.
|
|
137
|
-
- If the bug is in a dependency, document the workaround and file upstream
|
|
144
|
+
- If the bug is in a dependency, document the workaround and file upstream.`;
|
|
145
|
+
var TECH_WRITER_ROLE = `Technical writer \u2014 creates and maintains documentation, READMEs, API references, guides, and inline code comments.
|
|
138
146
|
|
|
139
147
|
## WORKFLOW
|
|
140
148
|
|
|
@@ -155,7 +163,8 @@ var n=`Backend engineer \u2014 builds APIs, services, database layers, and serve
|
|
|
155
163
|
- Use active voice and second person ("you can configure\u2026" not "it can be configured\u2026").
|
|
156
164
|
- Keep sentences under 25 words; paragraphs under 5 sentences.
|
|
157
165
|
- Code examples must be complete and runnable \u2014 no pseudo-code in docs.
|
|
158
|
-
- Never document internal implementation details in user-facing docs
|
|
166
|
+
- Never document internal implementation details in user-facing docs.`;
|
|
167
|
+
var MARKETER_ROLE = `Marketing strategist \u2014 develops positioning, messaging, copy, and campaign strategies using marketing psychology principles.
|
|
159
168
|
|
|
160
169
|
## WORKFLOW
|
|
161
170
|
|
|
@@ -176,7 +185,8 @@ var n=`Backend engineer \u2014 builds APIs, services, database layers, and serve
|
|
|
176
185
|
- Include measurable KPIs for every campaign recommendation.
|
|
177
186
|
- Respect brand voice and tone guidelines if they exist.
|
|
178
187
|
- A/B test assumptions \u2014 never assume you know what converts.
|
|
179
|
-
- Keep copy scannable: short paragraphs, bullet points, clear hierarchy
|
|
188
|
+
- Keep copy scannable: short paragraphs, bullet points, clear hierarchy.`;
|
|
189
|
+
var CONTENT_CREATOR_ROLE = `Content creator \u2014 writes blog posts, articles, social media content, and educational materials that drive engagement and authority.
|
|
180
190
|
|
|
181
191
|
## WORKFLOW
|
|
182
192
|
|
|
@@ -197,7 +207,8 @@ var n=`Backend engineer \u2014 builds APIs, services, database layers, and serve
|
|
|
197
207
|
- Paragraphs max 3-4 sentences for readability.
|
|
198
208
|
- Include at least one concrete example or data point per section.
|
|
199
209
|
- Never plagiarize \u2014 all content must be original.
|
|
200
|
-
- Optimize for the target platform (blog post \u2260 tweet \u2260 LinkedIn post)
|
|
210
|
+
- Optimize for the target platform (blog post \u2260 tweet \u2260 LinkedIn post).`;
|
|
211
|
+
var GROWTH_HACKER_ROLE = `Growth hacker \u2014 designs and implements data-driven growth experiments to improve acquisition, activation, retention, and revenue.
|
|
201
212
|
|
|
202
213
|
## WORKFLOW
|
|
203
214
|
|
|
@@ -215,7 +226,8 @@ var n=`Backend engineer \u2014 builds APIs, services, database layers, and serve
|
|
|
215
226
|
- Run one experiment per funnel stage at a time to avoid confounding.
|
|
216
227
|
- Prioritize experiments by ICE score (Impact \xD7 Confidence \xD7 Ease).
|
|
217
228
|
- Never ship a "growth hack" that degrades user experience long-term.
|
|
218
|
-
- Document results of every experiment, including failures \u2014 they are data
|
|
229
|
+
- Document results of every experiment, including failures \u2014 they are data.`;
|
|
230
|
+
var SECURITY_AUDITOR_ROLE = `Security auditor \u2014 performs security analysis, identifies vulnerabilities, and recommends hardening measures following OWASP and industry best practices.
|
|
219
231
|
|
|
220
232
|
## WORKFLOW
|
|
221
233
|
|
|
@@ -238,7 +250,8 @@ var n=`Backend engineer \u2014 builds APIs, services, database layers, and serve
|
|
|
238
250
|
- Classify severity honestly \u2014 don't inflate or downplay.
|
|
239
251
|
- Check both application code AND configuration (CORS, headers, TLS, CSP).
|
|
240
252
|
- Recommend defense-in-depth \u2014 never rely on a single security control.
|
|
241
|
-
- Flag any plaintext secrets immediately as Critical, even in test code
|
|
253
|
+
- Flag any plaintext secrets immediately as Critical, even in test code.`;
|
|
254
|
+
var PERFORMANCE_ENGINEER_ROLE = `Performance engineer \u2014 profiles, benchmarks, and optimizes code for speed, memory efficiency, and scalability.
|
|
242
255
|
|
|
243
256
|
## WORKFLOW
|
|
244
257
|
|
|
@@ -260,7 +273,8 @@ var n=`Backend engineer \u2014 builds APIs, services, database layers, and serve
|
|
|
260
273
|
- Prefer algorithmic improvements over micro-optimizations.
|
|
261
274
|
- Never sacrifice readability for marginal performance gains.
|
|
262
275
|
- Profile in realistic conditions \u2014 not with trivial test data.
|
|
263
|
-
- Watch for regressions \u2014 optimization in one area can degrade another
|
|
276
|
+
- Watch for regressions \u2014 optimization in one area can degrade another.`;
|
|
277
|
+
var DATA_ENGINEER_ROLE = `Data engineer \u2014 builds data pipelines, ETL processes, analytics queries, and data infrastructure.
|
|
264
278
|
|
|
265
279
|
## WORKFLOW
|
|
266
280
|
|
|
@@ -281,7 +295,8 @@ var n=`Backend engineer \u2014 builds APIs, services, database layers, and serve
|
|
|
281
295
|
- Always validate data at ingestion boundaries \u2014 never trust upstream data.
|
|
282
296
|
- Handle NULLs, duplicates, and encoding issues explicitly.
|
|
283
297
|
- Log pipeline metrics: rows processed, duration, error count.
|
|
284
|
-
- Never run DELETE or UPDATE without a WHERE clause and a backup plan
|
|
298
|
+
- Never run DELETE or UPDATE without a WHERE clause and a backup plan.`;
|
|
299
|
+
var FULLSTACK_DEV_ROLE = `Full-stack developer \u2014 works across the entire stack, from database and API to UI components and styling.
|
|
285
300
|
|
|
286
301
|
## WORKFLOW
|
|
287
302
|
|
|
@@ -305,4 +320,161 @@ var n=`Backend engineer \u2014 builds APIs, services, database layers, and serve
|
|
|
305
320
|
- Keep frontend and backend changes in the same branch for atomic features.
|
|
306
321
|
- Follow each layer's conventions independently \u2014 backend patterns for backend, frontend patterns for frontend.
|
|
307
322
|
- Handle every error state in the UI \u2014 users should never see a blank screen.
|
|
308
|
-
- If a task is too large to deliver end-to-end, split it and communicate the dependency
|
|
323
|
+
- If a task is too large to deliver end-to-end, split it and communicate the dependency.`;
|
|
324
|
+
var AGENT_SHOP_TEMPLATES = [
|
|
325
|
+
{
|
|
326
|
+
key: "backend-dev",
|
|
327
|
+
name: "Backend Developer",
|
|
328
|
+
description: "APIs, databases, backend services",
|
|
329
|
+
adapter: "claude",
|
|
330
|
+
model: "claude-sonnet-4-6",
|
|
331
|
+
approval_policy: "auto",
|
|
332
|
+
skills: ["feature-dev:feature-dev", "feature-dev:code-explorer"],
|
|
333
|
+
role: BACKEND_DEV_ROLE
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
key: "frontend-dev",
|
|
337
|
+
name: "Frontend Developer",
|
|
338
|
+
description: "React, UI components, CSS, responsive design",
|
|
339
|
+
adapter: "claude",
|
|
340
|
+
model: "claude-sonnet-4-6",
|
|
341
|
+
approval_policy: "auto",
|
|
342
|
+
skills: ["feature-dev:feature-dev", "feature-dev:code-explorer", "frontend-design"],
|
|
343
|
+
role: FRONTEND_DEV_ROLE
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
key: "qa-engineer",
|
|
347
|
+
name: "QA Engineer",
|
|
348
|
+
description: "Test writing, coverage analysis, quality assurance",
|
|
349
|
+
adapter: "claude",
|
|
350
|
+
model: "claude-sonnet-4-6",
|
|
351
|
+
approval_policy: "auto",
|
|
352
|
+
skills: ["testing-suite:generate-tests", "testing-suite:test-coverage", "testing-suite:test-quality-analyzer"],
|
|
353
|
+
role: QA_ENGINEER_ROLE
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
key: "code-reviewer",
|
|
357
|
+
name: "Code Reviewer",
|
|
358
|
+
description: "PR review, bug finding, code quality, security",
|
|
359
|
+
adapter: "claude",
|
|
360
|
+
model: "claude-opus-4-6",
|
|
361
|
+
approval_policy: "suggest",
|
|
362
|
+
skills: ["feature-dev:code-reviewer", "feature-dev:code-explorer"],
|
|
363
|
+
role: CODE_REVIEWER_ROLE
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
key: "architect",
|
|
367
|
+
name: "Architect",
|
|
368
|
+
description: "System design, architecture decisions, tech leadership",
|
|
369
|
+
adapter: "claude",
|
|
370
|
+
model: "claude-opus-4-6",
|
|
371
|
+
approval_policy: "suggest",
|
|
372
|
+
skills: ["feature-dev:code-architect", "feature-dev:code-explorer"],
|
|
373
|
+
role: ARCHITECT_ROLE
|
|
374
|
+
},
|
|
375
|
+
{
|
|
376
|
+
key: "devops-engineer",
|
|
377
|
+
name: "DevOps Engineer",
|
|
378
|
+
description: "CI/CD, infrastructure, deployment, cloud",
|
|
379
|
+
adapter: "claude",
|
|
380
|
+
model: "claude-sonnet-4-6",
|
|
381
|
+
approval_policy: "auto",
|
|
382
|
+
skills: ["devops-automation:cloud-architect", "feature-dev:code-explorer"],
|
|
383
|
+
role: DEVOPS_ENGINEER_ROLE
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
key: "bug-hunter",
|
|
387
|
+
name: "Bug Hunter",
|
|
388
|
+
description: "Find bugs, reproduce issues, propose fixes",
|
|
389
|
+
adapter: "claude",
|
|
390
|
+
model: "claude-sonnet-4-6",
|
|
391
|
+
approval_policy: "auto",
|
|
392
|
+
skills: ["feature-dev:feature-dev", "feature-dev:code-explorer"],
|
|
393
|
+
role: BUG_HUNTER_ROLE
|
|
394
|
+
},
|
|
395
|
+
{
|
|
396
|
+
key: "tech-writer",
|
|
397
|
+
name: "Technical Writer",
|
|
398
|
+
description: "Documentation, READMEs, API docs, guides",
|
|
399
|
+
adapter: "claude",
|
|
400
|
+
model: "claude-sonnet-4-6",
|
|
401
|
+
approval_policy: "auto",
|
|
402
|
+
skills: ["feature-dev:code-explorer", "docx"],
|
|
403
|
+
role: TECH_WRITER_ROLE
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
key: "marketer",
|
|
407
|
+
name: "Marketer",
|
|
408
|
+
description: "Marketing strategy, positioning, copy, campaigns",
|
|
409
|
+
adapter: "claude",
|
|
410
|
+
model: "claude-sonnet-4-6",
|
|
411
|
+
approval_policy: "auto",
|
|
412
|
+
skills: ["marketing-psychology", "product-manager-toolkit"],
|
|
413
|
+
role: MARKETER_ROLE
|
|
414
|
+
},
|
|
415
|
+
{
|
|
416
|
+
key: "content-creator",
|
|
417
|
+
name: "Content Creator",
|
|
418
|
+
description: "Blog posts, articles, social media content",
|
|
419
|
+
adapter: "claude",
|
|
420
|
+
model: "claude-sonnet-4-6",
|
|
421
|
+
approval_policy: "auto",
|
|
422
|
+
skills: ["marketing-psychology"],
|
|
423
|
+
role: CONTENT_CREATOR_ROLE
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
key: "growth-hacker",
|
|
427
|
+
name: "Growth Hacker",
|
|
428
|
+
description: "Growth experiments, analytics, user acquisition",
|
|
429
|
+
adapter: "claude",
|
|
430
|
+
model: "claude-sonnet-4-6",
|
|
431
|
+
approval_policy: "auto",
|
|
432
|
+
skills: ["product-manager-toolkit", "feature-dev:feature-dev"],
|
|
433
|
+
role: GROWTH_HACKER_ROLE
|
|
434
|
+
},
|
|
435
|
+
{
|
|
436
|
+
key: "security-auditor",
|
|
437
|
+
name: "Security Auditor",
|
|
438
|
+
description: "Security scanning, vulnerability analysis, OWASP",
|
|
439
|
+
adapter: "claude",
|
|
440
|
+
model: "claude-opus-4-6",
|
|
441
|
+
approval_policy: "suggest",
|
|
442
|
+
skills: ["feature-dev:code-reviewer", "feature-dev:code-explorer"],
|
|
443
|
+
role: SECURITY_AUDITOR_ROLE
|
|
444
|
+
},
|
|
445
|
+
{
|
|
446
|
+
key: "performance-engineer",
|
|
447
|
+
name: "Performance Engineer",
|
|
448
|
+
description: "Optimization, profiling, benchmarks, load testing",
|
|
449
|
+
adapter: "claude",
|
|
450
|
+
model: "claude-sonnet-4-6",
|
|
451
|
+
approval_policy: "auto",
|
|
452
|
+
skills: ["feature-dev:feature-dev", "feature-dev:code-explorer"],
|
|
453
|
+
role: PERFORMANCE_ENGINEER_ROLE
|
|
454
|
+
},
|
|
455
|
+
{
|
|
456
|
+
key: "data-engineer",
|
|
457
|
+
name: "Data Engineer",
|
|
458
|
+
description: "Data pipelines, ETL, analytics, SQL",
|
|
459
|
+
adapter: "claude",
|
|
460
|
+
model: "claude-sonnet-4-6",
|
|
461
|
+
approval_policy: "auto",
|
|
462
|
+
skills: ["feature-dev:feature-dev", "feature-dev:code-explorer"],
|
|
463
|
+
role: DATA_ENGINEER_ROLE
|
|
464
|
+
},
|
|
465
|
+
{
|
|
466
|
+
key: "fullstack-dev",
|
|
467
|
+
name: "Full-Stack Developer",
|
|
468
|
+
description: "End-to-end development, frontend and backend",
|
|
469
|
+
adapter: "claude",
|
|
470
|
+
model: "claude-sonnet-4-6",
|
|
471
|
+
approval_policy: "auto",
|
|
472
|
+
skills: ["feature-dev:feature-dev", "feature-dev:code-explorer", "frontend-design"],
|
|
473
|
+
role: FULLSTACK_DEV_ROLE
|
|
474
|
+
}
|
|
475
|
+
];
|
|
476
|
+
function getShopTemplateByKey(key) {
|
|
477
|
+
return AGENT_SHOP_TEMPLATES.find((t) => t.key === key);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
export { AGENT_SHOP_TEMPLATES, getShopTemplateByKey };
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from 'fs/promises';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import os from 'os';
|
|
5
|
+
import { execFile } from 'child_process';
|
|
6
|
+
|
|
7
|
+
var PACKAGE_NAME = "@oxgeneral/orch";
|
|
8
|
+
var CACHE_DIR = path.join(os.homedir(), ".orchestry");
|
|
9
|
+
var CACHE_FILE = path.join(CACHE_DIR, "update-check.json");
|
|
10
|
+
var CHECK_INTERVAL_MS = 4 * 60 * 60 * 1e3;
|
|
11
|
+
var REVALIDATE_AFTER_MS = CHECK_INTERVAL_MS * 0.75;
|
|
12
|
+
function compareSemver(a, b) {
|
|
13
|
+
const pa = a.split(".").map(Number);
|
|
14
|
+
const pb = b.split(".").map(Number);
|
|
15
|
+
for (let i = 0; i < 3; i++) {
|
|
16
|
+
const diff = (pa[i] ?? 0) - (pb[i] ?? 0);
|
|
17
|
+
if (diff !== 0) return diff > 0 ? 1 : -1;
|
|
18
|
+
}
|
|
19
|
+
return 0;
|
|
20
|
+
}
|
|
21
|
+
async function readCache() {
|
|
22
|
+
try {
|
|
23
|
+
const raw = await fs.readFile(CACHE_FILE, "utf-8");
|
|
24
|
+
const data = JSON.parse(raw);
|
|
25
|
+
if (Date.now() - data.checked_at < CHECK_INTERVAL_MS) return data;
|
|
26
|
+
} catch {
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
async function writeCache(latest) {
|
|
31
|
+
await fs.mkdir(CACHE_DIR, { recursive: true });
|
|
32
|
+
const data = { latest, checked_at: Date.now() };
|
|
33
|
+
const tmp = `${CACHE_FILE}.tmp.${process.pid}`;
|
|
34
|
+
await fs.writeFile(tmp, JSON.stringify(data), "utf-8");
|
|
35
|
+
await fs.rename(tmp, CACHE_FILE);
|
|
36
|
+
}
|
|
37
|
+
function fetchLatestVersion() {
|
|
38
|
+
return new Promise((resolve) => {
|
|
39
|
+
const child = execFile("npm", ["view", PACKAGE_NAME, "version", "--json"], { timeout: 5e3 }, (err, stdout) => {
|
|
40
|
+
if (err) return resolve(null);
|
|
41
|
+
try {
|
|
42
|
+
resolve(JSON.parse(stdout.trim()));
|
|
43
|
+
} catch {
|
|
44
|
+
resolve(null);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
child.unref();
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
function buildUpdateInfo(current, latest) {
|
|
51
|
+
return { current, latest, updateAvailable: compareSemver(latest, current) > 0 };
|
|
52
|
+
}
|
|
53
|
+
async function checkForUpdateNow(currentVersion) {
|
|
54
|
+
const latest = await fetchLatestVersion();
|
|
55
|
+
if (!latest) return null;
|
|
56
|
+
await writeCache(latest).catch(() => {
|
|
57
|
+
});
|
|
58
|
+
return buildUpdateInfo(currentVersion, latest);
|
|
59
|
+
}
|
|
60
|
+
async function checkForUpdateSWR(currentVersion) {
|
|
61
|
+
try {
|
|
62
|
+
const cached = await readCache();
|
|
63
|
+
if (!cached) {
|
|
64
|
+
checkForUpdateNow(currentVersion).catch(() => {
|
|
65
|
+
});
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
const age = Date.now() - cached.checked_at;
|
|
69
|
+
if (age >= REVALIDATE_AFTER_MS) {
|
|
70
|
+
checkForUpdateNow(currentVersion).catch(() => {
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
return buildUpdateInfo(currentVersion, cached.latest);
|
|
74
|
+
} catch {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function printUpdateNotification(info) {
|
|
79
|
+
if (!info.updateAvailable) return;
|
|
80
|
+
const msg = `
|
|
81
|
+
Update available: ${info.current} \u2192 ${info.latest}
|
|
82
|
+
Run: npm install -g ${PACKAGE_NAME}
|
|
83
|
+
`;
|
|
84
|
+
process.stderr.write(msg);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export { checkForUpdateNow, checkForUpdateSWR, printUpdateNotification };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// src/domain/goal.ts
|
|
3
|
+
var GOAL_STATUSES = ["active", "paused", "achieved", "abandoned"];
|
|
4
|
+
var TERMINAL_GOAL_STATUSES = /* @__PURE__ */ new Set(["achieved", "abandoned"]);
|
|
5
|
+
function isGoalTerminal(status) {
|
|
6
|
+
return TERMINAL_GOAL_STATUSES.has(status);
|
|
7
|
+
}
|
|
8
|
+
var GOAL_STATUS_ORDER = {
|
|
9
|
+
active: 0,
|
|
10
|
+
paused: 1,
|
|
11
|
+
achieved: 2,
|
|
12
|
+
abandoned: 3
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export { GOAL_STATUSES, GOAL_STATUS_ORDER, isGoalTerminal };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// src/domain/config.ts
|
|
3
|
+
var DEFAULT_CONFIG = {
|
|
4
|
+
project: {
|
|
5
|
+
name: "my-project"
|
|
6
|
+
},
|
|
7
|
+
defaults: {
|
|
8
|
+
agent: {
|
|
9
|
+
adapter: "claude",
|
|
10
|
+
approval_policy: "auto",
|
|
11
|
+
max_turns: 50,
|
|
12
|
+
timeout_ms: 36e5,
|
|
13
|
+
stall_timeout_ms: 3e5,
|
|
14
|
+
workspace_mode: "worktree"
|
|
15
|
+
},
|
|
16
|
+
task: {
|
|
17
|
+
max_attempts: 3,
|
|
18
|
+
priority: 3
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
scheduling: {
|
|
22
|
+
poll_interval_ms: 1e4,
|
|
23
|
+
max_concurrent_agents: 6,
|
|
24
|
+
retry_base_delay_ms: 1e4,
|
|
25
|
+
retry_max_delay_ms: 3e5
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export { DEFAULT_CONFIG };
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { execFile } from 'child_process';
|
|
3
|
+
import { promisify } from 'util';
|
|
4
|
+
import fs from 'fs/promises';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
|
|
7
|
+
var execFileAsync = promisify(execFile);
|
|
8
|
+
var DoctorService = class {
|
|
9
|
+
constructor(adapterRegistry, processManager, projectRoot) {
|
|
10
|
+
this.adapterRegistry = adapterRegistry;
|
|
11
|
+
this.processManager = processManager;
|
|
12
|
+
this.cwd = projectRoot ?? process.cwd();
|
|
13
|
+
}
|
|
14
|
+
cwd;
|
|
15
|
+
async runAll() {
|
|
16
|
+
const checks = [];
|
|
17
|
+
const adapters = this.adapterRegistry.list();
|
|
18
|
+
let adaptersReady = 0;
|
|
19
|
+
for (const adapter of adapters) {
|
|
20
|
+
const result = await adapter.test();
|
|
21
|
+
if (result.ok) {
|
|
22
|
+
adaptersReady++;
|
|
23
|
+
checks.push({
|
|
24
|
+
name: adapter.kind,
|
|
25
|
+
status: "ok",
|
|
26
|
+
detail: result.version
|
|
27
|
+
});
|
|
28
|
+
} else {
|
|
29
|
+
checks.push({
|
|
30
|
+
name: adapter.kind,
|
|
31
|
+
status: "fail",
|
|
32
|
+
detail: result.error
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
checks.push(await this.checkCommand("git", ["--version"], "git"));
|
|
37
|
+
checks.push(await this.checkGitRepo());
|
|
38
|
+
checks.push(await this.checkGitignore());
|
|
39
|
+
checks.push(await this.checkCommand("node", ["--version"], "node"));
|
|
40
|
+
return {
|
|
41
|
+
checks,
|
|
42
|
+
adaptersReady,
|
|
43
|
+
adaptersTotal: adapters.length
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
async checkCommand(command, args, name) {
|
|
47
|
+
try {
|
|
48
|
+
const { stdout } = await execFileAsync(command, args);
|
|
49
|
+
return { name, status: "ok", detail: stdout.trim() };
|
|
50
|
+
} catch {
|
|
51
|
+
return { name, status: "fail", detail: `${command}: command not found` };
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
async checkGitignore() {
|
|
55
|
+
const gitignorePath = path.join(this.cwd, ".gitignore");
|
|
56
|
+
try {
|
|
57
|
+
const content = await fs.readFile(gitignorePath, "utf-8");
|
|
58
|
+
const hasEntry = content.split("\n").some((line) => line.trim() === ".orchestry");
|
|
59
|
+
if (hasEntry) {
|
|
60
|
+
return { name: ".gitignore", status: "ok", detail: ".orchestry is excluded" };
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
name: ".gitignore",
|
|
64
|
+
status: "fail",
|
|
65
|
+
detail: ".orchestry not in .gitignore \u2014 worktrees will copy state recursively. Run: orch init"
|
|
66
|
+
};
|
|
67
|
+
} catch {
|
|
68
|
+
return {
|
|
69
|
+
name: ".gitignore",
|
|
70
|
+
status: "fail",
|
|
71
|
+
detail: "no .gitignore found \u2014 .orchestry may be committed to git. Run: orch init"
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
async checkGitRepo() {
|
|
76
|
+
try {
|
|
77
|
+
await execFileAsync("git", ["rev-parse", "--is-inside-work-tree"], { cwd: this.cwd });
|
|
78
|
+
return { name: "git repo", status: "ok", detail: "git repository detected" };
|
|
79
|
+
} catch {
|
|
80
|
+
return {
|
|
81
|
+
name: "git repo",
|
|
82
|
+
status: "fail",
|
|
83
|
+
detail: "not a git repository \u2014 worktree/isolated modes will fail. Run: git init"
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export { DoctorService };
|