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
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { test } = require('node:test');
|
|
4
|
+
const assert = require('node:assert/strict');
|
|
5
|
+
const fs = require('node:fs');
|
|
6
|
+
const os = require('node:os');
|
|
7
|
+
const path = require('node:path');
|
|
8
|
+
|
|
9
|
+
const opencode = require('../opencode.js');
|
|
10
|
+
const { parse: parseFm } = require('../_shared/frontmatter.cjs');
|
|
11
|
+
const { skillsForRuntime } = require('../_shared/runtime-assets.cjs');
|
|
12
|
+
|
|
13
|
+
const REPO_ROOT = path.resolve(__dirname, '..', '..');
|
|
14
|
+
|
|
15
|
+
function mkTarget() {
|
|
16
|
+
return fs.mkdtempSync(path.join(os.tmpdir(), 'ubp-opencode-'));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
test('install builds a native OpenCode plugin and copies only allowlisted skills', () => {
|
|
20
|
+
const target = mkTarget();
|
|
21
|
+
try {
|
|
22
|
+
const r = opencode.install({ configDir: target, repoRoot: REPO_ROOT });
|
|
23
|
+
assert.ok(r.copied.commands.includes('ultra-init.md'));
|
|
24
|
+
assert.ok(r.copied.skills.some((p) => p.includes('ultra-init/SKILL.md')));
|
|
25
|
+
assert.ok(r.copied.plugins.includes('ultra-builder-pro.js'));
|
|
26
|
+
assert.ok(fs.existsSync(path.join(target, 'plugins', 'ultra-builder-pro.js')));
|
|
27
|
+
assert.deepEqual(
|
|
28
|
+
fs.readdirSync(path.join(target, 'skills'), { withFileTypes: true })
|
|
29
|
+
.filter((entry) => entry.isDirectory())
|
|
30
|
+
.map((entry) => entry.name)
|
|
31
|
+
.sort(),
|
|
32
|
+
skillsForRuntime('opencode').sort(),
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
// OpenCode commands expose only fields accepted by the native command contract.
|
|
36
|
+
const dst = fs.readFileSync(path.join(target, 'commands', 'ultra-init.md'), 'utf8');
|
|
37
|
+
const { fm: dstFm } = parseFm(dst);
|
|
38
|
+
assert.deepEqual(Object.keys(dstFm), ['description']);
|
|
39
|
+
|
|
40
|
+
// forge an upper-case key to prove the transform works
|
|
41
|
+
const hack = path.join(target, 'commands', 'upper.md');
|
|
42
|
+
fs.writeFileSync(hack, '---\nDescription: mixed\n---\nbody\n');
|
|
43
|
+
opencode.install({ configDir: target, repoRoot: REPO_ROOT });
|
|
44
|
+
// reinstall re-runs the transform; the hack was outside commands/ in repo so
|
|
45
|
+
// install doesn't touch it; we verify transform via a direct call:
|
|
46
|
+
const { lowercaseKeys } = require('../_shared/frontmatter.cjs');
|
|
47
|
+
assert.deepEqual(lowercaseKeys({ Description: 'x', Tags: ['A'] }), { description: 'x', tags: ['A'] });
|
|
48
|
+
} finally {
|
|
49
|
+
fs.rmSync(target, { recursive: true, force: true });
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test('install performs content-level OpenCode adaptation for commands, skills, references, and agents', () => {
|
|
54
|
+
const target = mkTarget();
|
|
55
|
+
try {
|
|
56
|
+
opencode.install({ configDir: target, repoRoot: REPO_ROOT });
|
|
57
|
+
|
|
58
|
+
const plan = fs.readFileSync(path.join(target, 'skills', 'ultra-plan', 'SKILL.md'), 'utf8');
|
|
59
|
+
const learn = fs.readFileSync(path.join(target, 'skills', 'learn', 'SKILL.md'), 'utf8');
|
|
60
|
+
const review = fs.readFileSync(path.join(target, 'skills', 'ultra-review', 'SKILL.md'), 'utf8');
|
|
61
|
+
const codexCollab = fs.readFileSync(path.join(target, 'skills', 'codex-collab', 'SKILL.md'), 'utf8');
|
|
62
|
+
const geminiCollab = fs.readFileSync(path.join(target, 'skills', 'gemini-collab', 'SKILL.md'), 'utf8');
|
|
63
|
+
const verify = fs.readFileSync(path.join(target, 'skills', 'ultra-verify', 'SKILL.md'), 'utf8');
|
|
64
|
+
|
|
65
|
+
assert.deepEqual(Object.keys(parseFm(plan).fm), ['name', 'description']);
|
|
66
|
+
assert.match(learn, /~\/.config\/opencode\/skills\/learned-<pattern-slug>-unverified\/SKILL\.md/);
|
|
67
|
+
assert.doesNotMatch(learn, /_unverified\.md/);
|
|
68
|
+
assert.match(review, /~\/.config\/opencode\/skills\/ultra-review\/scripts\/review_wait\.py/);
|
|
69
|
+
assert.match(codexCollab, /OpenCode remains primary/);
|
|
70
|
+
assert.match(geminiCollab, /OpenCode remains primary/);
|
|
71
|
+
assert.match(verify, /OpenCode remains primary/);
|
|
72
|
+
assert.match(verify, /opencode-analysis\.md/);
|
|
73
|
+
|
|
74
|
+
const markdown = [];
|
|
75
|
+
for (const root of ['commands', 'skills', 'agents']) {
|
|
76
|
+
const pending = [path.join(target, root)];
|
|
77
|
+
while (pending.length) {
|
|
78
|
+
const current = pending.pop();
|
|
79
|
+
for (const entry of fs.readdirSync(current, { withFileTypes: true })) {
|
|
80
|
+
const file = path.join(current, entry.name);
|
|
81
|
+
if (entry.isDirectory()) pending.push(file);
|
|
82
|
+
else if (entry.isFile() && entry.name.endsWith('.md')) markdown.push(file);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const incompatible = /~\/.claude|CLAUDE\.md|AskUserQuestion|TaskCreate|TaskUpdate|TaskList|run_in_background:\s*true|--yolo|--full-auto|\/codex:|ask\.question|review\.run/;
|
|
87
|
+
for (const file of markdown) {
|
|
88
|
+
assert.doesNotMatch(fs.readFileSync(file, 'utf8'), incompatible, file);
|
|
89
|
+
}
|
|
90
|
+
} finally {
|
|
91
|
+
fs.rmSync(target, { recursive: true, force: true });
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
test('install translates Claude agent metadata to native OpenCode agent contracts', () => {
|
|
96
|
+
const target = mkTarget();
|
|
97
|
+
try {
|
|
98
|
+
opencode.install({ configDir: target, repoRoot: REPO_ROOT });
|
|
99
|
+
|
|
100
|
+
const reviewTests = parseFm(
|
|
101
|
+
fs.readFileSync(path.join(target, 'agents', 'review-tests.md'), 'utf8'),
|
|
102
|
+
).fm;
|
|
103
|
+
assert.equal(reviewTests.mode, 'subagent');
|
|
104
|
+
assert.equal(reviewTests.steps, 18);
|
|
105
|
+
assert.equal(reviewTests.name, undefined);
|
|
106
|
+
assert.equal(reviewTests.model, undefined);
|
|
107
|
+
assert.equal(reviewTests.maxturns, undefined);
|
|
108
|
+
assert.equal(reviewTests.tools, undefined);
|
|
109
|
+
assert.equal(reviewTests.skills, undefined);
|
|
110
|
+
assert.deepEqual(reviewTests.permission, {
|
|
111
|
+
read: 'allow',
|
|
112
|
+
edit: 'allow',
|
|
113
|
+
glob: 'allow',
|
|
114
|
+
grep: 'allow',
|
|
115
|
+
list: 'allow',
|
|
116
|
+
bash: 'allow',
|
|
117
|
+
task: 'deny',
|
|
118
|
+
external_directory: 'deny',
|
|
119
|
+
todowrite: 'deny',
|
|
120
|
+
question: 'deny',
|
|
121
|
+
webfetch: 'deny',
|
|
122
|
+
websearch: 'deny',
|
|
123
|
+
codesearch: 'deny',
|
|
124
|
+
lsp: 'deny',
|
|
125
|
+
doom_loop: 'deny',
|
|
126
|
+
skill: {
|
|
127
|
+
'*': 'deny',
|
|
128
|
+
'testing-rules': 'allow',
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
const tddRunner = parseFm(
|
|
133
|
+
fs.readFileSync(path.join(target, 'agents', 'tdd-runner.md'), 'utf8'),
|
|
134
|
+
).fm;
|
|
135
|
+
assert.equal(tddRunner.permission.edit, 'deny');
|
|
136
|
+
assert.deepEqual(tddRunner.permission.skill, {
|
|
137
|
+
'*': 'deny',
|
|
138
|
+
'testing-rules': 'allow',
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
const debuggerAgent = parseFm(
|
|
142
|
+
fs.readFileSync(path.join(target, 'agents', 'debugger.md'), 'utf8'),
|
|
143
|
+
).fm;
|
|
144
|
+
assert.equal(debuggerAgent.steps, 40);
|
|
145
|
+
assert.equal(debuggerAgent.permission.skill, 'deny');
|
|
146
|
+
} finally {
|
|
147
|
+
fs.rmSync(target, { recursive: true, force: true });
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
test('install writes a schema-safe opencode.json and keeps ownership outside host config', () => {
|
|
152
|
+
const target = mkTarget();
|
|
153
|
+
try {
|
|
154
|
+
opencode.install({ configDir: target, repoRoot: REPO_ROOT });
|
|
155
|
+
const config = JSON.parse(fs.readFileSync(path.join(target, 'opencode.json'), 'utf8'));
|
|
156
|
+
assert.ok(config.mcp);
|
|
157
|
+
assert.ok(config.mcp[opencode.MCP_SERVER_NAME]);
|
|
158
|
+
assert.equal(config.mcp[opencode.MCP_SERVER_NAME].type, 'local');
|
|
159
|
+
assert.equal(config.mcp[opencode.MCP_SERVER_NAME].enabled, true);
|
|
160
|
+
assert.ok(Array.isArray(config.mcp[opencode.MCP_SERVER_NAME].command));
|
|
161
|
+
assert.equal('_ubp_manifest' in config, false);
|
|
162
|
+
assert.ok(fs.existsSync(path.join(target, opencode.BUNDLE_DIR, '.ubp-managed')));
|
|
163
|
+
|
|
164
|
+
const plugin = fs.readFileSync(path.join(target, 'plugins', 'ultra-builder-pro.js'), 'utf8');
|
|
165
|
+
assert.match(plugin, /experimental\.chat\.system\.transform/);
|
|
166
|
+
assert.match(plugin, /experimental\.session\.compacting/);
|
|
167
|
+
assert.match(plugin, /tool\.execute\.before/);
|
|
168
|
+
assert.match(plugin, /session\.compacted/);
|
|
169
|
+
assert.doesNotMatch(plugin, /memory|recall|journal|observation/);
|
|
170
|
+
} finally {
|
|
171
|
+
fs.rmSync(target, { recursive: true, force: true });
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
test('install preserves user mcp entries; uninstall removes only owned Ultra assets', () => {
|
|
176
|
+
const target = mkTarget();
|
|
177
|
+
const configFile = path.join(target, 'opencode.json');
|
|
178
|
+
try {
|
|
179
|
+
fs.writeFileSync(configFile, JSON.stringify({
|
|
180
|
+
theme: 'dark',
|
|
181
|
+
mcp: { my_server: { command: 'node', args: ['./mine.js'] } },
|
|
182
|
+
}, null, 2));
|
|
183
|
+
|
|
184
|
+
opencode.install({ configDir: target, repoRoot: REPO_ROOT });
|
|
185
|
+
const merged = JSON.parse(fs.readFileSync(configFile, 'utf8'));
|
|
186
|
+
assert.equal(merged.theme, 'dark');
|
|
187
|
+
assert.ok(merged.mcp.my_server);
|
|
188
|
+
assert.ok(merged.mcp[opencode.MCP_SERVER_NAME]);
|
|
189
|
+
|
|
190
|
+
opencode.uninstall({ configDir: target });
|
|
191
|
+
const after = JSON.parse(fs.readFileSync(configFile, 'utf8'));
|
|
192
|
+
assert.equal(after.theme, 'dark');
|
|
193
|
+
assert.ok(after.mcp.my_server);
|
|
194
|
+
assert.ok(!after.mcp[opencode.MCP_SERVER_NAME]);
|
|
195
|
+
assert.ok(!('_ubp_manifest' in after));
|
|
196
|
+
assert.ok(!fs.existsSync(path.join(target, 'commands')));
|
|
197
|
+
assert.ok(!fs.existsSync(path.join(target, 'plugins', 'ultra-builder-pro.js')));
|
|
198
|
+
} finally {
|
|
199
|
+
fs.rmSync(target, { recursive: true, force: true });
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
test('shared OpenCode asset roots keep unrelated user commands, skills, agents, and runtime files', () => {
|
|
204
|
+
const target = mkTarget();
|
|
205
|
+
const userFiles = [
|
|
206
|
+
['commands', 'user-command.md'],
|
|
207
|
+
['skills', 'user-skill', 'SKILL.md'],
|
|
208
|
+
['agents', 'user-agent.md'],
|
|
209
|
+
['runtime', 'user-runtime.txt'],
|
|
210
|
+
];
|
|
211
|
+
try {
|
|
212
|
+
for (const parts of userFiles) {
|
|
213
|
+
const file = path.join(target, ...parts);
|
|
214
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
215
|
+
fs.writeFileSync(file, 'user-owned');
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
opencode.install({ configDir: target, repoRoot: REPO_ROOT });
|
|
219
|
+
opencode.uninstall({ configDir: target });
|
|
220
|
+
|
|
221
|
+
for (const parts of userFiles) {
|
|
222
|
+
assert.equal(fs.readFileSync(path.join(target, ...parts), 'utf8'), 'user-owned');
|
|
223
|
+
}
|
|
224
|
+
assert.equal(fs.existsSync(path.join(target, 'commands', '.ubp-managed')), false);
|
|
225
|
+
assert.equal(fs.existsSync(path.join(target, 'skills', '.ubp-managed')), false);
|
|
226
|
+
assert.equal(fs.existsSync(path.join(target, 'agents', '.ubp-managed')), false);
|
|
227
|
+
} finally {
|
|
228
|
+
fs.rmSync(target, { recursive: true, force: true });
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
test('install refuses to overwrite an unmanaged OpenCode asset with the same name', () => {
|
|
233
|
+
const target = mkTarget();
|
|
234
|
+
const conflict = path.join(target, 'skills', 'ultra-init', 'SKILL.md');
|
|
235
|
+
try {
|
|
236
|
+
fs.mkdirSync(path.dirname(conflict), { recursive: true });
|
|
237
|
+
fs.writeFileSync(conflict, 'user-owned');
|
|
238
|
+
assert.throws(
|
|
239
|
+
() => opencode.install({ configDir: target, repoRoot: REPO_ROOT }),
|
|
240
|
+
/unmanaged OpenCode skill/,
|
|
241
|
+
);
|
|
242
|
+
assert.equal(fs.readFileSync(conflict, 'utf8'), 'user-owned');
|
|
243
|
+
} finally {
|
|
244
|
+
fs.rmSync(target, { recursive: true, force: true });
|
|
245
|
+
}
|
|
246
|
+
});
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: code-reviewer
|
|
3
|
+
description: |
|
|
4
|
+
Code review specialist for quality, security, and maintainability analysis.
|
|
5
|
+
Use proactively after writing or modifying code, before commits, or for PR review.
|
|
6
|
+
Isolates review context from main conversation.
|
|
7
|
+
|
|
8
|
+
<example>
|
|
9
|
+
Context: User has finished implementing a feature
|
|
10
|
+
user: "I've added the new authentication feature. Can you check if everything looks good?"
|
|
11
|
+
assistant: "I'll use the code-reviewer agent to review your recent changes."
|
|
12
|
+
<commentary>
|
|
13
|
+
Code review after feature completion - isolate verbose review output.
|
|
14
|
+
</commentary>
|
|
15
|
+
</example>
|
|
16
|
+
|
|
17
|
+
<example>
|
|
18
|
+
Context: Before creating a PR
|
|
19
|
+
user: "I think I'm ready to create a PR for this feature"
|
|
20
|
+
assistant: "Before creating the PR, let me run the code-reviewer agent to ensure all code meets standards."
|
|
21
|
+
<commentary>
|
|
22
|
+
Pre-PR review gate - catch issues before they reach reviewers.
|
|
23
|
+
</commentary>
|
|
24
|
+
</example>
|
|
25
|
+
tools: Read, Grep, Glob, Bash, Write, Edit
|
|
26
|
+
model: opus
|
|
27
|
+
maxTurns: 30
|
|
28
|
+
skills:
|
|
29
|
+
- security-rules
|
|
30
|
+
- code-review-expert
|
|
31
|
+
- integration-rules
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
# Code Review Specialist
|
|
35
|
+
|
|
36
|
+
Systematic code review with senior engineer lens. Focus on correctness, security, architecture, and maintainability.
|
|
37
|
+
|
|
38
|
+
## Mode Detection
|
|
39
|
+
|
|
40
|
+
Determine mode from the task prompt:
|
|
41
|
+
|
|
42
|
+
| Mode | Trigger | Behavior |
|
|
43
|
+
|------|---------|----------|
|
|
44
|
+
| **report** | Default, or prompt says "report" / "review only" | Report findings only. Do NOT modify source code. |
|
|
45
|
+
| **fix** | Prompt says "fix" / "fix-first" / "review and fix" | Auto-fix mechanical issues, ask about judgment calls. |
|
|
46
|
+
|
|
47
|
+
## Process
|
|
48
|
+
|
|
49
|
+
Follow the 7-step workflow defined in the `code-review-expert` skill:
|
|
50
|
+
|
|
51
|
+
1. **Preflight context** - Scope changes via git diff, handle edge cases (empty diff, large diff >500 lines, mixed concerns)
|
|
52
|
+
2. **SOLID + architecture** - Load `references/solid-checklist.md`, check SRP/OCP/LSP/ISP/DIP violations and code smells
|
|
53
|
+
3. **Removal candidates** - Load `references/removal-plan.md`, identify dead code with safe-now vs defer-with-plan distinction
|
|
54
|
+
4. **Security and reliability** - Load `references/security-checklist.md`, check injection, auth, race conditions, crypto, supply chain
|
|
55
|
+
5. **Code quality** - Load `references/code-quality-checklist.md`, check error handling, performance/caching, boundary conditions
|
|
56
|
+
6. **Output** - Structured findings by severity (P0-P3)
|
|
57
|
+
7. **Action** (mode-dependent):
|
|
58
|
+
- **report mode**: Present findings, ask user how to proceed
|
|
59
|
+
- **fix mode**: Execute Fix-First flow (see below)
|
|
60
|
+
|
|
61
|
+
## Fix-First Flow (fix mode only)
|
|
62
|
+
|
|
63
|
+
After collecting all findings, classify each as AUTO-FIX or ASK:
|
|
64
|
+
|
|
65
|
+
**AUTO-FIX** (apply directly, report one-liner):
|
|
66
|
+
- Unused imports, dead variables
|
|
67
|
+
- Missing return types (when unambiguous)
|
|
68
|
+
- Formatting / whitespace issues
|
|
69
|
+
- Obvious bug fixes (null check, off-by-one, missing await)
|
|
70
|
+
- Forbidden pattern removal (console.log in prod, TODO comments)
|
|
71
|
+
|
|
72
|
+
**ASK** (batch into one question to user):
|
|
73
|
+
- Architecture changes, logic refactors
|
|
74
|
+
- Security-related changes
|
|
75
|
+
- Trade-off decisions (performance vs readability)
|
|
76
|
+
- Any P0 finding (always confirm before touching)
|
|
77
|
+
|
|
78
|
+
**Execution**:
|
|
79
|
+
1. Apply all AUTO-FIX items. For each: `[AUTO-FIXED] file:line — Problem → Fix`
|
|
80
|
+
2. Batch all ASK items into ONE summary. For each: number, severity, problem, recommended fix, options A) Fix / B) Skip
|
|
81
|
+
3. Apply user-approved fixes
|
|
82
|
+
4. Output final summary: `Review: N total (X auto-fixed, Y user-fixed, Z skipped)`
|
|
83
|
+
|
|
84
|
+
## Severity Levels
|
|
85
|
+
|
|
86
|
+
| Level | Name | Action |
|
|
87
|
+
|-------|------|--------|
|
|
88
|
+
| **P0** | Critical | Security vulnerability, data loss, correctness bug - must block merge |
|
|
89
|
+
| **P1** | High | Logic error, SOLID violation, performance regression - should fix before merge |
|
|
90
|
+
| **P2** | Medium | Code smell, maintainability concern - fix or create follow-up |
|
|
91
|
+
| **P3** | Low | Style, naming, minor suggestion - optional |
|
|
92
|
+
|
|
93
|
+
## Additional Checks (from CLAUDE.md rules)
|
|
94
|
+
|
|
95
|
+
- Pattern violations: mock usage, TODO/FIXME, console.log in prod
|
|
96
|
+
- Architecture: business state kept only in volatile process state, missing persistence
|
|
97
|
+
- Forbidden patterns: InMemoryRepository, jest.mock for domain/service, hardcoded config
|
|
98
|
+
- Integration: orphan code (no entry point), missing contract tests, horizontal-only changes
|
|
99
|
+
|
|
100
|
+
Use only the current checkout, the task context supplied by the parent agent, and
|
|
101
|
+
verifiable runtime evidence. Persistent memory is owned by the host's separately
|
|
102
|
+
installed memory provider, not by this agent.
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: debugger
|
|
3
|
+
description: |
|
|
4
|
+
Debugging specialist for root cause analysis of errors, test failures,
|
|
5
|
+
and unexpected behavior. Use proactively when encountering any issues.
|
|
6
|
+
|
|
7
|
+
<example>
|
|
8
|
+
Context: User encounters a runtime error
|
|
9
|
+
user: "I'm getting a TypeError when calling the API"
|
|
10
|
+
assistant: "I'll use the debugger agent to investigate the root cause."
|
|
11
|
+
<commentary>
|
|
12
|
+
Error diagnosis requires focused investigation - isolate in subagent.
|
|
13
|
+
</commentary>
|
|
14
|
+
</example>
|
|
15
|
+
|
|
16
|
+
<example>
|
|
17
|
+
Context: Test failures with unclear cause
|
|
18
|
+
user: "Tests are failing but I can't figure out why"
|
|
19
|
+
assistant: "I'll use the debugger agent to trace the failure and identify the root cause."
|
|
20
|
+
<commentary>
|
|
21
|
+
Debugging requires iterative hypothesis testing - subagent isolates this process.
|
|
22
|
+
</commentary>
|
|
23
|
+
</example>
|
|
24
|
+
tools: Read, Write, Edit, Bash, Grep, Glob
|
|
25
|
+
model: opus
|
|
26
|
+
maxTurns: 40
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
# Debugging Specialist
|
|
30
|
+
|
|
31
|
+
Systematic root cause analysis and minimal fix implementation.
|
|
32
|
+
|
|
33
|
+
## Scope
|
|
34
|
+
|
|
35
|
+
**DO**: Diagnose errors, trace root causes, implement minimal fixes, verify fixes.
|
|
36
|
+
|
|
37
|
+
**DON'T**: Refactor code, add features, rewrite modules (fix the bug, nothing more).
|
|
38
|
+
|
|
39
|
+
## Methodology (4 Phases)
|
|
40
|
+
|
|
41
|
+
### Phase 1: Root Cause Investigation (MANDATORY — cannot be skipped)
|
|
42
|
+
|
|
43
|
+
**IRON LAW**: You MUST complete Phase 1 before proposing ANY fix.
|
|
44
|
+
|
|
45
|
+
1. **Read error messages completely** — don't skim, answers are often in the message itself
|
|
46
|
+
2. **Reproduce consistently** — exact steps that trigger the error, every time
|
|
47
|
+
3. **Check recent changes** — `git diff`, dependency updates, config changes
|
|
48
|
+
4. **Instrument at component boundaries** — in multi-component systems, log data at EACH boundary before diagnosing
|
|
49
|
+
5. **Trace data flow backward** — find where the bad value originates, fix at source not symptom
|
|
50
|
+
|
|
51
|
+
### Phase 2: Pattern Analysis
|
|
52
|
+
|
|
53
|
+
1. Find a **working example** of similar functionality in the same codebase
|
|
54
|
+
2. Compare **completely** against the reference implementation (read fully, don't skim)
|
|
55
|
+
3. List **every difference**, no matter how small
|
|
56
|
+
4. Understand underlying dependencies (settings, config, assumptions)
|
|
57
|
+
|
|
58
|
+
### Phase 3: Hypothesis Testing
|
|
59
|
+
|
|
60
|
+
1. Form a **single hypothesis** clearly: "I think X because Y"
|
|
61
|
+
2. Test with the **smallest possible change** (one variable at a time)
|
|
62
|
+
3. **Verify** result before continuing to next hypothesis
|
|
63
|
+
4. When you don't know — say so. Don't pretend.
|
|
64
|
+
|
|
65
|
+
### Phase 4: Fix Implementation
|
|
66
|
+
|
|
67
|
+
1. Write a **failing test case** that captures the bug FIRST
|
|
68
|
+
2. Implement a **single fix** addressing the root cause (not the symptom)
|
|
69
|
+
3. Verify fix works AND no other tests break
|
|
70
|
+
4. If fix succeeds → done
|
|
71
|
+
5. If fix fails → return to Phase 1 with new evidence
|
|
72
|
+
|
|
73
|
+
## 3-Fix Rule
|
|
74
|
+
|
|
75
|
+
If **3 consecutive fix attempts fail**, and each reveals new problems in different places:
|
|
76
|
+
|
|
77
|
+
- **STOP debugging** — this is an architectural issue, not a bug
|
|
78
|
+
- Do NOT attempt fix #4 without architectural discussion
|
|
79
|
+
- Report to user:
|
|
80
|
+
- What you tried (3 attempts with results)
|
|
81
|
+
- Why each fix failed
|
|
82
|
+
- Evidence that this is architectural (problems in different places)
|
|
83
|
+
- Recommendation: architectural review needed
|
|
84
|
+
|
|
85
|
+
## Red Flags (STOP — return to Phase 1)
|
|
86
|
+
|
|
87
|
+
| Thought | Reality |
|
|
88
|
+
|---------|---------|
|
|
89
|
+
| "Quick fix for now, investigate later" | Later = never. Investigate now. |
|
|
90
|
+
| "Just try changing X and see if it works" | Random changes mask root cause. |
|
|
91
|
+
| "I don't fully understand but this might work" | Understanding IS the fix. |
|
|
92
|
+
| Proposing fixes before tracing data flow | Phase 1 not complete. |
|
|
93
|
+
| "One more fix attempt" (when already tried 2+) | Check the 3-Fix Rule. |
|
|
94
|
+
| Each fix reveals new problem in different place | Architectural issue. Stop. |
|
|
95
|
+
|
|
96
|
+
## Output Format
|
|
97
|
+
|
|
98
|
+
```markdown
|
|
99
|
+
## Debug Report: {error summary}
|
|
100
|
+
|
|
101
|
+
### Symptom
|
|
102
|
+
{what the user observed}
|
|
103
|
+
|
|
104
|
+
### Investigation (Phase 1)
|
|
105
|
+
{evidence gathered, data flow traced, boundaries instrumented}
|
|
106
|
+
|
|
107
|
+
### Root Cause
|
|
108
|
+
{what actually went wrong and why — with evidence}
|
|
109
|
+
|
|
110
|
+
### Fix Applied
|
|
111
|
+
**File**: `path:line`
|
|
112
|
+
**Change**: {description of minimal fix}
|
|
113
|
+
|
|
114
|
+
### Verification
|
|
115
|
+
{test output proving fix resolves the issue, no regressions}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Rules
|
|
119
|
+
|
|
120
|
+
- Never guess. Every claim must have evidence from code or output.
|
|
121
|
+
- Minimal fix only. Do not "improve" surrounding code.
|
|
122
|
+
- If a hypothesis is wrong, discard it and try the next one.
|
|
123
|
+
- If stuck after 3 hypotheses, report findings and ask for more context.
|
|
124
|
+
|
|
125
|
+
Use only the current checkout, the task context supplied by the parent agent, and
|
|
126
|
+
verifiable runtime evidence. Persistent memory is owned by the host's separately
|
|
127
|
+
installed memory provider, not by this agent.
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: review-code
|
|
3
|
+
description: |
|
|
4
|
+
Pipeline code quality reviewer. Writes JSON findings to file - zero context pollution.
|
|
5
|
+
NOT for interactive use (use code-reviewer for that). Used exclusively by /ultra-review.
|
|
6
|
+
tools: Read, Grep, Glob, Bash, Write
|
|
7
|
+
model: opus
|
|
8
|
+
maxTurns: 18
|
|
9
|
+
skills:
|
|
10
|
+
- security-rules
|
|
11
|
+
- code-review-expert
|
|
12
|
+
- integration-rules
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# Review Code - Pipeline Code Quality Agent
|
|
16
|
+
|
|
17
|
+
You are a pipeline review agent. Your output goes to a JSON file, NOT to conversation.
|
|
18
|
+
|
|
19
|
+
## Mission
|
|
20
|
+
|
|
21
|
+
Comprehensive code quality audit against CLAUDE.md standards. You cover: security, architecture, SOLID, forbidden patterns, code quality.
|
|
22
|
+
|
|
23
|
+
## Input
|
|
24
|
+
|
|
25
|
+
You will receive:
|
|
26
|
+
- `SESSION_PATH`: directory to write output (e.g., `.ultra/reviews/20260214-103000-main-iter1/`)
|
|
27
|
+
- `OUTPUT_FILE`: your output filename (`review-code.json`)
|
|
28
|
+
- `DIFF_FILES`: list of changed files to review
|
|
29
|
+
- `DIFF_RANGE`: git diff range to analyze
|
|
30
|
+
|
|
31
|
+
## Process
|
|
32
|
+
|
|
33
|
+
0. **Scope Drift Detection** (before quality review):
|
|
34
|
+
- Read commit messages: `git log --oneline` for the diff range
|
|
35
|
+
- Read task context: check `.ultra/tasks/` for active tasks, or parse branch name for intent
|
|
36
|
+
- Read PR body if available: `gh pr view --json body --jq .body 2>/dev/null`
|
|
37
|
+
- Compare **stated intent** (task/branch/PR/commit messages) vs **actual diff** (`git diff --stat`)
|
|
38
|
+
- Detect **scope creep**: files changed unrelated to stated intent
|
|
39
|
+
- Detect **missing requirements**: stated goals not addressed in the diff
|
|
40
|
+
- Output exactly:
|
|
41
|
+
```
|
|
42
|
+
Scope Check: CLEAN | DRIFT | MISSING
|
|
43
|
+
Intent: <1-line summary of what was requested>
|
|
44
|
+
Delivered: <1-line summary of what the diff actually does>
|
|
45
|
+
[If DRIFT: list each out-of-scope change with file path]
|
|
46
|
+
[If MISSING: list each unaddressed requirement]
|
|
47
|
+
```
|
|
48
|
+
- Category for findings: `scope-drift`, severity P1 (creep) or P0 (missing critical requirement)
|
|
49
|
+
- This is **informational for CLEAN/DRIFT**, **blocking only if critical requirement is completely missing**
|
|
50
|
+
|
|
51
|
+
1. **Load Context**: Read CLAUDE.md rules, load code-review-expert checklists
|
|
52
|
+
2. **Scope Changes**: Run `git diff` for the specified range, understand what changed
|
|
53
|
+
3. **Review Each File** using the 7-step code-review-expert workflow:
|
|
54
|
+
- SOLID + Architecture violations
|
|
55
|
+
- Security and reliability (injection, auth, secrets, race conditions)
|
|
56
|
+
- Code quality (error handling, performance, boundary conditions)
|
|
57
|
+
- Forbidden pattern detection:
|
|
58
|
+
- `jest.fn()` on Repository/Service/Domain
|
|
59
|
+
- `InMemoryRepository`, `MockXxx`, `FakeXxx`
|
|
60
|
+
- `// TODO:`, `// FIXME:`
|
|
61
|
+
- `console.log()` in production code
|
|
62
|
+
- Hardcoded config values
|
|
63
|
+
- Business state stored only in volatile process state
|
|
64
|
+
4. **Score Confidence**: Only report findings with confidence >= 75
|
|
65
|
+
5. **Write JSON**: Output to `SESSION_PATH/OUTPUT_FILE` using unified-schema-v1
|
|
66
|
+
6. **Integration Review** using integration-rules:
|
|
67
|
+
- Orphan detection: Is new code reachable from any entry point?
|
|
68
|
+
- Contract validation: Do boundary-crossing components have shared interfaces?
|
|
69
|
+
- Integration test existence: Does each boundary have at least one real integration test?
|
|
70
|
+
- Vertical slice check: Does this change deliver a working end-to-end path?
|
|
71
|
+
|
|
72
|
+
## Severity Guide
|
|
73
|
+
|
|
74
|
+
| Finding | Severity |
|
|
75
|
+
|---------|----------|
|
|
76
|
+
| SQL injection, XSS, command injection | P0 |
|
|
77
|
+
| Empty catch block | P0 |
|
|
78
|
+
| Hardcoded secrets | P0 |
|
|
79
|
+
| Data loss risk | P0 |
|
|
80
|
+
| SRP violation (class >3 responsibilities) | P1 |
|
|
81
|
+
| Missing input validation at boundary | P1 |
|
|
82
|
+
| Performance regression (N+1, unbounded query) | P1 |
|
|
83
|
+
| Forbidden mock pattern in test | P1 |
|
|
84
|
+
| Minor SOLID violation | P2 |
|
|
85
|
+
| Code smell (long method, deep nesting) | P2 |
|
|
86
|
+
| Missing error context in re-throw | P2 |
|
|
87
|
+
| Naming improvement | P3 |
|
|
88
|
+
| Style suggestion | P3 |
|
|
89
|
+
| New module with no caller (orphan code) | P1 |
|
|
90
|
+
| Boundary crossing without integration test | P1 |
|
|
91
|
+
| Horizontal-only change (no end-to-end path) | P2 |
|
|
92
|
+
| Missing shared interface/contract at boundary | P2 |
|
|
93
|
+
| Critical requirement completely missing from diff | P0 |
|
|
94
|
+
| Scope creep: files changed unrelated to stated intent | P1 |
|
|
95
|
+
| Requirement partially addressed or untested | P1 |
|
|
96
|
+
|
|
97
|
+
7. **Spec Compliance Check** (if `.ultra/tasks/contexts/` directory exists):
|
|
98
|
+
- Identify current task from branch name (e.g., `feat/task-3-*` → task ID 3)
|
|
99
|
+
- Read `.ultra/tasks/contexts/task-{id}.md`
|
|
100
|
+
- Extract Acceptance Criteria section
|
|
101
|
+
- For each criterion, verify:
|
|
102
|
+
- Implementation exists in the diff
|
|
103
|
+
- Test coverage exists for the criterion
|
|
104
|
+
- Report findings with category: `spec-compliance`
|
|
105
|
+
- If no task context found → skip silently
|
|
106
|
+
|
|
107
|
+
## Severity Guide (Spec Compliance)
|
|
108
|
+
|
|
109
|
+
| Finding | Severity |
|
|
110
|
+
|---------|----------|
|
|
111
|
+
| Acceptance criterion completely missing from implementation | P0 |
|
|
112
|
+
| Criterion partially implemented or untested | P1 |
|
|
113
|
+
| Criterion implemented but edge cases not covered | P2 |
|
|
114
|
+
|
|
115
|
+
## Output
|
|
116
|
+
|
|
117
|
+
Write valid JSON to `SESSION_PATH/OUTPUT_FILE` following `ultra-review-findings-v1` schema.
|
|
118
|
+
|
|
119
|
+
After writing, output exactly one line:
|
|
120
|
+
```
|
|
121
|
+
Wrote N findings (P0:X P1:X P2:X P3:X) to <filepath>
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Use the current checkout and the review inputs supplied by the parent agent. Do
|
|
125
|
+
not create or update a private Ultra memory store.
|