ultra-builder-pro-cli 0.11.0 → 0.12.1
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/specs/architecture.md +54 -223
- package/.ultra-template/specs/discovery.md +34 -231
- package/.ultra-template/specs/product.md +44 -200
- package/.ultra-template/tasks/contexts/TEMPLATE.md +36 -0
- package/.ultra-template/tasks/tasks.json +6 -0
- package/CHANGELOG.md +42 -1
- package/README.md +21 -9
- package/adapters/_shared/codex-assets.cjs +1 -1
- package/adapters/_shared/handbook.cjs +4 -3
- package/adapters/_shared/tests/handbook.test.cjs +4 -0
- package/adapters/opencode.js +8 -2
- package/adapters/tests/codex.test.cjs +2 -2
- package/adapters/tests/kimi-hook.test.cjs +1 -1
- package/adapters/tests/opencode.test.cjs +36 -1
- package/commands/ultra-init.md +3 -3
- package/docs/AGENT-CONTEXT.md +16 -8
- package/docs/ARCHITECTURE.md +32 -5
- package/docs/PLAN.zh-CN.md +7 -5
- package/docs/ROADMAP.md +4 -2
- package/docs/RUNTIME-COMPAT-MATRIX.md +8 -5
- package/docs/STATE-DB-ACCESS-POLICY.md +17 -11
- package/docs/USER-HANDBOOK-CONTRACT.md +8 -5
- package/hooks/README.md +4 -3
- package/hooks/adapters/codex.py +1 -1
- package/hooks/adapters/kimi.py +1 -1
- package/hooks/context_spine.py +120 -16
- package/hooks/health_check.py +11 -0
- package/hooks/pre_stop_check.py +6 -5
- package/mcp-server/lib/baseline-workflow.cjs +415 -0
- package/mcp-server/lib/baseline-workflow.test.cjs +225 -0
- package/mcp-server/lib/change-workflow.cjs +24 -27
- package/mcp-server/lib/change-workflow.test.cjs +202 -6
- package/mcp-server/lib/context-spine.cjs +74 -9
- package/mcp-server/lib/context-spine.test.cjs +15 -0
- package/mcp-server/lib/doctor.cjs +14 -0
- package/mcp-server/lib/doctor.test.cjs +25 -1
- package/mcp-server/lib/init-project.cjs +49 -14
- package/mcp-server/lib/provider-refs.cjs +42 -0
- package/mcp-server/lib/spec-learning.test.cjs +5 -0
- package/mcp-server/lib/state-db.cjs +63 -4
- package/mcp-server/lib/state-db.test.cjs +8 -3
- package/mcp-server/server.cjs +48 -3
- package/mcp-server/tests/init-project.test.cjs +54 -8
- package/mcp-server/tests/server-contract.test.cjs +99 -2
- package/mcp-server/tests/state-db.test.cjs +11 -2
- package/package.json +1 -1
- package/skills/ultra-change/SKILL.md +24 -13
- package/skills/ultra-deliver/SKILL.md +15 -5
- package/skills/ultra-dev/SKILL.md +4 -0
- package/skills/ultra-doctor/SKILL.md +8 -2
- package/skills/ultra-init/SKILL.md +46 -50
- package/skills/ultra-init/references/brownfield-adoption.md +65 -0
- package/skills/ultra-plan/SKILL.md +9 -2
- package/skills/ultra-research/SKILL.md +10 -5
- package/skills/ultra-status/SKILL.md +13 -6
- package/spec/cli-protocol.md +4 -0
- package/spec/mcp-tools.yaml +223 -4
- package/spec/schemas/mcp-tools.schema.json +1 -1
- package/spec/schemas/state-db.sql +33 -2
- package/ultra-tools/commands/status.cjs +20 -2
- package/ultra-tools/commands/task.cjs +4 -1
- package/ultra-tools/status-command.test.cjs +20 -0
- package/ultra-tools/system-command.test.cjs +5 -0
|
@@ -10,6 +10,7 @@ const fs = require('node:fs');
|
|
|
10
10
|
const path = require('node:path');
|
|
11
11
|
|
|
12
12
|
const ops = require('../../mcp-server/lib/state-ops.cjs');
|
|
13
|
+
const baselines = require('../../mcp-server/lib/baseline-workflow.cjs');
|
|
13
14
|
|
|
14
15
|
const USAGE = `ultra-tools status [flags]
|
|
15
16
|
|
|
@@ -64,12 +65,23 @@ function parseFlags(args) {
|
|
|
64
65
|
return out;
|
|
65
66
|
}
|
|
66
67
|
|
|
67
|
-
function buildCostPanel(db, { since = null, limit = 3 } = {}) {
|
|
68
|
+
function buildCostPanel(db, { since = null, limit = 3, rootDir = process.cwd() } = {}) {
|
|
68
69
|
const by_runtime = ops.aggregateTelemetryByRuntime(db, { since });
|
|
69
70
|
const top_tasks = ops.aggregateTelemetryByTask(db, { since, limit });
|
|
70
71
|
const total_cost_usd = by_runtime.reduce((acc, r) => acc + (r.cost_usd || 0), 0);
|
|
72
|
+
const baselineHealth = baselines.inspectBaseline(db, { rootDir });
|
|
73
|
+
const current = baselineHealth.baseline;
|
|
71
74
|
return {
|
|
72
75
|
period: { since: since || 'all-time' },
|
|
76
|
+
baseline: {
|
|
77
|
+
id: current?.id || null,
|
|
78
|
+
mode: current?.mode || null,
|
|
79
|
+
status: current?.status || 'missing',
|
|
80
|
+
health: baselineHealth.status,
|
|
81
|
+
repository_revision: current?.repository_revision || null,
|
|
82
|
+
blockers: baselineHealth.blockers,
|
|
83
|
+
warnings: baselineHealth.warnings,
|
|
84
|
+
},
|
|
73
85
|
by_runtime,
|
|
74
86
|
top_tasks,
|
|
75
87
|
total_cost_usd,
|
|
@@ -84,6 +96,11 @@ function formatCost(n) {
|
|
|
84
96
|
|
|
85
97
|
function renderHuman(panel) {
|
|
86
98
|
const lines = [];
|
|
99
|
+
const baseline = panel.baseline;
|
|
100
|
+
lines.push(
|
|
101
|
+
`Baseline: ${baseline.mode || 'none'}/${baseline.status} · ${baseline.health === 'pass' ? 'ready' : 'blocked'}`,
|
|
102
|
+
);
|
|
103
|
+
if (baseline.blockers.length > 0) lines.push(`Baseline blockers: ${baseline.blockers.join(', ')}`);
|
|
87
104
|
lines.push(`Period: ${panel.period.since}`);
|
|
88
105
|
lines.push(`Total cost: ${formatCost(panel.total_cost_usd)}`);
|
|
89
106
|
lines.push('');
|
|
@@ -136,7 +153,8 @@ function dispatch(args) {
|
|
|
136
153
|
const Database = require('better-sqlite3');
|
|
137
154
|
const db = new Database(dbPath, { readonly: true });
|
|
138
155
|
try {
|
|
139
|
-
const
|
|
156
|
+
const rootDir = path.dirname(path.dirname(dbPath));
|
|
157
|
+
const panel = buildCostPanel(db, { since, limit: flags.limit, rootDir });
|
|
140
158
|
if (flags.json) {
|
|
141
159
|
emit({ ok: true, data: panel });
|
|
142
160
|
} else {
|
|
@@ -9,13 +9,14 @@ const { initProject, InitProjectError } = require('../../mcp-server/lib/init-pro
|
|
|
9
9
|
const USAGE = `ultra-tools task <verb> [flags]
|
|
10
10
|
|
|
11
11
|
VERBS:
|
|
12
|
-
init-project
|
|
12
|
+
init-project Initialize or adopt a project with authoritative Ultra state
|
|
13
13
|
|
|
14
14
|
FLAGS (init-project):
|
|
15
15
|
--target-dir <path> target project root (default: cwd)
|
|
16
16
|
--project-name <name> project name (required)
|
|
17
17
|
--project-type <type> web | api | cli | fullstack | other
|
|
18
18
|
--stack <stack> tech stack descriptor (comma-separated ok)
|
|
19
|
+
--mode <mode> auto | greenfield | brownfield (default: auto)
|
|
19
20
|
--overwrite replace existing .ultra/ (backup created)
|
|
20
21
|
--source-template <path> override bundled template source
|
|
21
22
|
-h, --help show this message
|
|
@@ -34,6 +35,7 @@ function parseInitFlags(args) {
|
|
|
34
35
|
case '--project-name': flags.project_name = args[++i]; break;
|
|
35
36
|
case '--project-type': flags.project_type = args[++i]; break;
|
|
36
37
|
case '--stack': flags.stack = args[++i]; break;
|
|
38
|
+
case '--mode': flags.mode = args[++i]; break;
|
|
37
39
|
case '--source-template': flags.source_template = args[++i]; break;
|
|
38
40
|
case '--overwrite': flags.overwrite = true; break;
|
|
39
41
|
case '--no-overwrite': flags.overwrite = false; break;
|
|
@@ -59,6 +61,7 @@ function dispatchInitProject(rawArgs) {
|
|
|
59
61
|
project_name: flags.project_name,
|
|
60
62
|
project_type: flags.project_type,
|
|
61
63
|
stack: flags.stack,
|
|
64
|
+
mode: flags.mode || 'auto',
|
|
62
65
|
overwrite: !!flags.overwrite,
|
|
63
66
|
source_template: flags.source_template,
|
|
64
67
|
};
|
|
@@ -63,6 +63,26 @@ test('buildCostPanel: empty db → zero totals, empty arrays', () => {
|
|
|
63
63
|
assert.equal(out.total_cost_usd, 0);
|
|
64
64
|
assert.equal(out.by_runtime.length, 0);
|
|
65
65
|
assert.equal(out.top_tasks.length, 0);
|
|
66
|
+
assert.deepEqual(out.baseline, {
|
|
67
|
+
id: null, mode: null, status: 'missing', health: 'fail',
|
|
68
|
+
repository_revision: null, blockers: ['BASELINE_MISSING'], warnings: [],
|
|
69
|
+
});
|
|
70
|
+
} finally { teardown(dir, db); }
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test('status exposes an in-progress brownfield baseline from authoritative state', () => {
|
|
74
|
+
const { dir, db } = freshFixture();
|
|
75
|
+
try {
|
|
76
|
+
db.prepare(
|
|
77
|
+
`INSERT INTO baselines (id, project_name, mode, status)
|
|
78
|
+
VALUES ('adoption', 'legacy', 'brownfield', 'adopting')`,
|
|
79
|
+
).run();
|
|
80
|
+
const out = statusCmd.buildCostPanel(db, { rootDir: dir });
|
|
81
|
+
assert.equal(out.baseline.id, 'adoption');
|
|
82
|
+
assert.equal(out.baseline.mode, 'brownfield');
|
|
83
|
+
assert.equal(out.baseline.status, 'adopting');
|
|
84
|
+
assert.deepEqual(out.baseline.blockers, ['BASELINE_NOT_READY:adopting']);
|
|
85
|
+
assert.match(statusCmd.renderHuman(out), /Baseline: brownfield\/adopting.*blocked/i);
|
|
66
86
|
} finally { teardown(dir, db); }
|
|
67
87
|
});
|
|
68
88
|
|
|
@@ -14,6 +14,11 @@ const CLI = path.join(__dirname, 'cli.cjs');
|
|
|
14
14
|
function fixture() {
|
|
15
15
|
const rootDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ubp-system-cli-'));
|
|
16
16
|
const { db } = initStateDb(path.join(rootDir, '.ultra', 'state.db'));
|
|
17
|
+
db.prepare(
|
|
18
|
+
`INSERT INTO baselines
|
|
19
|
+
(id, project_name, mode, status, approved_by, approval_note, converged_at)
|
|
20
|
+
VALUES ('test-baseline', 'fixture', 'migrated', 'ready', 'test', 'legacy fixture', ?)`,
|
|
21
|
+
).run(new Date().toISOString());
|
|
17
22
|
closeStateDb(db);
|
|
18
23
|
return rootDir;
|
|
19
24
|
}
|