ultra-builder-pro-cli 0.5.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/.ultra-template/delivery-report.json +9 -0
- package/.ultra-template/docs/research/README.md +53 -0
- package/.ultra-template/specs/architecture.md +250 -0
- package/.ultra-template/specs/discovery.md +248 -0
- package/.ultra-template/specs/product.md +223 -0
- package/.ultra-template/tasks/contexts/TEMPLATE.md +57 -0
- package/.ultra-template/tasks/tasks.json +33 -0
- package/.ultra-template/test-report.json +8 -0
- package/CHANGELOG.md +194 -0
- package/LICENSE +21 -0
- package/README.md +187 -0
- package/adapters/_shared/codex-assets.cjs +1128 -0
- package/adapters/_shared/codex-ultra-tools-entry.cjs +11 -0
- package/adapters/_shared/file-ops.cjs +115 -0
- package/adapters/_shared/frontmatter.cjs +52 -0
- package/adapters/_shared/handbook.cjs +144 -0
- package/adapters/_shared/md-to-toml.cjs +54 -0
- package/adapters/_shared/path-rewrite.cjs +79 -0
- package/adapters/_shared/rtk-detect.cjs +86 -0
- package/adapters/_shared/runtime-assets.cjs +70 -0
- package/adapters/_shared/settings-merge.cjs +76 -0
- package/adapters/_shared/tests/file-ops.test.cjs +54 -0
- package/adapters/_shared/tests/frontmatter.test.cjs +47 -0
- package/adapters/_shared/tests/handbook.test.cjs +86 -0
- package/adapters/_shared/tests/md-to-toml.test.cjs +48 -0
- package/adapters/_shared/tests/path-rewrite.test.cjs +60 -0
- package/adapters/_shared/tests/resolve-target.test.cjs +85 -0
- package/adapters/_shared/tests/rtk-detect.test.cjs +116 -0
- package/adapters/_shared/tests/runtime-assets.test.cjs +107 -0
- package/adapters/_shared/tests/settings-merge.test.cjs +85 -0
- package/adapters/_shared/tests/validate.test.cjs +30 -0
- package/adapters/_shared/validate.cjs +24 -0
- package/adapters/claude.js +182 -0
- package/adapters/codex.js +385 -0
- package/adapters/gemini.js +204 -0
- package/adapters/opencode.js +506 -0
- package/adapters/tests/claude.test.cjs +117 -0
- package/adapters/tests/codex-hook.test.cjs +90 -0
- package/adapters/tests/codex.test.cjs +356 -0
- package/adapters/tests/gemini.test.cjs +112 -0
- package/adapters/tests/opencode.test.cjs +246 -0
- package/agents/code-reviewer.md +102 -0
- package/agents/debugger.md +127 -0
- package/agents/review-code.md +125 -0
- package/agents/review-comments.md +98 -0
- package/agents/review-coordinator.md +146 -0
- package/agents/review-design.md +133 -0
- package/agents/review-errors.md +87 -0
- package/agents/review-tests.md +93 -0
- package/agents/tdd-runner.md +92 -0
- package/bin/handbook.js +54 -0
- package/bin/install.js +254 -0
- package/bin/orchestrator.js +214 -0
- package/commands/learn.md +41 -0
- package/commands/ultra-deliver.md +45 -0
- package/commands/ultra-dev.md +50 -0
- package/commands/ultra-init.md +51 -0
- package/commands/ultra-plan.md +49 -0
- package/commands/ultra-research.md +59 -0
- package/commands/ultra-status.md +46 -0
- package/commands/ultra-test.md +48 -0
- package/commands/ultra-think.md +45 -0
- package/docs/AGENT-CONTEXT.md +143 -0
- package/docs/ARCHITECTURE.md +197 -0
- package/docs/COMMIT-HASH-BACKFILL.md +101 -0
- package/docs/LEGACY-HERMES.md +1175 -0
- package/docs/PLAN.zh-CN.md +1683 -0
- package/docs/ROADMAP.md +102 -0
- package/docs/RUNTIME-COMPAT-MATRIX.md +98 -0
- package/docs/STATE-DB-ACCESS-POLICY.md +109 -0
- package/docs/USER-HANDBOOK-CONTRACT.md +61 -0
- package/hooks/README.md +24 -0
- package/hooks/active_task_context.py +44 -0
- package/hooks/adapters/codex.py +302 -0
- package/hooks/health_check.py +61 -0
- package/hooks/pre_stop_check.py +56 -0
- package/hooks/subagent_tracker.py +116 -0
- package/hooks/workflow_checkpoint.py +56 -0
- package/hooks/workflow_context.py +63 -0
- package/hooks/workflow_resume.py +50 -0
- package/mcp-server/lib/init-project.cjs +162 -0
- package/mcp-server/lib/llm-client.cjs +157 -0
- package/mcp-server/lib/llm-client.test.cjs +156 -0
- package/mcp-server/lib/plan-store.cjs +96 -0
- package/mcp-server/lib/plan-store.test.cjs +132 -0
- package/mcp-server/lib/prd-parser.cjs +110 -0
- package/mcp-server/lib/prd-parser.test.cjs +171 -0
- package/mcp-server/lib/pricing.cjs +53 -0
- package/mcp-server/lib/projector.cjs +158 -0
- package/mcp-server/lib/state-db.cjs +113 -0
- package/mcp-server/lib/state-db.test.cjs +116 -0
- package/mcp-server/lib/state-ops.cjs +725 -0
- package/mcp-server/lib/task-expander.cjs +123 -0
- package/mcp-server/lib/task-expander.test.cjs +253 -0
- package/mcp-server/lib/telemetry.cjs +72 -0
- package/mcp-server/lib/topo.cjs +131 -0
- package/mcp-server/lib/topo.test.cjs +158 -0
- package/mcp-server/server.cjs +482 -0
- package/mcp-server/tests/circuit-breaker.test.cjs +125 -0
- package/mcp-server/tests/commit-hash-flow.test.cjs +117 -0
- package/mcp-server/tests/concurrency-update.test.cjs +96 -0
- package/mcp-server/tests/concurrency.test.cjs +112 -0
- package/mcp-server/tests/db-ops.test.cjs +117 -0
- package/mcp-server/tests/init-project.test.cjs +141 -0
- package/mcp-server/tests/migrate.test.cjs +144 -0
- package/mcp-server/tests/projector.test.cjs +130 -0
- package/mcp-server/tests/server-contract.test.cjs +750 -0
- package/mcp-server/tests/staleness.test.cjs +190 -0
- package/mcp-server/tests/state-ops.test.cjs +286 -0
- package/mcp-server/tests/tagged-tasks.test.cjs +163 -0
- package/mcp-server/tests/telemetry.test.cjs +205 -0
- package/orchestrator/auto-merge.cjs +109 -0
- package/orchestrator/code-graph-watcher.cjs +121 -0
- package/orchestrator/daemon.cjs +112 -0
- package/orchestrator/dispatch-rules.cjs +93 -0
- package/orchestrator/parallel-orchestrator.cjs +195 -0
- package/orchestrator/planner/expand-prompt.cjs +62 -0
- package/orchestrator/planner/expand-prompt.test.cjs +52 -0
- package/orchestrator/planner/plan-builder.cjs +116 -0
- package/orchestrator/planner/plan-builder.test.cjs +165 -0
- package/orchestrator/planner/prd-prompt.cjs +44 -0
- package/orchestrator/planner/prd-prompt.test.cjs +30 -0
- package/orchestrator/recovery.cjs +70 -0
- package/orchestrator/session-runner.cjs +224 -0
- package/orchestrator/skill-miner.cjs +133 -0
- package/orchestrator/tests/auto-merge.test.cjs +216 -0
- package/orchestrator/tests/code-graph-watcher.test.cjs +183 -0
- package/orchestrator/tests/daemon.test.cjs +260 -0
- package/orchestrator/tests/dispatch-rules.test.cjs +122 -0
- package/orchestrator/tests/parallel-orchestrator.test.cjs +233 -0
- package/orchestrator/tests/phase-8b-gate.test.cjs +183 -0
- package/orchestrator/tests/recovery.test.cjs +190 -0
- package/orchestrator/tests/session-runner.test.cjs +314 -0
- package/orchestrator/tests/skill-miner.test.cjs +147 -0
- package/orchestrator/tests/worktree-manager.test.cjs +148 -0
- package/orchestrator/worktree-manager.cjs +131 -0
- package/output-styles/coding-vibes.md +67 -0
- package/output-styles/structural-thinking.md +61 -0
- package/package.json +109 -0
- package/settings.json +8 -0
- package/skills/cc-collab/SKILL.md +41 -0
- package/skills/code-review-expert/SKILL.md +118 -0
- package/skills/code-review-expert/references/code-quality-checklist.md +112 -0
- package/skills/code-review-expert/references/integration-checklist.md +46 -0
- package/skills/code-review-expert/references/removal-plan.md +52 -0
- package/skills/code-review-expert/references/security-checklist.md +100 -0
- package/skills/code-review-expert/references/solid-checklist.md +65 -0
- package/skills/codex-collab/SKILL.md +52 -0
- package/skills/codex-collab/evals/evals.json +40 -0
- package/skills/gemini-collab/SKILL.md +51 -0
- package/skills/gemini-collab/evals/evals.json +42 -0
- package/skills/integration-rules/SKILL.md +71 -0
- package/skills/learn/SKILL.md +117 -0
- package/skills/security-rules/SKILL.md +60 -0
- package/skills/testing-rules/SKILL.md +56 -0
- package/skills/ultra-deliver/SKILL.md +171 -0
- package/skills/ultra-dev/SKILL.md +324 -0
- package/skills/ultra-init/SKILL.md +148 -0
- package/skills/ultra-plan/SKILL.md +314 -0
- package/skills/ultra-research/SKILL.md +156 -0
- package/skills/ultra-research/steps/step-00-problem-validation.md +154 -0
- package/skills/ultra-research/steps/step-01-opportunity-discovery.md +172 -0
- package/skills/ultra-research/steps/step-02-market-assessment.md +195 -0
- package/skills/ultra-research/steps/step-03-competitive-landscape.md +197 -0
- package/skills/ultra-research/steps/step-04-product-strategy.md +196 -0
- package/skills/ultra-research/steps/step-05-assumptions-validation.md +234 -0
- package/skills/ultra-research/steps/step-10-user-personas.md +169 -0
- package/skills/ultra-research/steps/step-11-user-scenarios.md +181 -0
- package/skills/ultra-research/steps/step-20-user-stories.md +156 -0
- package/skills/ultra-research/steps/step-21-features-scope.md +157 -0
- package/skills/ultra-research/steps/step-22-success-metrics.md +195 -0
- package/skills/ultra-research/steps/step-30-architecture-context.md +154 -0
- package/skills/ultra-research/steps/step-31-solution-strategy.md +172 -0
- package/skills/ultra-research/steps/step-32-building-blocks.md +188 -0
- package/skills/ultra-research/steps/step-40-deployment.md +123 -0
- package/skills/ultra-research/steps/step-41-quality-risks.md +135 -0
- package/skills/ultra-research/steps/step-99-synthesis.md +188 -0
- package/skills/ultra-review/SKILL.md +437 -0
- package/skills/ultra-review/references/unified-schema.md +127 -0
- package/skills/ultra-review/scripts/review_verdict_update.py +99 -0
- package/skills/ultra-review/scripts/review_wait.py +120 -0
- package/skills/ultra-status/SKILL.md +162 -0
- package/skills/ultra-test/SKILL.md +195 -0
- package/skills/ultra-think/SKILL.md +109 -0
- package/skills/ultra-verify/SKILL.md +111 -0
- package/skills/ultra-verify/evals/evals.json +51 -0
- package/skills/ultra-verify/references/confidence-system.md +38 -0
- package/skills/ultra-verify/references/cross-verify-modes.md +73 -0
- package/skills/ultra-verify/scripts/verify_wait.py +131 -0
- package/spec/cli-protocol.md +118 -0
- package/spec/mcp-tools.yaml +658 -0
- package/spec/schemas/command-manifest.schema.json +47 -0
- package/spec/schemas/context-file.v4.5.schema.json +54 -0
- package/spec/schemas/mcp-tools.schema.json +136 -0
- package/spec/schemas/skill-manifest.schema.json +94 -0
- package/spec/schemas/state-db.sql +154 -0
- package/spec/schemas/tasks.v4.5.schema.json +66 -0
- package/ultra-tools/cli.cjs +121 -0
- package/ultra-tools/commands/db.cjs +175 -0
- package/ultra-tools/commands/legacy-memory.cjs +159 -0
- package/ultra-tools/commands/migrate.cjs +354 -0
- package/ultra-tools/commands/session.cjs +180 -0
- package/ultra-tools/commands/status.cjs +158 -0
- package/ultra-tools/commands/task.cjs +95 -0
- package/ultra-tools/legacy-memory.test.cjs +80 -0
- package/ultra-tools/status-command.test.cjs +132 -0
package/bin/install.js
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ultra-builder-pro-cli — multi-runtime installer.
|
|
5
|
+
*
|
|
6
|
+
* Distributes Ultra Builder Pro assets — commands, agents, skills, hooks,
|
|
7
|
+
* MCP server — to Claude Code, OpenCode, Codex CLI, and Gemini CLI via
|
|
8
|
+
* runtime-specific adapters under adapters/. Install is idempotent and
|
|
9
|
+
* uses atomic writes; uninstall reverses via sentinel/manifest blocks.
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* npx ultra-builder-pro-cli [options]
|
|
13
|
+
*
|
|
14
|
+
* --claude / --opencode / --codex / --gemini select runtime(s)
|
|
15
|
+
* --all install to all supported runtimes
|
|
16
|
+
* -g, --global install to runtime's global config dir
|
|
17
|
+
* -l, --local install into current working directory
|
|
18
|
+
* -u, --uninstall remove installed assets
|
|
19
|
+
* -c, --config-dir <path> override config directory
|
|
20
|
+
* --skip-rtk do not detect / install RTK hook
|
|
21
|
+
* -h, --help show help
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
'use strict';
|
|
25
|
+
|
|
26
|
+
const fs = require('node:fs');
|
|
27
|
+
const path = require('node:path');
|
|
28
|
+
const os = require('node:os');
|
|
29
|
+
|
|
30
|
+
const pkg = require('../package.json');
|
|
31
|
+
const { validateConfigDir } = require('../adapters/_shared/validate.cjs');
|
|
32
|
+
|
|
33
|
+
const SUPPORTED_RUNTIMES = ['claude', 'opencode', 'codex', 'gemini'];
|
|
34
|
+
|
|
35
|
+
const COLORS = {
|
|
36
|
+
reset: '\x1b[0m',
|
|
37
|
+
bold: '\x1b[1m',
|
|
38
|
+
dim: '\x1b[2m',
|
|
39
|
+
red: '\x1b[31m',
|
|
40
|
+
green: '\x1b[32m',
|
|
41
|
+
yellow: '\x1b[33m',
|
|
42
|
+
cyan: '\x1b[36m',
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
function paint(color, text) {
|
|
46
|
+
if (!process.stdout.isTTY) return text;
|
|
47
|
+
return `${COLORS[color] || ''}${text}${COLORS.reset}`;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function printBanner() {
|
|
51
|
+
const banner = [
|
|
52
|
+
'',
|
|
53
|
+
paint('cyan', ' ██╗ ██╗██████╗ ██████╗ ██████╗██╗ ██╗'),
|
|
54
|
+
paint('cyan', ' ██║ ██║██╔══██╗██╔══██╗ ██╔════╝██║ ██║'),
|
|
55
|
+
paint('cyan', ' ██║ ██║██████╔╝██████╔╝ ██║ ██║ ██║'),
|
|
56
|
+
paint('cyan', ' ██║ ██║██╔══██╗██╔═══╝ ██║ ██║ ██║'),
|
|
57
|
+
paint('cyan', ' ╚██████╔╝██████╔╝██║ ╚██████╗███████╗██║'),
|
|
58
|
+
paint('cyan', ' ╚═════╝ ╚═════╝ ╚═╝ ╚═════╝╚══════╝╚═╝'),
|
|
59
|
+
'',
|
|
60
|
+
` ${paint('bold', 'Ultra Builder Pro CLI')} ${paint('dim', 'v' + pkg.version)}`,
|
|
61
|
+
` ${paint('dim', 'Multi-runtime installer for Claude Code, OpenCode, Codex, Gemini')}`,
|
|
62
|
+
'',
|
|
63
|
+
];
|
|
64
|
+
console.log(banner.join('\n'));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function printHelp() {
|
|
68
|
+
console.log(` ${paint('yellow', 'Usage:')} npx ultra-builder-pro-cli [options]
|
|
69
|
+
|
|
70
|
+
${paint('yellow', 'Runtime selection (pick ≥1, or --all):')}
|
|
71
|
+
${paint('cyan', '--claude')} Claude Code
|
|
72
|
+
${paint('cyan', '--opencode')} OpenCode
|
|
73
|
+
${paint('cyan', '--codex')} Codex CLI (OpenAI)
|
|
74
|
+
${paint('cyan', '--gemini')} Gemini CLI (Google)
|
|
75
|
+
${paint('cyan', '--all')} all supported runtimes
|
|
76
|
+
|
|
77
|
+
${paint('yellow', 'Scope:')}
|
|
78
|
+
${paint('cyan', '-g, --global')} install to runtime's global config directory
|
|
79
|
+
${paint('cyan', '-l, --local')} install to current working directory
|
|
80
|
+
|
|
81
|
+
${paint('yellow', 'Other:')}
|
|
82
|
+
${paint('cyan', '-u, --uninstall')} remove installed assets
|
|
83
|
+
${paint('cyan', '-c, --config-dir')} override runtime's config directory (string path)
|
|
84
|
+
${paint('cyan', '--skip-rtk')} skip RTK hook registration (RTK is a soft dependency)
|
|
85
|
+
${paint('cyan', '-h, --help')} show this help
|
|
86
|
+
${paint('cyan', '-v, --version')} show CLI version
|
|
87
|
+
|
|
88
|
+
${paint('yellow', 'Examples:')}
|
|
89
|
+
${paint('dim', '# Install to Claude Code globally')}
|
|
90
|
+
npx ultra-builder-pro-cli --claude --global
|
|
91
|
+
|
|
92
|
+
${paint('dim', '# Install to all 4 runtimes locally in this repo')}
|
|
93
|
+
npx ultra-builder-pro-cli --all --local
|
|
94
|
+
|
|
95
|
+
${paint('dim', '# Uninstall from OpenCode')}
|
|
96
|
+
npx ultra-builder-pro-cli --opencode --global --uninstall
|
|
97
|
+
`);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function parseArgs(argv) {
|
|
101
|
+
const args = argv.slice(2);
|
|
102
|
+
const runtimes = new Set();
|
|
103
|
+
const flags = {
|
|
104
|
+
global: false,
|
|
105
|
+
local: false,
|
|
106
|
+
uninstall: false,
|
|
107
|
+
help: false,
|
|
108
|
+
version: false,
|
|
109
|
+
configDir: null,
|
|
110
|
+
skipRtk: false,
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
for (let i = 0; i < args.length; i++) {
|
|
114
|
+
const a = args[i];
|
|
115
|
+
switch (a) {
|
|
116
|
+
case '--claude': runtimes.add('claude'); break;
|
|
117
|
+
case '--opencode': runtimes.add('opencode'); break;
|
|
118
|
+
case '--codex': runtimes.add('codex'); break;
|
|
119
|
+
case '--gemini': runtimes.add('gemini'); break;
|
|
120
|
+
case '--all':
|
|
121
|
+
SUPPORTED_RUNTIMES.forEach(r => runtimes.add(r));
|
|
122
|
+
break;
|
|
123
|
+
case '-g': case '--global': flags.global = true; break;
|
|
124
|
+
case '-l': case '--local': flags.local = true; break;
|
|
125
|
+
case '-u': case '--uninstall': flags.uninstall = true; break;
|
|
126
|
+
case '-h': case '--help': flags.help = true; break;
|
|
127
|
+
case '-v': case '--version': flags.version = true; break;
|
|
128
|
+
case '--skip-rtk': flags.skipRtk = true; break;
|
|
129
|
+
case '-c': case '--config-dir':
|
|
130
|
+
flags.configDir = args[++i];
|
|
131
|
+
if (!flags.configDir || flags.configDir.startsWith('-')) {
|
|
132
|
+
bail(`--config-dir requires a path argument`);
|
|
133
|
+
}
|
|
134
|
+
{
|
|
135
|
+
const verdict = validateConfigDir(flags.configDir);
|
|
136
|
+
if (!verdict.ok) bail(verdict.error);
|
|
137
|
+
}
|
|
138
|
+
break;
|
|
139
|
+
default:
|
|
140
|
+
if (a.startsWith('--config-dir=')) {
|
|
141
|
+
flags.configDir = a.split('=')[1];
|
|
142
|
+
const verdict = validateConfigDir(flags.configDir);
|
|
143
|
+
if (!verdict.ok) bail(verdict.error);
|
|
144
|
+
} else if (a.startsWith('-')) {
|
|
145
|
+
bail(`unknown flag: ${a}`);
|
|
146
|
+
} else {
|
|
147
|
+
bail(`unexpected positional argument: ${a}`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return { runtimes: Array.from(runtimes), flags };
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function bail(msg) {
|
|
156
|
+
console.error(` ${paint('red', '✗')} ${msg}`);
|
|
157
|
+
console.error(` ${paint('dim', 'Run with --help for usage.')}`);
|
|
158
|
+
process.exit(1);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function expandTilde(p) {
|
|
162
|
+
if (p && p.startsWith('~/')) return path.join(os.homedir(), p.slice(2));
|
|
163
|
+
return p;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function loadAdapter(runtime) {
|
|
167
|
+
const adapterPath = path.join(__dirname, '..', 'adapters', `${runtime}.js`);
|
|
168
|
+
if (!fs.existsSync(adapterPath)) {
|
|
169
|
+
bail(`adapter not found for runtime: ${runtime}`);
|
|
170
|
+
}
|
|
171
|
+
return require(adapterPath);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function resolveScope(flags) {
|
|
175
|
+
if (flags.global && flags.local) bail('cannot use --global and --local together');
|
|
176
|
+
if (!flags.global && !flags.local) return 'local';
|
|
177
|
+
return flags.global ? 'global' : 'local';
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
async function main() {
|
|
181
|
+
const { runtimes, flags } = parseArgs(process.argv);
|
|
182
|
+
|
|
183
|
+
if (flags.version) {
|
|
184
|
+
console.log(`ultra-builder-pro-cli v${pkg.version}`);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
printBanner();
|
|
189
|
+
|
|
190
|
+
if (flags.help) {
|
|
191
|
+
printHelp();
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (runtimes.length === 0) {
|
|
196
|
+
bail('no runtime selected; use --claude / --opencode / --codex / --gemini / --all');
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const scope = resolveScope(flags);
|
|
200
|
+
const repoRoot = path.resolve(__dirname, '..');
|
|
201
|
+
const configDir = flags.configDir ? expandTilde(flags.configDir) : null;
|
|
202
|
+
|
|
203
|
+
const mode = flags.uninstall ? 'uninstall' : 'install';
|
|
204
|
+
console.log(` ${paint('bold', 'Mode:')} ${mode}`);
|
|
205
|
+
console.log(` ${paint('bold', 'Scope:')} ${scope}`);
|
|
206
|
+
console.log(` ${paint('bold', 'Runtimes:')} ${runtimes.join(', ')}`);
|
|
207
|
+
if (configDir) console.log(` ${paint('bold', 'ConfigDir:')} ${configDir}`);
|
|
208
|
+
console.log();
|
|
209
|
+
|
|
210
|
+
const ctx = { repoRoot, scope, configDir, homeDir: os.homedir() };
|
|
211
|
+
|
|
212
|
+
let failed = 0;
|
|
213
|
+
for (const runtime of runtimes) {
|
|
214
|
+
const adapter = loadAdapter(runtime);
|
|
215
|
+
try {
|
|
216
|
+
console.log(` ${paint('cyan', '▸')} ${runtime} — starting ${mode}...`);
|
|
217
|
+
await adapter[mode](ctx);
|
|
218
|
+
console.log(` ${paint('green', '✓')} ${runtime} — ${mode} complete`);
|
|
219
|
+
} catch (err) {
|
|
220
|
+
failed++;
|
|
221
|
+
console.error(` ${paint('red', '✗')} ${runtime} — ${mode} failed: ${err.message}`);
|
|
222
|
+
if (process.env.UBP_DEBUG) console.error(err.stack);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
console.log();
|
|
227
|
+
if (failed > 0) {
|
|
228
|
+
console.error(` ${paint('red', `${failed} runtime(s) failed`)}`);
|
|
229
|
+
process.exit(1);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Phase 6.1 — RTK hook (soft dependency; install continues on absence).
|
|
233
|
+
if (mode === 'install') {
|
|
234
|
+
const rtk = require('../adapters/_shared/rtk-detect.cjs');
|
|
235
|
+
const result = rtk.installHook({ skip: flags.skipRtk, scope });
|
|
236
|
+
if (result.skipped) {
|
|
237
|
+
console.log(` ${paint('dim', '⤼ rtk skipped (--skip-rtk)')}`);
|
|
238
|
+
} else if (result.available && result.initialized) {
|
|
239
|
+
console.log(` ${paint('green', '✓')} rtk hook registered (${result.version})`);
|
|
240
|
+
} else if (result.available && !result.initialized) {
|
|
241
|
+
console.log(` ${paint('yellow', '!')} rtk present but init failed: ${result.init_error}`);
|
|
242
|
+
} else {
|
|
243
|
+
console.log(` ${paint('dim', '⤼ ' + result.hint.replace(/\n/g, '\n '))}`);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
console.log(` ${paint('green', 'Done.')}`);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
main().catch(err => {
|
|
251
|
+
console.error(paint('red', ' Fatal: ') + err.message);
|
|
252
|
+
if (process.env.UBP_DEBUG) console.error(err.stack);
|
|
253
|
+
process.exit(1);
|
|
254
|
+
});
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ubp-orchestrator — Phase 5.4 daemon CLI.
|
|
5
|
+
*
|
|
6
|
+
* Subcommands:
|
|
7
|
+
* run foreground daemon (debug / test).
|
|
8
|
+
* start detached background daemon, writes .ultra/orchestrator.pid.
|
|
9
|
+
* stop reads pidfile, SIGTERM the process, deletes pidfile.
|
|
10
|
+
* status prints pidfile + running session summary.
|
|
11
|
+
*
|
|
12
|
+
* Opt-in gate: `start` and `run` require settings.json
|
|
13
|
+
* `orchestrator.auto_dispatch: true` — default off per PLAN Phase 5.4 AC.
|
|
14
|
+
*
|
|
15
|
+
* The daemon never launches real runtime children in this phase — session
|
|
16
|
+
* rows + git worktrees are created, external adapters (Phase 4) attach to
|
|
17
|
+
* the worktree out-of-band. command/args can be passed via env for testing.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
'use strict';
|
|
21
|
+
|
|
22
|
+
const fs = require('node:fs');
|
|
23
|
+
const path = require('node:path');
|
|
24
|
+
const { spawn } = require('node:child_process');
|
|
25
|
+
|
|
26
|
+
const REPO_ROOT = process.env.UBP_REPO_ROOT || process.cwd();
|
|
27
|
+
const PIDFILE = path.join(REPO_ROOT, '.ultra', 'orchestrator.pid');
|
|
28
|
+
const LOGFILE = path.join(REPO_ROOT, '.ultra', 'orchestrator.log');
|
|
29
|
+
const SETTINGS_FILES = [
|
|
30
|
+
path.join(REPO_ROOT, 'settings.json'),
|
|
31
|
+
path.join(REPO_ROOT, '.claude', 'settings.json'),
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
function readSettings() {
|
|
35
|
+
for (const f of SETTINGS_FILES) {
|
|
36
|
+
if (fs.existsSync(f)) {
|
|
37
|
+
try { return JSON.parse(fs.readFileSync(f, 'utf8')) || {}; }
|
|
38
|
+
catch { /* fall through */ }
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return {};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function optInAllowed(settings) {
|
|
45
|
+
return !!(settings && settings.orchestrator && settings.orchestrator.auto_dispatch === true);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function parseRuntimes() {
|
|
49
|
+
const raw = process.env.UBP_ORCH_RUNTIMES || 'claude,opencode,codex,gemini';
|
|
50
|
+
return raw.split(',').map((s) => s.trim()).filter(Boolean);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function cmdRun(opts = {}) {
|
|
54
|
+
const settings = readSettings();
|
|
55
|
+
if (!opts.skipOptIn && !optInAllowed(settings)) {
|
|
56
|
+
process.stderr.write(
|
|
57
|
+
'orchestrator.auto_dispatch is not enabled in settings.json.\n' +
|
|
58
|
+
'Set {"orchestrator":{"auto_dispatch":true}} to opt in.\n',
|
|
59
|
+
);
|
|
60
|
+
process.exit(2);
|
|
61
|
+
}
|
|
62
|
+
const { initStateDb } = require('../mcp-server/lib/state-db.cjs');
|
|
63
|
+
const { runDaemon } = require('../orchestrator/daemon.cjs');
|
|
64
|
+
const { db } = initStateDb(path.join(REPO_ROOT, '.ultra', 'state.db'));
|
|
65
|
+
const handle = runDaemon({
|
|
66
|
+
db,
|
|
67
|
+
repoRoot: REPO_ROOT,
|
|
68
|
+
runtimes: parseRuntimes(),
|
|
69
|
+
pollMs: Number(process.env.UBP_ORCH_POLL_MS || 1000),
|
|
70
|
+
onError: (err) => process.stderr.write(`orchestrator error: ${err.message}\n`),
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// Phase 6.4 — optional code-graph watcher (opt-in via settings or CLI).
|
|
74
|
+
const watcherEnabled =
|
|
75
|
+
opts.withGraphWatcher === true ||
|
|
76
|
+
!!(settings && settings.orchestrator && settings.orchestrator.graph_watcher === true);
|
|
77
|
+
let watcherHandle = null;
|
|
78
|
+
if (watcherEnabled) {
|
|
79
|
+
try {
|
|
80
|
+
const { startWatcher } = require('../orchestrator/code-graph-watcher.cjs');
|
|
81
|
+
const jsonlPath = path.join(REPO_ROOT, '.ultra', 'code-graph-events.jsonl');
|
|
82
|
+
fs.mkdirSync(path.dirname(jsonlPath), { recursive: true });
|
|
83
|
+
watcherHandle = startWatcher({
|
|
84
|
+
repoRoot: REPO_ROOT,
|
|
85
|
+
onBatch: (batch) => {
|
|
86
|
+
try { fs.appendFileSync(jsonlPath, JSON.stringify(batch) + '\n'); }
|
|
87
|
+
catch (err) { process.stderr.write(`graph-watcher write error: ${err.message}\n`); }
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
process.stderr.write(`orchestrator: graph-watcher enabled → ${jsonlPath}\n`);
|
|
91
|
+
} catch (err) {
|
|
92
|
+
process.stderr.write(`orchestrator: graph-watcher disabled (${err.message})\n`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const shutdown = (signal) => {
|
|
97
|
+
process.stderr.write(`orchestrator received ${signal}, stopping\n`);
|
|
98
|
+
handle.stop();
|
|
99
|
+
if (watcherHandle) watcherHandle.stop();
|
|
100
|
+
try { db.close(); } catch (_) { /* ignore */ }
|
|
101
|
+
process.exit(0);
|
|
102
|
+
};
|
|
103
|
+
process.on('SIGTERM', () => shutdown('SIGTERM'));
|
|
104
|
+
process.on('SIGINT', () => shutdown('SIGINT'));
|
|
105
|
+
process.stderr.write(`orchestrator running (pollMs=${Number(process.env.UBP_ORCH_POLL_MS || 1000)}, runtimes=${parseRuntimes().join(',')})\n`);
|
|
106
|
+
// Keep process alive while the setInterval is unref'd.
|
|
107
|
+
setInterval(() => {}, 60000);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function cmdStart() {
|
|
111
|
+
const settings = readSettings();
|
|
112
|
+
if (!optInAllowed(settings)) {
|
|
113
|
+
process.stderr.write('orchestrator.auto_dispatch is not enabled; refusing to start.\n');
|
|
114
|
+
process.exit(2);
|
|
115
|
+
}
|
|
116
|
+
if (fs.existsSync(PIDFILE)) {
|
|
117
|
+
const existing = Number(fs.readFileSync(PIDFILE, 'utf8'));
|
|
118
|
+
try { process.kill(existing, 0); }
|
|
119
|
+
catch (_) { fs.unlinkSync(PIDFILE); }
|
|
120
|
+
if (fs.existsSync(PIDFILE)) {
|
|
121
|
+
process.stderr.write(`orchestrator already running (pid=${existing}).\n`);
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
fs.mkdirSync(path.dirname(PIDFILE), { recursive: true });
|
|
126
|
+
const out = fs.openSync(LOGFILE, 'a');
|
|
127
|
+
const err = fs.openSync(LOGFILE, 'a');
|
|
128
|
+
const child = spawn(process.execPath, [__filename, 'run'], {
|
|
129
|
+
detached: true,
|
|
130
|
+
stdio: ['ignore', out, err],
|
|
131
|
+
env: { ...process.env, UBP_REPO_ROOT: REPO_ROOT },
|
|
132
|
+
});
|
|
133
|
+
child.unref();
|
|
134
|
+
fs.writeFileSync(PIDFILE, String(child.pid));
|
|
135
|
+
process.stdout.write(`orchestrator started (pid=${child.pid}, log=${LOGFILE})\n`);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function cmdStop() {
|
|
139
|
+
if (!fs.existsSync(PIDFILE)) {
|
|
140
|
+
process.stderr.write('no pidfile found; orchestrator not running.\n');
|
|
141
|
+
process.exit(1);
|
|
142
|
+
}
|
|
143
|
+
const pid = Number(fs.readFileSync(PIDFILE, 'utf8'));
|
|
144
|
+
try { process.kill(pid, 'SIGTERM'); }
|
|
145
|
+
catch (err) {
|
|
146
|
+
if (err.code === 'ESRCH') {
|
|
147
|
+
process.stderr.write(`pid ${pid} already dead; cleaning pidfile.\n`);
|
|
148
|
+
fs.unlinkSync(PIDFILE);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
throw err;
|
|
152
|
+
}
|
|
153
|
+
// Wait briefly for the process to exit, then clean up.
|
|
154
|
+
setTimeout(() => {
|
|
155
|
+
try { process.kill(pid, 0); }
|
|
156
|
+
catch (_) { /* dead; good */ }
|
|
157
|
+
if (fs.existsSync(PIDFILE)) fs.unlinkSync(PIDFILE);
|
|
158
|
+
process.stdout.write(`orchestrator stopped (pid=${pid})\n`);
|
|
159
|
+
}, 200);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function cmdStatus() {
|
|
163
|
+
const out = { pidfile: PIDFILE, running: false };
|
|
164
|
+
if (fs.existsSync(PIDFILE)) {
|
|
165
|
+
const pid = Number(fs.readFileSync(PIDFILE, 'utf8'));
|
|
166
|
+
try { process.kill(pid, 0); out.pid = pid; out.running = true; }
|
|
167
|
+
catch (_) { out.pid = pid; out.running = false; out.note = 'pidfile stale'; }
|
|
168
|
+
}
|
|
169
|
+
// Session summary.
|
|
170
|
+
try {
|
|
171
|
+
const Database = require('better-sqlite3');
|
|
172
|
+
const dbPath = path.join(REPO_ROOT, '.ultra', 'state.db');
|
|
173
|
+
if (fs.existsSync(dbPath)) {
|
|
174
|
+
const db = new Database(dbPath, { readonly: true });
|
|
175
|
+
const counts = db.prepare(
|
|
176
|
+
"SELECT status, COUNT(*) AS n FROM sessions GROUP BY status",
|
|
177
|
+
).all();
|
|
178
|
+
out.sessions = {};
|
|
179
|
+
for (const r of counts) out.sessions[r.status] = r.n;
|
|
180
|
+
db.close();
|
|
181
|
+
}
|
|
182
|
+
} catch (err) {
|
|
183
|
+
out.session_error = err.message;
|
|
184
|
+
}
|
|
185
|
+
process.stdout.write(`${JSON.stringify(out, null, 2)}\n`);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function usage() {
|
|
189
|
+
process.stderr.write(
|
|
190
|
+
'usage: ubp-orchestrator <run|start|stop|status>\n' +
|
|
191
|
+
'\n' +
|
|
192
|
+
' run foreground daemon (requires opt-in)\n' +
|
|
193
|
+
' start detached background daemon (requires opt-in)\n' +
|
|
194
|
+
' stop terminate running daemon\n' +
|
|
195
|
+
' status print pid + session counts\n',
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const argv = process.argv.slice(2);
|
|
200
|
+
const subcommand = argv[0];
|
|
201
|
+
const runOpts = { withGraphWatcher: argv.includes('--with-graph-watcher') };
|
|
202
|
+
switch (subcommand) {
|
|
203
|
+
case 'run': cmdRun(runOpts); break;
|
|
204
|
+
case 'start': cmdStart(); break;
|
|
205
|
+
case 'stop': cmdStop(); break;
|
|
206
|
+
case 'status': cmdStatus(); break;
|
|
207
|
+
case '-h':
|
|
208
|
+
case '--help':
|
|
209
|
+
case 'help':
|
|
210
|
+
usage(); process.exit(0);
|
|
211
|
+
break;
|
|
212
|
+
default:
|
|
213
|
+
usage(); process.exit(1);
|
|
214
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Extract one reusable pattern into a valid user skill after explicit approval
|
|
3
|
+
argument-hint: "[pattern-name]"
|
|
4
|
+
allowed-tools: Read, Write, Grep, Glob, AskUserQuestion
|
|
5
|
+
model: opus
|
|
6
|
+
workflow-ref: "@skills/learn/SKILL.md"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# /learn
|
|
10
|
+
|
|
11
|
+
## 目标
|
|
12
|
+
|
|
13
|
+
扫当前会话挑一个最值得保存的「可复用模式」,以 Speculation 级别写到
|
|
14
|
+
`~/.claude/skills/learned-<slug>-unverified/SKILL.md`。写入前必问用户确认。
|
|
15
|
+
|
|
16
|
+
## 参数
|
|
17
|
+
|
|
18
|
+
| 位 | 含义 | 缺省 |
|
|
19
|
+
|----|------|------|
|
|
20
|
+
| `$1` | pattern 文件名建议 slug | 由 skill 自动生成 |
|
|
21
|
+
|
|
22
|
+
## Workflow
|
|
23
|
+
|
|
24
|
+
完整 5 步见 `@skills/learn/SKILL.md`(review → pick one → draft → 用户确认 → write)。
|
|
25
|
+
|
|
26
|
+
**命令入口做的事**:
|
|
27
|
+
1. 回溯会话找可提炼的模式(错误修复 / 调试套路 / workaround / 项目级惯例)
|
|
28
|
+
2. 选一个价值最高的(不是多个 — 一个文件一个模式)
|
|
29
|
+
3. 按模板起草 → 直接询问用户选择 Save/Edit/Cancel
|
|
30
|
+
4. 保存到 `~/.claude/skills/learned-<slug>-unverified/SKILL.md`(不覆盖已存在目录)
|
|
31
|
+
|
|
32
|
+
## 用法
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
/learn # 自动挑
|
|
36
|
+
/learn supabase-rls-debug # 指定文件名 slug
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## 下一步
|
|
40
|
+
|
|
41
|
+
用户以后 review 后手动去掉 `_unverified` 后缀升为 Inference;多次成功使用后升为 Fact。
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Release preparation — docs + build + version bump + tag + push, gated by /ultra-test pass
|
|
3
|
+
argument-hint: "[version-type]"
|
|
4
|
+
allowed-tools: Task, Read, Write, Edit, Bash, Grep, Glob, AskUserQuestion
|
|
5
|
+
model: opus
|
|
6
|
+
workflow-ref: "@skills/ultra-deliver/SKILL.md"
|
|
7
|
+
cli_fallback: "direct user interaction"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# /ultra-deliver
|
|
11
|
+
|
|
12
|
+
## 目标
|
|
13
|
+
|
|
14
|
+
`/ultra-test` 绿灯后做发布准备:更新 CHANGELOG + technical-debt + README →
|
|
15
|
+
production build → 版本号 + git tag + push。写 `.ultra/delivery-report.json`。
|
|
16
|
+
|
|
17
|
+
## 参数
|
|
18
|
+
|
|
19
|
+
| 位 | 含义 | 缺省 |
|
|
20
|
+
|----|------|------|
|
|
21
|
+
| `$1` | 版本跳跃(`patch`/`minor`/`major`) | 按 commit 类型自动判断 |
|
|
22
|
+
|
|
23
|
+
## Workflow
|
|
24
|
+
|
|
25
|
+
完整 5 步见 `@skills/ultra-deliver/SKILL.md`(validations → 文档 → build → 版本发布 → 产物报告)。
|
|
26
|
+
|
|
27
|
+
**命令入口做的事**:
|
|
28
|
+
1. 读 `.ultra/test-report.json` 验 `passed=true` + `git_commit === HEAD`
|
|
29
|
+
2. `git status` 清洁检查;不干净 → 通过 Host 原生提问界面选处理方式
|
|
30
|
+
3. 驱动 skill 跑文档 + build + 版本 + tag + push
|
|
31
|
+
4. 写 `.ultra/delivery-report.json`
|
|
32
|
+
5. 输出 release summary
|
|
33
|
+
|
|
34
|
+
## 用法
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
/ultra-deliver # 自动判断版本号
|
|
38
|
+
/ultra-deliver major # 强制 major bump(breaking changes)
|
|
39
|
+
/ultra-deliver patch # 强制 patch
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## 下一步
|
|
43
|
+
|
|
44
|
+
部署到 Railway / Vercel,或在 release channel 广播。`delivery-report.json` 里
|
|
45
|
+
`pushed=true` 后即可视作发布完成。
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Agile development execution — one task through TDD + review gate, writing state via MCP task.update
|
|
3
|
+
argument-hint: "[task-id]"
|
|
4
|
+
allowed-tools: Read, Write, Edit, Bash, Grep, Glob, Task, AskUserQuestion, Skill
|
|
5
|
+
model: opus
|
|
6
|
+
workflow-ref: "@skills/ultra-dev/SKILL.md"
|
|
7
|
+
mcp_tools_required:
|
|
8
|
+
- task.update
|
|
9
|
+
- task.get
|
|
10
|
+
- task.list
|
|
11
|
+
cli_fallback: "task update"
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# /ultra-dev
|
|
15
|
+
|
|
16
|
+
## 目标
|
|
17
|
+
|
|
18
|
+
把一个 task 从 `pending` 推到 `completed`:进入 feature 分支 → RED/GREEN/REFACTOR
|
|
19
|
+
TDD → 质量门 → `/ultra-review all` → 完成 → commit/merge。**单写**:状态只通过
|
|
20
|
+
MCP `task.update` 改一次;projector 自动更新 tasks.json + context-md frontmatter。
|
|
21
|
+
|
|
22
|
+
## 参数
|
|
23
|
+
|
|
24
|
+
| 位 | 含义 | 缺省 |
|
|
25
|
+
|----|------|------|
|
|
26
|
+
| `$1` | task id | 拓扑序第一个 `pending` |
|
|
27
|
+
|
|
28
|
+
## Workflow
|
|
29
|
+
|
|
30
|
+
完整 8 步流程见 `@skills/ultra-dev/SKILL.md`(Resume Check → Design Gate → 选 task →
|
|
31
|
+
状态 in_progress → 环境 → TDD → 质量门 → checkpoint → review → 完成 → commit/merge → report)。
|
|
32
|
+
|
|
33
|
+
**命令入口做的事**:
|
|
34
|
+
1. 读 `.ultra/workflow-state.json` 决定新跑 vs resume
|
|
35
|
+
2. 首跑通过 Host 原生提问触发 Design Approval Gate
|
|
36
|
+
3. 驱动 skill 走 TDD + review 循环;状态仅通过 MCP `task.update`(双写消除)
|
|
37
|
+
4. Step 4.5 review 通过 `/ultra-review` 和 Host 原生 subagent 执行
|
|
38
|
+
5. Step 4.4 pre-review checkpoint 写入 workflow-state.json,不依赖 `/compact`
|
|
39
|
+
|
|
40
|
+
## 用法
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
/ultra-dev # 自动选下一个 pending task
|
|
44
|
+
/ultra-dev 3 # 直接做 task 3
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## 下一步
|
|
48
|
+
|
|
49
|
+
单个 task 完成后自动提示下一个 `/ultra-dev`;所有 Walking Skeleton +
|
|
50
|
+
critical-path task 完成 → `/ultra-test` 做交付前质量审计。
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Initialize Ultra Builder Pro project — scaffold .ultra/, seed tasks.json, optional git
|
|
3
|
+
argument-hint: <name> <type> <stack> [git]
|
|
4
|
+
allowed-tools: Read, Write, Bash, Grep, Glob, AskUserQuestion
|
|
5
|
+
model: opus
|
|
6
|
+
workflow-ref: "@skills/ultra-init/SKILL.md"
|
|
7
|
+
mcp_tools_required:
|
|
8
|
+
- task.init_project
|
|
9
|
+
cli_fallback: "task init-project"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# /ultra-init
|
|
13
|
+
|
|
14
|
+
## 目标
|
|
15
|
+
|
|
16
|
+
搭 `.ultra/` 骨架(specs + tasks + docs + reports);写入带元数据的 `tasks.json`;
|
|
17
|
+
按需初始化 git。4 个 runtime 行为一致,不依赖 Claude 独占工具。
|
|
18
|
+
|
|
19
|
+
## 参数
|
|
20
|
+
|
|
21
|
+
| 位 | 含义 | 缺省 |
|
|
22
|
+
|----|------|------|
|
|
23
|
+
| `$1` | 项目名 | 当前目录名 |
|
|
24
|
+
| `$2` | 项目类型(`web`/`api`/`cli`/`fullstack`/`other`) | 从 package 文件识别 |
|
|
25
|
+
| `$3` | 技术栈(逗号分隔) | 从 package 文件识别 |
|
|
26
|
+
| `$4` | `git` → 初始化 git | 检测已有 `.git/` 时询问 |
|
|
27
|
+
|
|
28
|
+
## Workflow
|
|
29
|
+
|
|
30
|
+
完整流程见 `@skills/ultra-init/SKILL.md`(4 步:状态检测 → 参数补全 →
|
|
31
|
+
`task.init_project` 拉起骨架 → git 集成)。
|
|
32
|
+
|
|
33
|
+
**命令入口做的事**:
|
|
34
|
+
1. 解析 `$1-$4`,补缺省
|
|
35
|
+
2. 探测 runtime 能力:优先走 MCP `task.init_project`;不可达时退回 `ultra-tools task init-project`
|
|
36
|
+
3. 按 skill 的 4 步工作流推进
|
|
37
|
+
4. 完成后提示下一步命令
|
|
38
|
+
|
|
39
|
+
## 用法
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
/ultra-init # 交互模式(自动识别)
|
|
43
|
+
/ultra-init my-app # 带项目名
|
|
44
|
+
/ultra-init my-app api # 带类型
|
|
45
|
+
/ultra-init my-app fullstack react,postgres git # 完整 + git
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## 下一步
|
|
49
|
+
|
|
50
|
+
**CRITICAL**:跑 `/ultra-research` 做 17 步 discovery 把 spec 填满,
|
|
51
|
+
**然后**才跑 `/ultra-plan` 生成任务。直接 plan 会产出基于模糊需求的任务。
|