orchestrix 15.14.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/bin/o8x.js ADDED
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const args = process.argv.slice(2);
5
+ const command = args[0];
6
+ const flags = parseFlags(args.slice(1));
7
+
8
+ function parseFlags(argv) {
9
+ const result = { _: [] };
10
+ for (let i = 0; i < argv.length; i++) {
11
+ const arg = argv[i];
12
+ if (arg === '--key' && i + 1 < argv.length) {
13
+ result.key = argv[++i];
14
+ } else if (arg === '--offline') {
15
+ result.offline = true;
16
+ } else if (arg === '--force') {
17
+ result.force = true;
18
+ } else if (arg === '--no-hooks') {
19
+ result.noHooks = true;
20
+ } else if (arg === '--no-scripts') {
21
+ result.noScripts = true;
22
+ } else if (arg === '--no-mcp') {
23
+ result.noMcp = true;
24
+ } else if (arg === '--yes' || arg === '-y') {
25
+ result.yes = true;
26
+ } else {
27
+ result._.push(arg);
28
+ }
29
+ }
30
+ return result;
31
+ }
32
+
33
+ async function main() {
34
+ if (command === 'install' || command === 'i') {
35
+ const { install } = require('../lib/install');
36
+ await install(flags);
37
+ } else if (command === 'doctor' || command === 'dr') {
38
+ const { doctor } = require('../lib/doctor');
39
+ await doctor(flags);
40
+ } else if (command === 'upgrade' || command === 'up') {
41
+ const { upgrade } = require('../lib/upgrade');
42
+ await upgrade(flags);
43
+ } else if (command === 'uninstall' || command === 'rm') {
44
+ const { uninstall } = require('../lib/uninstall');
45
+ await uninstall(flags);
46
+ } else if (command === '--version' || command === '-v' || command === '-V') {
47
+ const { version } = require('../package.json');
48
+ console.log(version);
49
+ } else if (command === '--help' || command === '-h' || !command) {
50
+ printHelp();
51
+ } else {
52
+ console.error(`Unknown command: ${command}`);
53
+ console.error('Run "o8x --help" for usage information.');
54
+ process.exit(1);
55
+ }
56
+ }
57
+
58
+ function printHelp() {
59
+ const { version } = require('../package.json');
60
+ console.log(`
61
+ o8x v${version} — Install Orchestrix multi-agent infrastructure
62
+
63
+ Usage:
64
+ npx o8x install [options] Install into current project
65
+ npx o8x doctor Check installation health
66
+ npx o8x upgrade Upgrade to latest from MCP server
67
+ npx o8x uninstall Remove Orchestrix files from project
68
+ npx o8x --version Show version
69
+ npx o8x --help Show this help message
70
+
71
+ Install options:
72
+ --key <KEY> License key (skips interactive prompt)
73
+ --offline Use embedded files only (no MCP fetch)
74
+ --force Overwrite all files without confirmation
75
+ --no-hooks Skip Stop hook installation
76
+ --no-scripts Skip tmux scripts installation
77
+ --no-mcp Skip .mcp.json modification
78
+ -y, --yes Skip confirmations
79
+
80
+ Examples:
81
+ npx o8x install Interactive install
82
+ npx o8x install --key orch_live_xxx Install with key
83
+ npx o8x install --offline Offline install (embedded files)
84
+ npx o8x doctor Health check
85
+ `);
86
+ }
87
+
88
+ main().catch((err) => {
89
+ console.error(`\n Error: ${err.message}`);
90
+ process.exit(1);
91
+ });
package/lib/doctor.js ADDED
@@ -0,0 +1,150 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const { execSync } = require('child_process');
6
+ const ui = require('./ui');
7
+ const { validateKey } = require('./mcp-client');
8
+ const { resolveKey } = require('./license');
9
+
10
+ async function doctor(flags) {
11
+ ui.banner();
12
+ ui.header('Health Check');
13
+
14
+ const projectDir = process.cwd();
15
+ let allGood = true;
16
+
17
+ // 1. Node.js version
18
+ const nodeVersion = process.versions.node;
19
+ const nodeMajor = parseInt(nodeVersion.split('.')[0], 10);
20
+ if (nodeMajor >= 18) {
21
+ ui.success(`Node.js ${nodeVersion}`);
22
+ } else {
23
+ ui.error(`Node.js ${nodeVersion} (need >= 18)`);
24
+ allGood = false;
25
+ }
26
+
27
+ // 2. tmux
28
+ try {
29
+ const tmuxVersion = execSync('tmux -V', { stdio: 'pipe' }).toString().trim();
30
+ ui.success(`tmux: ${tmuxVersion}`);
31
+ } catch {
32
+ ui.warn('tmux not installed (needed for multi-agent automation)');
33
+ ui.log(` Install: brew install tmux (macOS) or sudo apt install tmux (Linux)`);
34
+ }
35
+
36
+ // 3. .mcp.json
37
+ const mcpPath = path.join(projectDir, '.mcp.json');
38
+ if (fs.existsSync(mcpPath)) {
39
+ try {
40
+ const mcp = JSON.parse(fs.readFileSync(mcpPath, 'utf-8'));
41
+ if (mcp.mcpServers && mcp.mcpServers.orchestrix) {
42
+ ui.success(`.mcp.json: orchestrix entry found (${mcp.mcpServers.orchestrix.url})`);
43
+ } else {
44
+ ui.error('.mcp.json: missing orchestrix entry');
45
+ allGood = false;
46
+ }
47
+ } catch {
48
+ ui.error('.mcp.json: invalid JSON');
49
+ allGood = false;
50
+ }
51
+ } else {
52
+ ui.error('.mcp.json: not found');
53
+ allGood = false;
54
+ }
55
+
56
+ // 4. License key + MCP server
57
+ try {
58
+ const key = await resolveKey({ ...flags, key: flags.key || process.env.ORCHESTRIX_LICENSE_KEY });
59
+ const result = await validateKey(key);
60
+ if (result.valid) {
61
+ ui.success(`MCP server: reachable (tier: ${result.tier})`);
62
+ } else {
63
+ ui.warn(`MCP server: ${result.error}`);
64
+ }
65
+ } catch {
66
+ ui.warn('License key not found — MCP server check skipped');
67
+ }
68
+
69
+ // 5. Slash commands
70
+ const commandsDir = path.join(projectDir, '.claude', 'commands');
71
+ const expectedCommands = ['o.md', 'o-help.md', 'o-status.md'];
72
+ const foundCommands = expectedCommands.filter((f) => fs.existsSync(path.join(commandsDir, f)));
73
+ if (foundCommands.length === expectedCommands.length) {
74
+ ui.success(`Slash commands: ${foundCommands.length}/${expectedCommands.length} installed`);
75
+ } else {
76
+ ui.error(`Slash commands: ${foundCommands.length}/${expectedCommands.length} installed`);
77
+ allGood = false;
78
+ }
79
+
80
+ // 6. Core config
81
+ const configPath = path.join(projectDir, '.orchestrix-core', 'core-config.yaml');
82
+ if (fs.existsSync(configPath)) {
83
+ ui.success('core-config.yaml: found');
84
+ } else {
85
+ ui.error('core-config.yaml: not found');
86
+ allGood = false;
87
+ }
88
+
89
+ // 7. Scripts
90
+ const scriptsDir = path.join(projectDir, '.orchestrix-core', 'scripts');
91
+ const expectedScripts = ['start-orchestrix.sh', 'handoff-detector.sh'];
92
+ const foundScripts = expectedScripts.filter((f) => {
93
+ const p = path.join(scriptsDir, f);
94
+ if (!fs.existsSync(p)) return false;
95
+ try {
96
+ fs.accessSync(p, fs.constants.X_OK);
97
+ return true;
98
+ } catch {
99
+ ui.warn(`${f}: exists but not executable (chmod +x)`);
100
+ return false;
101
+ }
102
+ });
103
+ if (foundScripts.length === expectedScripts.length) {
104
+ ui.success(`Scripts: ${foundScripts.length}/${expectedScripts.length} installed + executable`);
105
+ } else {
106
+ ui.warn(`Scripts: ${foundScripts.length}/${expectedScripts.length} ready`);
107
+ }
108
+
109
+ // 8. Hooks
110
+ const settingsPath = path.join(projectDir, '.claude', 'settings.local.json');
111
+ if (fs.existsSync(settingsPath)) {
112
+ try {
113
+ const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
114
+ const hasHook = settings.hooks?.Stop?.some((entry) =>
115
+ entry.hooks?.some((h) => h.command?.includes('handoff-detector'))
116
+ );
117
+ if (hasHook) {
118
+ ui.success('Hooks: handoff-detector configured');
119
+ } else {
120
+ ui.warn('Hooks: settings.local.json exists but no handoff-detector hook');
121
+ }
122
+ } catch {
123
+ ui.warn('Hooks: settings.local.json invalid JSON');
124
+ }
125
+ } else {
126
+ ui.warn('Hooks: settings.local.json not found');
127
+ }
128
+
129
+ // 9. .gitignore
130
+ const gitignorePath = path.join(projectDir, '.gitignore');
131
+ if (fs.existsSync(gitignorePath)) {
132
+ const content = fs.readFileSync(gitignorePath, 'utf-8');
133
+ if (content.includes('.env.local')) {
134
+ ui.success('.gitignore: .env.local covered');
135
+ } else {
136
+ ui.warn('.gitignore: .env.local not listed');
137
+ }
138
+ }
139
+
140
+ // Result
141
+ console.log();
142
+ if (allGood) {
143
+ ui.success('All checks passed');
144
+ } else {
145
+ ui.info('Some checks failed — run "npx o8x install" to fix');
146
+ }
147
+ console.log();
148
+ }
149
+
150
+ module.exports = { doctor };
@@ -0,0 +1,163 @@
1
+ 'use strict';
2
+
3
+ // Embedded slash command files — canonical content from Orchestrix MCP Server
4
+ // These serve as offline fallback when MCP server is unreachable
5
+
6
+ const O_MD = `---
7
+ description: Activate Orchestrix Agent (e.g., /o dev, /o sm --lang=zh)
8
+ ---
9
+
10
+ # Orchestrix Agent Activation
11
+
12
+ ## Available Agents
13
+
14
+ | ID | Agent | Description |
15
+ |----|-------|-------------|
16
+ | \`dev\` | Full Stack Developer | implementation, debugging, refactoring |
17
+ | \`sm\` | Scrum Master | story creation, epic management, agile guidance |
18
+ | \`qa\` | QA Engineer | E2E testing, quality verification |
19
+ | \`architect\` | Solution Architect | system design, tech selection, API design |
20
+ | \`pm\` | Product Manager | PRDs, product strategy, roadmap planning |
21
+ | \`po\` | Product Owner | backlog management, story refinement |
22
+ | \`analyst\` | Business Analyst | market research, competitive analysis |
23
+ | \`ux-expert\` | UX Expert | UI/UX design, wireframes, prototypes |
24
+ | \`orchestrix-orchestrator\` | Workflow Coordinator | multi-agent tasks |
25
+ | \`orchestrix-master\` | Master Agent | one-off tasks across domains |
26
+ | \`decision-evaluator\` | Decision Evaluator | execute decision rules |
27
+
28
+ ## Language Support
29
+
30
+ Use \`--lang=xx\` to load agent content in a specific language:
31
+ - \`--lang=en\` - English (default)
32
+ - \`--lang=zh\` - Chinese / 中文
33
+
34
+ Examples:
35
+ - \`/o dev\` - Load Developer agent in English (default)
36
+ - \`/o dev --lang=zh\` - Load Developer agent in Chinese
37
+ - \`/o sm --lang=zh\` - Load Scrum Master agent in Chinese
38
+
39
+ ## Action Required
40
+
41
+ **FIRST**: Parse \`$ARGUMENTS\` to extract agent ID and language option.
42
+
43
+ Arguments format: \`[agent_id] [--lang=xx]\`
44
+
45
+ Parsing rules:
46
+ 1. If \`$ARGUMENTS\` is empty or blank → Show agent table, ask user to select
47
+ 2. If \`$ARGUMENTS\` contains \`--lang=xx\` → Extract language code (en or zh)
48
+ 3. Extract agent ID (everything before \`--lang\` or the entire argument if no \`--lang\`)
49
+
50
+ If \`$ARGUMENTS\` is empty or blank:
51
+ - Show the table above directly
52
+ - Ask user to select an agent
53
+ - **DO NOT** call ReadMcpResourceTool with empty arguments
54
+
55
+ If agent ID is provided, proceed to load the agent:
56
+
57
+ ## Step 1: Read Agent Configuration
58
+
59
+ **CRITICAL**: You MUST use \`ReadMcpResourceTool\` (NOT prompts!) with the EXACT parameters below.
60
+
61
+ \`ReadMcpResourceTool\` only accepts \`server\` and \`uri\` parameters. Language MUST be encoded in the URI as a query parameter.
62
+
63
+ **Without language** (default English):
64
+ - server: \`orchestrix\`
65
+ - uri: \`orchestrix://agents/{agent_id}.yaml\`
66
+
67
+ **With language** (e.g., \`--lang=zh\`):
68
+ - server: \`orchestrix\`
69
+ - uri: \`orchestrix://agents/{agent_id}.yaml?lang=zh\`
70
+
71
+ ### Examples
72
+
73
+ For \`/o pm\`:
74
+ \`\`\`
75
+ ReadMcpResourceTool(server="orchestrix", uri="orchestrix://agents/pm.yaml")
76
+ \`\`\`
77
+
78
+ For \`/o pm --lang=zh\`:
79
+ \`\`\`
80
+ ReadMcpResourceTool(server="orchestrix", uri="orchestrix://agents/pm.yaml?lang=zh")
81
+ \`\`\`
82
+
83
+ **DO NOT** use \`orchestrix://prompts/\` - agents are exposed as **resources**, not prompts!
84
+ **DO NOT** pass \`lang\` as a separate parameter - it MUST be in the URI query string.
85
+
86
+ ## Step 2: After Loading Agent
87
+
88
+ 1. Adopt the persona defined in the \`agent\` section completely
89
+ 2. Follow \`activation_instructions\` exactly
90
+ 3. Display greeting with agent name/role
91
+ 4. Show the numbered command list from \`commands.help.output_format\`
92
+ 5. Wait for user selection
93
+ `;
94
+
95
+ const O_HELP_MD = `---
96
+ description: Show Orchestrix help and available agents
97
+ ---
98
+
99
+ # Orchestrix Help
100
+
101
+ Please call the Orchestrix MCP Server's \`list-agents\` tool to display all available agents.
102
+
103
+ Then display the following usage guide:
104
+
105
+ ## Usage
106
+
107
+ \`\`\`
108
+ /o [agent_id] Activate an agent (e.g., /o dev, /o sm)
109
+ /o-help Show this help message
110
+ /o-status Show current Orchestrix status
111
+ \`\`\`
112
+
113
+ ## Quick Start
114
+
115
+ 1. Use \`/o dev\` to activate the Developer agent for coding tasks
116
+ 2. Use \`/o sm\` to activate the Scrum Master for story management
117
+ 3. Use \`/o qa\` to activate QA Engineer for testing
118
+ `;
119
+
120
+ const O_STATUS_MD = `---
121
+ description: Show Orchestrix server status
122
+ ---
123
+
124
+ # Orchestrix Status
125
+
126
+ Please check and display the current Orchestrix status:
127
+
128
+ ## Status Check Items
129
+
130
+ 1. **MCP Server Connection**: Check if Orchestrix MCP Server is connected
131
+ 2. **Available Agents**: Call \`list-agents\` tool to verify agents are loaded
132
+ 3. **License Status**: Display current license tier (if applicable)
133
+
134
+ ## Expected Output
135
+
136
+ Display the status in this format:
137
+
138
+ \`\`\`
139
+ Orchestrix Status
140
+ =================
141
+ Server: Connected / Disconnected
142
+ Agents: [count] agents available
143
+ License: [tier] mode
144
+
145
+ Available Commands:
146
+ /o [agent] - Activate agent
147
+ /o-help - Show help
148
+ /o-status - This status
149
+ \`\`\`
150
+
151
+ ## Troubleshooting
152
+
153
+ If the server is not connected:
154
+ 1. Check \`.mcp.json\` configuration
155
+ 2. Verify the MCP server process is running
156
+ 3. Check server logs for errors
157
+ `;
158
+
159
+ module.exports = {
160
+ 'o.md': O_MD,
161
+ 'o-help.md': O_HELP_MD,
162
+ 'o-status.md': O_STATUS_MD,
163
+ };
@@ -0,0 +1,74 @@
1
+ 'use strict';
2
+
3
+ // Embedded core-config.template.yaml — project configuration template
4
+
5
+ const CORE_CONFIG_TEMPLATE = `title: Orchestrix Core System
6
+ description: >
7
+ The core agent framework for Orchestrix, providing the essential agents,
8
+ workflows, and data for building and managing AI-driven development teams.
9
+ markdownExploder: true
10
+ project:
11
+ name: '{{PROJECT_NAME}}'
12
+ mode: monolith
13
+ testCommand: '{{TEST_COMMAND}}'
14
+ multi_repo:
15
+ role: implementation
16
+ repository_id: '{{REPO_ID}}'
17
+ product_repo_path: ''
18
+ auto_filter_stories: false
19
+ assigned_stories: []
20
+ prd:
21
+ prdFile: docs/prd.md
22
+ prdSharded: false
23
+ prdShardedLocation: docs/prd
24
+ architecture:
25
+ architectureFile: docs/architecture.md
26
+ architectureSharded: false
27
+ architectureShardedLocation: docs/architecture
28
+ storyReviewsLocation: docs/architecture/story-reviews
29
+ customTechnicalDocuments: null
30
+ devLoadAlwaysFiles:
31
+ - docs/architecture/*coding-standards.md
32
+ - docs/architecture/*tech-stack.md
33
+ - docs/architecture/*source-tree.md
34
+ devDebugLog: .ai/debug-log.md
35
+ devStoryLocation: docs/stories
36
+ verticalSliceStrategy: true
37
+ dev:
38
+ devLogLocation: docs/dev/logs
39
+ devLogEnabled: true
40
+ architect:
41
+ storyReviewsLocation: docs/architecture/story-reviews
42
+ qa:
43
+ qaLocation: docs/qa
44
+ qaReviewsLocation: docs/qa/reviews
45
+ evidenceLocation: docs/qa/evidence
46
+ testDesignThresholds:
47
+ simple:
48
+ maxComplexity: 0
49
+ minQualityScore: 8.5
50
+ securitySensitive: false
51
+ tasks: []
52
+ standard:
53
+ maxComplexity: 2
54
+ minQualityScore: 7
55
+ tasks:
56
+ - test-design
57
+ comprehensive:
58
+ minComplexity: 3
59
+ securitySensitive: true
60
+ tasks:
61
+ - test-design
62
+ - risk-profile
63
+ slashPrefix: Orchestrix
64
+ version: 15.14.0
65
+ i18n:
66
+ default_language: en
67
+ supported_languages:
68
+ - en
69
+ - zh
70
+ fallback_to_default: true
71
+ file_pattern: '{name}.{lang}.{ext}'
72
+ `;
73
+
74
+ module.exports = { CORE_CONFIG_TEMPLATE };