ultra-builder-pro-cli 0.13.0 → 0.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/CHANGELOG.md +43 -1
- package/README.md +7 -8
- package/adapters/_shared/codex-assets.cjs +23 -163
- package/adapters/_shared/runtime-assets.cjs +1 -0
- package/adapters/_shared/tests/runtime-assets.test.cjs +18 -0
- package/adapters/opencode.js +30 -120
- package/adapters/tests/claude.test.cjs +3 -2
- package/adapters/tests/codex-hook.test.cjs +34 -7
- package/adapters/tests/codex.test.cjs +13 -6
- package/adapters/tests/kimi-hook.test.cjs +34 -7
- package/adapters/tests/opencode.test.cjs +70 -84
- package/docs/AGENT-CONTEXT.md +6 -3
- package/docs/ARCHITECTURE.md +8 -1
- package/docs/ROADMAP.md +1 -1
- package/docs/RUNTIME-COMPAT-MATRIX.md +4 -4
- package/hooks/active_task_context.py +22 -50
- package/hooks/context_spine.py +61 -332
- package/hooks/health_check.py +19 -17
- package/hooks/pre_stop_check.py +28 -33
- package/hooks/subagent_tracker.py +13 -19
- package/hooks/workflow_checkpoint.py +39 -47
- package/hooks/workflow_context.py +4 -9
- package/hooks/workflow_resume.py +48 -128
- package/mcp-server/breadcrumb.cjs +22 -0
- package/mcp-server/lib/prd-parser.cjs +14 -41
- package/mcp-server/lib/prd-parser.test.cjs +49 -138
- package/mcp-server/lib/project-breadcrumb.cjs +139 -0
- package/mcp-server/lib/project-breadcrumb.test.cjs +112 -0
- package/mcp-server/lib/task-expander.cjs +9 -38
- package/mcp-server/lib/task-expander.test.cjs +54 -209
- package/mcp-server/server.cjs +21 -35
- package/mcp-server/tests/server-contract.test.cjs +41 -45
- package/package.json +2 -4
- package/skills/cc-collab/SKILL.md +2 -2
- package/skills/codex-collab/SKILL.md +2 -3
- package/skills/ultra-plan/SKILL.md +15 -5
- package/skills/ultra-verify/SKILL.md +21 -30
- package/skills/ultra-verify/scripts/verify_wait.py +54 -54
- package/spec/mcp-tools.yaml +38 -10
- package/mcp-server/lib/llm-client.cjs +0 -157
- package/mcp-server/lib/llm-client.test.cjs +0 -156
- package/orchestrator/planner/expand-prompt.cjs +0 -62
- package/orchestrator/planner/expand-prompt.test.cjs +0 -52
- package/orchestrator/planner/prd-prompt.cjs +0 -44
- package/orchestrator/planner/prd-prompt.test.cjs +0 -30
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
// Phase 8A.3 — Prompt templates for task → subtasks expansion.
|
|
4
|
-
//
|
|
5
|
-
// Parent context (title, type, priority, complexity, files_modified) is
|
|
6
|
-
// serialized into the user prompt so the LLM can produce children aligned
|
|
7
|
-
// with the parent's shape. sub_count defaults to 3 when omitted.
|
|
8
|
-
|
|
9
|
-
const DEFAULT_SUB_COUNT = 3;
|
|
10
|
-
|
|
11
|
-
function buildExpandSystemPrompt({ sub_count = DEFAULT_SUB_COUNT } = {}) {
|
|
12
|
-
return `You are an engineering task decomposer. Break a single complex task into ${sub_count} smaller subtasks that together deliver the parent's scope.
|
|
13
|
-
|
|
14
|
-
Output STRICT JSON matching this shape — nothing else, no markdown fences, no prose:
|
|
15
|
-
|
|
16
|
-
{
|
|
17
|
-
"children": [
|
|
18
|
-
{
|
|
19
|
-
"id": "child-1",
|
|
20
|
-
"title": "Imperative short title (3-80 chars)",
|
|
21
|
-
"type": "architecture | feature | bugfix",
|
|
22
|
-
"priority": "P0 | P1 | P2 | P3",
|
|
23
|
-
"complexity": 1-10,
|
|
24
|
-
"deps": ["child-2"],
|
|
25
|
-
"files_modified": ["src/path/to/file.ts"]
|
|
26
|
-
}
|
|
27
|
-
]
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
Rules:
|
|
31
|
-
- Exactly ${sub_count} children.
|
|
32
|
-
- Each id matches /^[a-zA-Z0-9_\\-]+$/ and is unique in the list.
|
|
33
|
-
- "deps" references siblings in the same list; omit or use [] when none.
|
|
34
|
-
- "files_modified" overlaps with the parent's files_modified where possible.
|
|
35
|
-
- Each child's complexity is < parent's complexity; sum should approximate the parent.
|
|
36
|
-
- Return JSON only.`;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function buildExpandUserPrompt(parent) {
|
|
40
|
-
const files = Array.isArray(parent.files_modified) ? parent.files_modified : [];
|
|
41
|
-
const deps = Array.isArray(parent.deps) ? parent.deps : [];
|
|
42
|
-
return [
|
|
43
|
-
'Parent task to decompose:',
|
|
44
|
-
'',
|
|
45
|
-
`- id: ${parent.id}`,
|
|
46
|
-
`- title: ${parent.title}`,
|
|
47
|
-
`- type: ${parent.type}`,
|
|
48
|
-
`- priority: ${parent.priority}`,
|
|
49
|
-
parent.complexity != null ? `- complexity: ${parent.complexity}` : null,
|
|
50
|
-
files.length ? `- files_modified: ${JSON.stringify(files)}` : null,
|
|
51
|
-
deps.length ? `- existing deps: ${JSON.stringify(deps)}` : null,
|
|
52
|
-
parent.trace_to ? `- trace_to: ${parent.trace_to}` : null,
|
|
53
|
-
'',
|
|
54
|
-
'Return the children list as JSON following the system schema.',
|
|
55
|
-
].filter((l) => l !== null).join('\n');
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
module.exports = {
|
|
59
|
-
buildExpandSystemPrompt,
|
|
60
|
-
buildExpandUserPrompt,
|
|
61
|
-
DEFAULT_SUB_COUNT,
|
|
62
|
-
};
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const test = require('node:test');
|
|
4
|
-
const assert = require('node:assert/strict');
|
|
5
|
-
|
|
6
|
-
const {
|
|
7
|
-
buildExpandSystemPrompt,
|
|
8
|
-
buildExpandUserPrompt,
|
|
9
|
-
DEFAULT_SUB_COUNT,
|
|
10
|
-
} = require('./expand-prompt.cjs');
|
|
11
|
-
|
|
12
|
-
test('buildExpandSystemPrompt: mentions sub_count explicitly', () => {
|
|
13
|
-
const s = buildExpandSystemPrompt({ sub_count: 4 });
|
|
14
|
-
assert.match(s, /Exactly 4 children/);
|
|
15
|
-
assert.match(s, /STRICT JSON/);
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
test('buildExpandSystemPrompt: falls back to DEFAULT_SUB_COUNT when omitted', () => {
|
|
19
|
-
const s = buildExpandSystemPrompt({});
|
|
20
|
-
assert.match(s, new RegExp(`Exactly ${DEFAULT_SUB_COUNT} children`));
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
test('buildExpandUserPrompt: serializes parent fields into prompt body', () => {
|
|
24
|
-
const parent = {
|
|
25
|
-
id: 'parent-1',
|
|
26
|
-
title: 'Build search feature',
|
|
27
|
-
type: 'feature',
|
|
28
|
-
priority: 'P1',
|
|
29
|
-
complexity: 8,
|
|
30
|
-
files_modified: ['src/search/index.ts', 'src/search/query.ts'],
|
|
31
|
-
deps: ['infra-1'],
|
|
32
|
-
trace_to: 'spec §3.2',
|
|
33
|
-
};
|
|
34
|
-
const body = buildExpandUserPrompt(parent);
|
|
35
|
-
assert.match(body, /parent-1/);
|
|
36
|
-
assert.match(body, /Build search feature/);
|
|
37
|
-
assert.match(body, /complexity: 8/);
|
|
38
|
-
assert.match(body, /src\/search\/index\.ts/);
|
|
39
|
-
assert.match(body, /infra-1/);
|
|
40
|
-
assert.match(body, /spec §3\.2/);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
test('buildExpandUserPrompt: omits empty optional fields', () => {
|
|
44
|
-
const parent = {
|
|
45
|
-
id: 'p', title: 'Tiny task', type: 'feature', priority: 'P3',
|
|
46
|
-
complexity: null, files_modified: [], deps: [],
|
|
47
|
-
};
|
|
48
|
-
const body = buildExpandUserPrompt(parent);
|
|
49
|
-
assert.doesNotMatch(body, /files_modified/);
|
|
50
|
-
assert.doesNotMatch(body, /existing deps/);
|
|
51
|
-
assert.doesNotMatch(body, /complexity:/);
|
|
52
|
-
});
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
// Phase 8A.1 — Prompt templates for PRD → task-list parsing.
|
|
4
|
-
//
|
|
5
|
-
// Kept in a dedicated module so downstream evaluation (fixture regression,
|
|
6
|
-
// prompt A/B testing) can diff the template against commits without touching
|
|
7
|
-
// parser logic.
|
|
8
|
-
|
|
9
|
-
const SYSTEM_PROMPT = `You are an engineering planner. Decompose a product requirement document (PRD) into a topologically ordered task list that a coding agent can execute sequentially or in parallel.
|
|
10
|
-
|
|
11
|
-
Output STRICT JSON matching this shape — nothing else, no markdown fences, no prose:
|
|
12
|
-
|
|
13
|
-
{
|
|
14
|
-
"tasks": [
|
|
15
|
-
{
|
|
16
|
-
"id": "task-1",
|
|
17
|
-
"title": "Imperative short title (3-80 chars)",
|
|
18
|
-
"type": "architecture | feature | bugfix",
|
|
19
|
-
"priority": "P0 | P1 | P2 | P3",
|
|
20
|
-
"complexity": 1-10,
|
|
21
|
-
"deps": ["task-2"],
|
|
22
|
-
"files_modified": ["src/path/to/file.ts"]
|
|
23
|
-
}
|
|
24
|
-
]
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
Rules:
|
|
28
|
-
- Every task id matches /^task-[0-9]+$/ and is unique in the list.
|
|
29
|
-
- "deps" references other ids in the same list; omit or use [] when none.
|
|
30
|
-
- "files_modified" is your best guess of affected paths; use [] when unsure.
|
|
31
|
-
- "complexity" 1 = trivial, 10 = multi-day. Tasks at 7+ will be auto-expanded later.
|
|
32
|
-
- "priority" — P0 blocks other work, P1 critical path, P2 standard, P3 nice-to-have.
|
|
33
|
-
- "type" — architecture for design/scaffolding, feature for new capability, bugfix for correcting existing behaviour.
|
|
34
|
-
- Return JSON only. No surrounding text, no trailing explanation.`;
|
|
35
|
-
|
|
36
|
-
function buildSystemPrompt() {
|
|
37
|
-
return SYSTEM_PROMPT;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function buildUserPrompt(prdText) {
|
|
41
|
-
return `PRD:\n\n${prdText}\n\nReturn the task list as JSON following the system schema.`;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
module.exports = { SYSTEM_PROMPT, buildSystemPrompt, buildUserPrompt };
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const test = require('node:test');
|
|
4
|
-
const assert = require('node:assert/strict');
|
|
5
|
-
|
|
6
|
-
const {
|
|
7
|
-
SYSTEM_PROMPT,
|
|
8
|
-
buildSystemPrompt,
|
|
9
|
-
buildUserPrompt,
|
|
10
|
-
} = require('./prd-prompt.cjs');
|
|
11
|
-
|
|
12
|
-
test('buildSystemPrompt returns the module-level template', () => {
|
|
13
|
-
assert.equal(buildSystemPrompt(), SYSTEM_PROMPT);
|
|
14
|
-
assert.match(SYSTEM_PROMPT, /engineering planner/i);
|
|
15
|
-
assert.match(SYSTEM_PROMPT, /STRICT JSON/);
|
|
16
|
-
assert.match(SYSTEM_PROMPT, /\/\^task-\[0-9\]\+\$\//);
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
test('buildUserPrompt embeds PRD text verbatim', () => {
|
|
20
|
-
const prd = 'As a user I want to search products by keyword';
|
|
21
|
-
const out = buildUserPrompt(prd);
|
|
22
|
-
assert.ok(out.includes(prd), 'user prompt must contain the PRD text');
|
|
23
|
-
assert.match(out, /JSON/);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
test('buildUserPrompt tolerates long PRD text without truncation', () => {
|
|
27
|
-
const long = 'line\n'.repeat(500);
|
|
28
|
-
const out = buildUserPrompt(long);
|
|
29
|
-
assert.ok(out.includes(long));
|
|
30
|
-
});
|