@spec-box/sdd 0.6.4
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/README.md +81 -0
- package/assets/adapters/openspec/instructions.md +47 -0
- package/assets/adapters/spec-box/instructions.md +44 -0
- package/assets/ci/Dockerfile +9 -0
- package/assets/ci/github-sbox-run.yml +85 -0
- package/assets/ci/github-tests.yml +25 -0
- package/assets/project/architecture.md +29 -0
- package/assets/project/contracts.md +29 -0
- package/assets/project/conventions.md +29 -0
- package/assets/project/decisions.README.md +3 -0
- package/assets/project/glossary.md +13 -0
- package/assets/project/overview.md +29 -0
- package/assets/project/testing.md +34 -0
- package/assets/project/workflow.md +29 -0
- package/assets/prompts/fill-project-docs.md +43 -0
- package/assets/roles/challenger.md +33 -0
- package/assets/roles/distiller.md +18 -0
- package/assets/roles/implementer.md +39 -0
- package/assets/roles/planner.md +58 -0
- package/assets/roles/researcher.md +47 -0
- package/assets/roles/reviewer.md +68 -0
- package/assets/roles/tester.md +36 -0
- package/assets/roles/verifier.md +57 -0
- package/assets/schema/default.yaml +121 -0
- package/assets/schema/sbox-answer.schema.json +42 -0
- package/assets/templates/coverage.yaml +12 -0
- package/assets/templates/design.md +48 -0
- package/assets/templates/proposal.md +27 -0
- package/assets/templates/tasks.md +9 -0
- package/assets/templates/test-plan.md +7 -0
- package/bin/sbox.js +5 -0
- package/dist/adapters/host/claude/index.js +112 -0
- package/dist/adapters/host/claude/index.js.map +1 -0
- package/dist/adapters/repo/git.js +81 -0
- package/dist/adapters/repo/git.js.map +1 -0
- package/dist/adapters/repo/github/index.js +136 -0
- package/dist/adapters/repo/github/index.js.map +1 -0
- package/dist/adapters/repo/index.js +4 -0
- package/dist/adapters/repo/index.js.map +1 -0
- package/dist/adapters/repo/local.js +47 -0
- package/dist/adapters/repo/local.js.map +1 -0
- package/dist/adapters/runner/claude.js +129 -0
- package/dist/adapters/runner/claude.js.map +1 -0
- package/dist/adapters/runner/codex.js +151 -0
- package/dist/adapters/runner/codex.js.map +1 -0
- package/dist/adapters/runner/index.js +4 -0
- package/dist/adapters/runner/index.js.map +1 -0
- package/dist/adapters/spec/index.js +4 -0
- package/dist/adapters/spec/index.js.map +1 -0
- package/dist/adapters/spec/openspec/delta.js +268 -0
- package/dist/adapters/spec/openspec/delta.js.map +1 -0
- package/dist/adapters/spec/openspec/index.js +107 -0
- package/dist/adapters/spec/openspec/index.js.map +1 -0
- package/dist/adapters/spec/openspec/parser.js +188 -0
- package/dist/adapters/spec/openspec/parser.js.map +1 -0
- package/dist/adapters/spec/spec-box/delta.js +198 -0
- package/dist/adapters/spec/spec-box/delta.js.map +1 -0
- package/dist/adapters/spec/spec-box/index.js +112 -0
- package/dist/adapters/spec/spec-box/index.js.map +1 -0
- package/dist/adapters/spec/spec-box/yaml.js +74 -0
- package/dist/adapters/spec/spec-box/yaml.js.map +1 -0
- package/dist/cli/commands/artifacts.js +86 -0
- package/dist/cli/commands/artifacts.js.map +1 -0
- package/dist/cli/commands/change.js +111 -0
- package/dist/cli/commands/change.js.map +1 -0
- package/dist/cli/commands/changeset.js +81 -0
- package/dist/cli/commands/changeset.js.map +1 -0
- package/dist/cli/commands/ci.js +45 -0
- package/dist/cli/commands/ci.js.map +1 -0
- package/dist/cli/commands/coverage.js +45 -0
- package/dist/cli/commands/coverage.js.map +1 -0
- package/dist/cli/commands/deliver.js +71 -0
- package/dist/cli/commands/deliver.js.map +1 -0
- package/dist/cli/commands/doctor.js +55 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/host.js +30 -0
- package/dist/cli/commands/host.js.map +1 -0
- package/dist/cli/commands/init.js +150 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/metrics.js +62 -0
- package/dist/cli/commands/metrics.js.map +1 -0
- package/dist/cli/commands/prompt.js +68 -0
- package/dist/cli/commands/prompt.js.map +1 -0
- package/dist/cli/commands/protocol.js +151 -0
- package/dist/cli/commands/protocol.js.map +1 -0
- package/dist/cli/commands/run.js +157 -0
- package/dist/cli/commands/run.js.map +1 -0
- package/dist/cli/commands/spec.js +84 -0
- package/dist/cli/commands/spec.js.map +1 -0
- package/dist/cli/commands/wiring.js +50 -0
- package/dist/cli/commands/wiring.js.map +1 -0
- package/dist/cli/context.js +18 -0
- package/dist/cli/context.js.map +1 -0
- package/dist/cli/main.js +63 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/output.js +31 -0
- package/dist/cli/output.js.map +1 -0
- package/dist/core/archive.js +77 -0
- package/dist/core/archive.js.map +1 -0
- package/dist/core/change.js +240 -0
- package/dist/core/change.js.map +1 -0
- package/dist/core/changeset.js +98 -0
- package/dist/core/changeset.js.map +1 -0
- package/dist/core/config.js +144 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/coverage.js +69 -0
- package/dist/core/coverage.js.map +1 -0
- package/dist/core/deliver.js +190 -0
- package/dist/core/deliver.js.map +1 -0
- package/dist/core/diagnostics.js +12 -0
- package/dist/core/diagnostics.js.map +1 -0
- package/dist/core/drift.js +44 -0
- package/dist/core/drift.js.map +1 -0
- package/dist/core/errors.js +12 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/gates.js +76 -0
- package/dist/core/gates.js.map +1 -0
- package/dist/core/lock.js +57 -0
- package/dist/core/lock.js.map +1 -0
- package/dist/core/metrics.js +140 -0
- package/dist/core/metrics.js.map +1 -0
- package/dist/core/packet.js +172 -0
- package/dist/core/packet.js.map +1 -0
- package/dist/core/paths.js +63 -0
- package/dist/core/paths.js.map +1 -0
- package/dist/core/phases.js +203 -0
- package/dist/core/phases.js.map +1 -0
- package/dist/core/pr-body.js +64 -0
- package/dist/core/pr-body.js.map +1 -0
- package/dist/core/project-docs.js +246 -0
- package/dist/core/project-docs.js.map +1 -0
- package/dist/core/protect.js +47 -0
- package/dist/core/protect.js.map +1 -0
- package/dist/core/repo-host.js +11 -0
- package/dist/core/repo-host.js.map +1 -0
- package/dist/core/report.js +286 -0
- package/dist/core/report.js.map +1 -0
- package/dist/core/result.js +90 -0
- package/dist/core/result.js.map +1 -0
- package/dist/core/roles.js +18 -0
- package/dist/core/roles.js.map +1 -0
- package/dist/core/run.js +222 -0
- package/dist/core/run.js.map +1 -0
- package/dist/core/runner.js +40 -0
- package/dist/core/runner.js.map +1 -0
- package/dist/core/schema.js +104 -0
- package/dist/core/schema.js.map +1 -0
- package/dist/core/spec-adapter.js +12 -0
- package/dist/core/spec-adapter.js.map +1 -0
- package/dist/core/spec-model.js +8 -0
- package/dist/core/spec-model.js.map +1 -0
- package/dist/core/tasks.js +15 -0
- package/dist/core/tasks.js.map +1 -0
- package/dist/core/test-reports.js +60 -0
- package/dist/core/test-reports.js.map +1 -0
- package/dist/core/wiki.js +86 -0
- package/dist/core/wiki.js.map +1 -0
- package/dist/core/wiring.js +65 -0
- package/dist/core/wiring.js.map +1 -0
- package/docs/design.md +829 -0
- package/package.json +66 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host.js","sourceRoot":"","sources":["../../../src/cli/commands/host.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE/C,MAAM,iBAAiB,GAAG;;mHAEyF,CAAC;AAEpH,MAAM,UAAU,YAAY,CAAC,OAAgB;IAC3C,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,mCAAmC,CAAC,CAAC;IACtF,IAAI;SACD,OAAO,CAAC,SAAS,CAAC;SAClB,WAAW,CAAC,0CAA0C,CAAC;SACvD,cAAc,CAAC,iBAAiB,EAAE,gBAAgB,CAAC;SACnD,MAAM,CAAC,CAAC,IAAwB,EAAE,GAAY,EAAE,EAAE;QACjD,MAAM,CAAC,GAAG,GAAG,CAAC,eAAe,EAAqC,CAAC;QACnE,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YAClC,IAAI,IAAI,CAAC,MAAM,KAAK,QAAQ;gBAAE,MAAM,IAAI,SAAS,CAAC,gBAAgB,EAAE,QAAQ,IAAI,CAAC,MAAM,qCAAqC,CAAC,CAAC;YAC9H,MAAM,KAAK,GAAG,sBAAsB,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAClG,IAAI,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,iBAAiB,CAAC,CAAC,MAAM,GAAG,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,4DAA4D,EAAE,2DAA2D,EAAE,EAAE,EAAE,CAAC,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACzT,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAChB,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { installClaudeMaterials } from '../../adapters/host/claude/index.js';
|
|
4
|
+
import { defaultConfig, loadConfig, saveConfig } from '../../core/config.js';
|
|
5
|
+
import { SboxError } from '../../core/errors.js';
|
|
6
|
+
import { assetsDir, sboxDir, exists, readText, today, writeText } from '../../core/paths.js';
|
|
7
|
+
import { DOC_CATEGORIES } from '../../core/project-docs.js';
|
|
8
|
+
import { WIKI_README } from '../../core/wiki.js';
|
|
9
|
+
import { emit, emitError } from '../output.js';
|
|
10
|
+
const GITIGNORE_BLOCK = ['# sbox: служебные файлы запусков', '**/.sbox/**/.lock', '**/.stop', '**/change.yaml.*.tmp', '**/runs/run.log', '**/runs/r*/packet.json'];
|
|
11
|
+
export function registerInit(program) {
|
|
12
|
+
program
|
|
13
|
+
.command('init')
|
|
14
|
+
.description('Создать .sbox/: конфиг, шаблоны проектной документации, каталог изменений; при --host сразу материалы для хоста')
|
|
15
|
+
.option('--adapter <name>', 'адаптер спецификаций: spec-box | openspec; при существующем конфиге меняет только его')
|
|
16
|
+
.option('--host <name>', 'сразу установить материалы хоста: claude')
|
|
17
|
+
.option('--force', 'перезаписать конфиг целиком (документация не трогается)')
|
|
18
|
+
.option('--reset-docs', 'перезаписать заполненную документацию шаблонами')
|
|
19
|
+
.action((opts, cmd) => {
|
|
20
|
+
const g = cmd.optsWithGlobals();
|
|
21
|
+
try {
|
|
22
|
+
const root = path.resolve(g.cwd ?? process.cwd());
|
|
23
|
+
const adapter = (opts.adapter ?? (exists(path.join(root, 'openspec', 'specs')) && !exists(path.join(root, '.tms.json')) ? 'openspec' : 'spec-box'));
|
|
24
|
+
if (adapter !== 'spec-box' && adapter !== 'openspec')
|
|
25
|
+
throw new SboxError('ADAPTER_UNKNOWN', `Неизвестный адаптер ${String(adapter)}; доступны spec-box и openspec.`);
|
|
26
|
+
const dir = sboxDir(root);
|
|
27
|
+
const created = [];
|
|
28
|
+
const notes = [];
|
|
29
|
+
const configFile = path.join(dir, 'config.yaml');
|
|
30
|
+
if (exists(configFile) && !opts.force) {
|
|
31
|
+
// Повторный запуск: обновляем только адаптер и связанные пути, остальное сохраняем.
|
|
32
|
+
const current = loadConfig(root);
|
|
33
|
+
if (opts.adapter && current.spec.adapter !== adapter) {
|
|
34
|
+
current.spec.adapter = adapter;
|
|
35
|
+
if (adapter === 'openspec') {
|
|
36
|
+
const activeChanges = exists(path.join(root, current.changes.dir)) ? fs.readdirSync(path.join(root, current.changes.dir)).filter((n) => n !== 'archive' && n !== '.gitkeep') : [];
|
|
37
|
+
if (activeChanges.length === 0) {
|
|
38
|
+
current.changes.dir = 'openspec/changes';
|
|
39
|
+
notes.push('changes.dir переключён на openspec/changes для совместимости с CLI OpenSpec.');
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
notes.push(`В ${current.changes.dir} есть изменения (${activeChanges.join(', ')}): changes.dir оставлен; перенесите их в openspec/changes и поправьте конфиг вручную, если нужна совместимость с CLI OpenSpec.`);
|
|
43
|
+
}
|
|
44
|
+
for (const sub of ['specs', 'changes', 'changes/archive']) {
|
|
45
|
+
const keep = path.join(root, 'openspec', sub, '.gitkeep');
|
|
46
|
+
if (!exists(path.join(root, 'openspec', sub))) {
|
|
47
|
+
writeText(keep, '');
|
|
48
|
+
created.push(keep);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const staleKeep = path.join(root, 'specs', '.gitkeep');
|
|
52
|
+
if (exists(staleKeep) && fs.readdirSync(path.join(root, 'specs')).length === 1) {
|
|
53
|
+
fs.rmSync(path.join(root, 'specs'), { recursive: true, force: true });
|
|
54
|
+
notes.push('Удалён пустой каталог specs/, созданный для spec-box.');
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
saveConfig(root, current);
|
|
58
|
+
created.push(configFile);
|
|
59
|
+
notes.push(`Адаптер спецификаций переключён на ${adapter}; проверьте раздел «Истина спецификаций» в .sbox/project/overview.md.`);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
notes.push('Конфиг уже есть и не изменён: укажите --adapter для смены адаптера или --force для перезаписи.');
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
const config = defaultConfig(adapter);
|
|
67
|
+
if (adapter === 'openspec') {
|
|
68
|
+
// Совместимость с CLI OpenSpec: изменения живут в openspec/changes, истина в openspec/specs.
|
|
69
|
+
config.changes.dir = 'openspec/changes';
|
|
70
|
+
for (const sub of ['specs', 'changes', 'changes/archive']) {
|
|
71
|
+
const keep = path.join(root, 'openspec', sub, '.gitkeep');
|
|
72
|
+
if (!exists(path.join(root, 'openspec', sub))) {
|
|
73
|
+
writeText(keep, '');
|
|
74
|
+
created.push(keep);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
notes.push('Адаптер openspec: истина в openspec/specs/<capability>/spec.md, изменения в openspec/changes/<id>/ (совместимо с openspec CLI).');
|
|
78
|
+
}
|
|
79
|
+
else if (!exists(path.join(root, '.tms.json'))) {
|
|
80
|
+
// Нет конфига spec-box: истина будет жить в specs/*.spec-box.yml прямо в репозитории.
|
|
81
|
+
config.spec['spec-box'].files = ['specs/**/*.spec-box.yml'];
|
|
82
|
+
const keep = path.join(root, 'specs', '.gitkeep');
|
|
83
|
+
if (!exists(keep)) {
|
|
84
|
+
writeText(keep, '');
|
|
85
|
+
created.push(keep);
|
|
86
|
+
}
|
|
87
|
+
notes.push('Файла .tms.json нет: спецификации ожидаются в specs/**/*.spec-box.yml (поле spec.spec-box.files в конфиге).');
|
|
88
|
+
}
|
|
89
|
+
saveConfig(root, config);
|
|
90
|
+
created.push(configFile);
|
|
91
|
+
}
|
|
92
|
+
const date = today();
|
|
93
|
+
for (const category of DOC_CATEGORIES) {
|
|
94
|
+
const target = path.join(dir, 'project', category.file);
|
|
95
|
+
if (exists(target) && !opts.resetDocs)
|
|
96
|
+
continue;
|
|
97
|
+
writeText(target, readText(path.join(assetsDir(), 'project', category.file)).replace(/\{\{DATE\}\}/g, date));
|
|
98
|
+
created.push(target);
|
|
99
|
+
}
|
|
100
|
+
const decisionsReadme = path.join(dir, 'project', 'decisions', 'README.md');
|
|
101
|
+
if (!exists(decisionsReadme)) {
|
|
102
|
+
writeText(decisionsReadme, readText(path.join(assetsDir(), 'project', 'decisions.README.md')));
|
|
103
|
+
created.push(decisionsReadme);
|
|
104
|
+
}
|
|
105
|
+
const wikiReadme = path.join(dir, 'wiki', 'README.md');
|
|
106
|
+
if (!exists(wikiReadme)) {
|
|
107
|
+
writeText(wikiReadme, WIKI_README);
|
|
108
|
+
created.push(wikiReadme);
|
|
109
|
+
}
|
|
110
|
+
for (const sub of ['changes', 'changes/archive', 'discovery']) {
|
|
111
|
+
const keep = path.join(dir, sub, '.gitkeep');
|
|
112
|
+
if (!exists(keep)) {
|
|
113
|
+
fs.mkdirSync(path.dirname(keep), { recursive: true });
|
|
114
|
+
fs.writeFileSync(keep, '');
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
const gitignore = path.join(root, '.gitignore');
|
|
118
|
+
const current = exists(gitignore) ? readText(gitignore) : '';
|
|
119
|
+
const lines = new Set(current.split(/\r?\n/).map((l) => l.trim()));
|
|
120
|
+
const missing = GITIGNORE_BLOCK.filter((l) => !l.startsWith('#') && !lines.has(l));
|
|
121
|
+
if (missing.length > 0) {
|
|
122
|
+
const header = current.includes('# sbox:') ? '' : `${GITIGNORE_BLOCK[0]}\n`;
|
|
123
|
+
writeText(gitignore, `${current.trimEnd()}${current.trim() ? '\n\n' : ''}${header}${missing.join('\n')}\n`);
|
|
124
|
+
created.push(gitignore);
|
|
125
|
+
}
|
|
126
|
+
let hostFiles = [];
|
|
127
|
+
if (opts.host) {
|
|
128
|
+
if (opts.host !== 'claude')
|
|
129
|
+
throw new SboxError('HOST_NOT_READY', `Хост ${opts.host} ещё не поддержан; доступен claude.`);
|
|
130
|
+
hostFiles = installClaudeMaterials(root, exists(configFile) ? loadConfig(root) : undefined).map((f) => path.relative(root, f));
|
|
131
|
+
}
|
|
132
|
+
emit(g, { root, adapter, created: created.map((f) => path.relative(root, f)), host: hostFiles, notes }, (d) => [
|
|
133
|
+
`Инициализировано в ${d.root} (адаптер ${d.adapter})`,
|
|
134
|
+
...d.created.map((f) => ` + ${f}`),
|
|
135
|
+
...d.host.map((f) => ` + ${f}`),
|
|
136
|
+
...d.notes.map((n) => ` ! ${n}`),
|
|
137
|
+
'',
|
|
138
|
+
'Дальше:',
|
|
139
|
+
' 1. Заполните .sbox/project/*.md (или попросите researcher: `sbox change new` и роль соберёт черновик по коду).',
|
|
140
|
+
' 2. `sbox doctor` — проверка документации и спецификаций.',
|
|
141
|
+
...(d.host.length ? [' 3. В Claude Code: `/sbox-run` после `sbox change new <id> --title "..." --request "..."`.'] : [' 3. `sbox host install --target claude` — скиллы и агенты для Claude Code.']),
|
|
142
|
+
].join('\n'));
|
|
143
|
+
}
|
|
144
|
+
catch (e) {
|
|
145
|
+
emitError(g, e);
|
|
146
|
+
process.exitCode = 1;
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { loadChange, saveChange } from '../../core/change.js';
|
|
2
|
+
import { SboxError } from '../../core/errors.js';
|
|
3
|
+
import { allChangeDirs, changeMetrics, findChangeDir, summarize } from '../../core/metrics.js';
|
|
4
|
+
import { projectContext } from '../context.js';
|
|
5
|
+
import { emit, emitError } from '../output.js';
|
|
6
|
+
export function registerMetrics(program) {
|
|
7
|
+
program
|
|
8
|
+
.command('metrics')
|
|
9
|
+
.description('Метрики работы решателя: время, запуски, стоимость, возвраты, вмешательства, оценки')
|
|
10
|
+
.option('--change <id>', 'одно изменение (активное или архивное)')
|
|
11
|
+
.action((opts, cmd) => {
|
|
12
|
+
const g = cmd.optsWithGlobals();
|
|
13
|
+
try {
|
|
14
|
+
const ctx = projectContext(g.cwd);
|
|
15
|
+
const dirs = opts.change ? [findChangeDir(ctx.root, ctx.config, opts.change)].filter((d) => Boolean(d)) : allChangeDirs(ctx.root, ctx.config);
|
|
16
|
+
if (opts.change && dirs.length === 0)
|
|
17
|
+
throw new SboxError('NO_CHANGE', `Изменение ${opts.change} не найдено ни среди активных, ни в архиве`);
|
|
18
|
+
const all = dirs.map((d) => changeMetrics(d, loadChange(d)));
|
|
19
|
+
const summary = summarize(all);
|
|
20
|
+
emit(g, { changes: all, summary }, (d) => [
|
|
21
|
+
...d.changes.map((m) => [
|
|
22
|
+
`${m.id} (${m.status}, ${m.size}): запусков ${m.runs}, агенты ${m.agent_minutes} мин, стоимость ${m.cost_usd === null ? 'н/д' : `$${m.cost_usd}`}, вмешательств ${m.interventions.total}${m.autonomous ? ' (автономно)' : ''}${m.rating ? `, оценка ${m.rating.score}/5` : ''}`,
|
|
23
|
+
...Object.entries(m.phases).map(([ph, p]) => ` ${ph.padEnd(13)} запусков ${p.runs}, ${Math.round(p.agent_minutes)} мин${p.returns ? `, возвратов ${p.returns}` : ''}${p.rejections ? `, отклонений ${p.rejections}` : ''}`),
|
|
24
|
+
...Object.entries(m.gates).map(([gate, x]) => ` гейт ${gate.padEnd(9)} ${x.state}${x.wait_minutes !== null ? `, ожидание ${Math.round(x.wait_minutes)} мин` : ''}${x.rejected_times ? `, отклонён ${x.rejected_times} раз` : ''}`),
|
|
25
|
+
].join('\n')),
|
|
26
|
+
'',
|
|
27
|
+
`итого: изменений ${d.summary.changes}, завершено ${d.summary.finished}, автономно ${d.summary.autonomous_share === null ? 'н/д' : `${Math.round(d.summary.autonomous_share * 100)}%`}, медиана времени агентов ${d.summary.median_agent_minutes ?? 'н/д'} мин, медиана запусков ${d.summary.median_runs ?? 'н/д'}, стоимость ${d.summary.total_cost_usd === null ? 'н/д' : `$${d.summary.total_cost_usd}`}, средняя оценка ${d.summary.mean_rating ?? 'н/д'}, вмешательств на изменение ${d.summary.interventions_per_change ?? 'н/д'}`,
|
|
28
|
+
].join('\n'));
|
|
29
|
+
}
|
|
30
|
+
catch (e) {
|
|
31
|
+
emitError(g, e);
|
|
32
|
+
process.exitCode = 1;
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
export function registerRate(change) {
|
|
37
|
+
change
|
|
38
|
+
.command('rate <id>')
|
|
39
|
+
.description('Оценка результата человеком после проверки: 1–5 и комментарий')
|
|
40
|
+
.requiredOption('--score <n>', '1 (переделывать) … 5 (принял без правок)', (v) => Number.parseInt(v, 10))
|
|
41
|
+
.option('--comment <text>')
|
|
42
|
+
.action((id, opts, cmd) => {
|
|
43
|
+
const g = cmd.optsWithGlobals();
|
|
44
|
+
try {
|
|
45
|
+
const ctx = projectContext(g.cwd);
|
|
46
|
+
const dir = findChangeDir(ctx.root, ctx.config, id);
|
|
47
|
+
if (!dir)
|
|
48
|
+
throw new SboxError('NO_CHANGE', `Изменение ${id} не найдено`);
|
|
49
|
+
if (!(opts.score >= 1 && opts.score <= 5))
|
|
50
|
+
throw new SboxError('BAD_SCORE', 'Оценка от 1 до 5');
|
|
51
|
+
const c = loadChange(dir);
|
|
52
|
+
c.rating = { score: opts.score, at: new Date().toISOString(), ...(opts.comment ? { comment: opts.comment } : {}) };
|
|
53
|
+
saveChange(dir, c, { allowTerminalReopen: true });
|
|
54
|
+
emit(g, { id, rating: c.rating }, (d) => `Оценка ${d.rating.score}/5 записана для ${d.id}.`);
|
|
55
|
+
}
|
|
56
|
+
catch (e) {
|
|
57
|
+
emitError(g, e);
|
|
58
|
+
process.exitCode = 1;
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=metrics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../../src/cli/commands/metrics.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { SboxError } from '../../core/errors.js';
|
|
4
|
+
import { assetsDir, readText } from '../../core/paths.js';
|
|
5
|
+
import { projectContext } from '../context.js';
|
|
6
|
+
import { emit, emitError } from '../output.js';
|
|
7
|
+
const PROMPTS = {
|
|
8
|
+
'project-docs': { file: 'fill-project-docs.md', description: 'Заполнить .sbox/project/*.md по коду репозитория' },
|
|
9
|
+
};
|
|
10
|
+
/** Подстановки под адаптер спецификаций проекта. */
|
|
11
|
+
function substitutions(adapter) {
|
|
12
|
+
if (adapter === 'openspec') {
|
|
13
|
+
return {
|
|
14
|
+
SPEC_CHAIN: '«название capability › требование › сценарий» из `openspec/specs/<capability>/spec.md` (заголовки `# … Specification`, `### Requirement:`, `#### Scenario:`)',
|
|
15
|
+
SPEC_TRUTH: 'формат OpenSpec, файлы `openspec/specs/<capability>/spec.md`',
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
return {
|
|
19
|
+
SPEC_CHAIN: '«название фичи › группа › утверждение» из YAML spec-box (поля `feature`, ключ группы в `specs-unit`, `assert`)',
|
|
20
|
+
SPEC_TRUTH: 'формат spec-box, YAML-файлы по шаблонам из `.tms.json` или `spec.spec-box.files`',
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export function renderPrompt(name, adapter) {
|
|
24
|
+
const entry = PROMPTS[name];
|
|
25
|
+
if (!entry)
|
|
26
|
+
throw new SboxError('NO_PROMPT', `Нет промпта ${name}; доступны: ${Object.keys(PROMPTS).join(', ')}`);
|
|
27
|
+
const subs = substitutions(adapter);
|
|
28
|
+
return readText(path.join(assetsDir(), 'prompts', entry.file)).replace(/\{\{(\w+)\}\}/g, (_m, key) => subs[key] ?? `{{${key}}}`);
|
|
29
|
+
}
|
|
30
|
+
export function registerPrompt(program) {
|
|
31
|
+
const prompt = program.command('prompt').description('Готовые промпты для хоста разработчика');
|
|
32
|
+
prompt
|
|
33
|
+
.command('list')
|
|
34
|
+
.description('Список промптов')
|
|
35
|
+
.action((_opts, cmd) => {
|
|
36
|
+
const g = cmd.optsWithGlobals();
|
|
37
|
+
emit(g, { prompts: Object.entries(PROMPTS).map(([name, p]) => ({ name, description: p.description })) }, (d) => d.prompts.map((p) => `${p.name}\t${p.description}`).join('\n'));
|
|
38
|
+
});
|
|
39
|
+
prompt
|
|
40
|
+
.command('show <name>')
|
|
41
|
+
.description('Напечатать промпт с формулировками под адаптер проекта')
|
|
42
|
+
.option('--adapter <name>', 'spec-box | openspec (по умолчанию из конфига проекта)')
|
|
43
|
+
.action((name, opts, cmd) => {
|
|
44
|
+
const g = cmd.optsWithGlobals();
|
|
45
|
+
try {
|
|
46
|
+
let adapter = opts.adapter;
|
|
47
|
+
if (!adapter) {
|
|
48
|
+
try {
|
|
49
|
+
adapter = projectContext(g.cwd).config.spec.adapter;
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
adapter = 'spec-box';
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const text = renderPrompt(name, adapter);
|
|
56
|
+
if (g.json)
|
|
57
|
+
emit(g, { name, adapter, text }, () => text);
|
|
58
|
+
else
|
|
59
|
+
process.stdout.write(`${text.trimEnd()}\n`);
|
|
60
|
+
}
|
|
61
|
+
catch (e) {
|
|
62
|
+
emitError(g, e);
|
|
63
|
+
process.exitCode = 1;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
export { fs };
|
|
68
|
+
//# sourceMappingURL=prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../../src/cli/commands/prompt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { nextRunId, saveChange } from '../../core/change.js';
|
|
4
|
+
import { GATES } from '../../core/config.js';
|
|
5
|
+
import { SboxError } from '../../core/errors.js';
|
|
6
|
+
import { buildPacket } from '../../core/packet.js';
|
|
7
|
+
import { exists, readText, toPosix, writeText } from '../../core/paths.js';
|
|
8
|
+
import { approveGate, isRoleName, nextStep, rejectGate, ROLE_BY_PHASE } from '../../core/phases.js';
|
|
9
|
+
import { applyReport } from '../../core/report.js';
|
|
10
|
+
import { artifactStates, loadWorkflow } from '../../core/schema.js';
|
|
11
|
+
import { changeContext } from '../context.js';
|
|
12
|
+
import { emit, emitError, formatDiagnostics } from '../output.js';
|
|
13
|
+
export function registerProtocol(program) {
|
|
14
|
+
program
|
|
15
|
+
.command('next')
|
|
16
|
+
.description('Следующий шаг изменения: пакет для роли, гейт, доставка или ожидание')
|
|
17
|
+
.option('--change <id>', 'идентификатор изменения')
|
|
18
|
+
.option('--brief', 'не печатать пакет целиком: только роль, фаза, путь к пакету и команда отчёта')
|
|
19
|
+
.action(async (opts, cmd) => {
|
|
20
|
+
const g = cmd.optsWithGlobals();
|
|
21
|
+
try {
|
|
22
|
+
const ctx = changeContext(g.cwd, opts.change);
|
|
23
|
+
const step = nextStep(ctx.change, ctx.config);
|
|
24
|
+
if (step.kind === 'role') {
|
|
25
|
+
if (ctx.change.phase === 'intake') {
|
|
26
|
+
ctx.change.phase = 'research';
|
|
27
|
+
saveChange(ctx.dir, ctx.change);
|
|
28
|
+
}
|
|
29
|
+
const truthSources = (await ctx.adapter.readTruth()).map((c) => c.source ?? c.id);
|
|
30
|
+
const packet = buildPacket({ ...ctx, role: step.role, phase: step.phase, truthSources });
|
|
31
|
+
const packetFile = path.join(ctx.dir, 'runs', packet.runId, 'packet.json');
|
|
32
|
+
writeText(packetFile, JSON.stringify(packet, null, 2));
|
|
33
|
+
const rel = toPosix(path.relative(ctx.root, packetFile));
|
|
34
|
+
const brief = { kind: 'role', role: step.role, phase: step.phase, runId: packet.runId, packetFile: rel, resultFile: packet.resultFile, objective: packet.objective, feedback: packet.feedback, report: packet.commands.report };
|
|
35
|
+
if (opts.brief) {
|
|
36
|
+
emit(g, brief, (d) => [`Шаг: роль ${d.role}, фаза ${d.phase}`, `Пакет: ${d.packetFile}`, `Цель: ${d.objective}`, ...(d.feedback ? [`Фидбэк: ${d.feedback.slice(0, 300)}`] : []), `Отчёт: ${d.report}`].join('\n'));
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
emit(g, { ...brief, packet }, (d) => [`Шаг: роль ${d.role}, фаза ${d.phase}`, `Пакет: ${d.packetFile}`, `Цель: ${d.objective}`, `Отчёт: ${d.report}`].join('\n'));
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (step.kind === 'gate') {
|
|
43
|
+
const states = artifactStates(loadWorkflow(ctx.root), ctx.change, ctx.dir);
|
|
44
|
+
const review = states.filter((s) => s.existing.length > 0).map((s) => ({ id: s.id, files: s.existing.map((f) => toPosix(path.relative(ctx.root, f))) }));
|
|
45
|
+
const questions = pendingQuestions(ctx.change);
|
|
46
|
+
emit(g, { kind: 'gate', gate: step.gate, phase: step.phase, review, questions, approve: `sbox approve ${step.gate} --change ${ctx.change.id} --by <user>`, reject: `sbox reject ${step.gate} --change ${ctx.change.id} --comment "<замечание>"` }, (d) => [`Гейт ${d.gate}: нужно решение человека.`, 'Посмотрите:', ...d.review.flatMap((r) => r.files.map((f) => ` ${f}`)), ...(d.questions.length ? ['Вопросы:', ...d.questions.map((q) => ` ${q}`)] : []), `Утвердить: ${d.approve}`, `Отклонить: ${d.reject}`].join('\n'));
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (step.kind === 'deliver') {
|
|
50
|
+
emit(g, { kind: 'deliver', archive: `sbox archive --change ${ctx.change.id}` }, (d) => `Изменение готово к доставке. Архивация: ${d.archive}`);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (step.kind === 'wait') {
|
|
54
|
+
emit(g, { kind: 'wait', status: step.status, blocker: step.blocker }, (d) => `Ожидание: статус ${d.status}${d.blocker ? `, блокер ${d.blocker.category}: ${d.blocker.message}` : ''}`);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
emit(g, { kind: 'done' }, () => 'Изменение завершено.');
|
|
58
|
+
}
|
|
59
|
+
catch (e) {
|
|
60
|
+
emitError(g, e);
|
|
61
|
+
process.exitCode = 1;
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
program
|
|
65
|
+
.command('report')
|
|
66
|
+
.description('Принять ответ роли и перевести изменение дальше')
|
|
67
|
+
.requiredOption('--role <role>', 'роль')
|
|
68
|
+
.option('--file <path>', 'файл с ответом роли; по умолчанию runs/<следующий запуск>/result.md')
|
|
69
|
+
.option('--change <id>', 'идентификатор изменения')
|
|
70
|
+
.option('--phase <phase>', 'фаза, если отличается от текущей')
|
|
71
|
+
.option('--runner <name>', 'адаптер среды')
|
|
72
|
+
.option('--model <name>', 'модель')
|
|
73
|
+
.option('--session <id>', 'идентификатор сессии агента')
|
|
74
|
+
.action(async (opts, cmd) => {
|
|
75
|
+
const g = cmd.optsWithGlobals();
|
|
76
|
+
try {
|
|
77
|
+
const ctx = changeContext(g.cwd, opts.change);
|
|
78
|
+
if (!isRoleName(opts.role))
|
|
79
|
+
throw new SboxError('BAD_ROLE', `Неизвестная роль ${opts.role}`);
|
|
80
|
+
const step = nextStep(ctx.change, ctx.config);
|
|
81
|
+
const phase = opts.phase ?? (step.kind === 'role' ? step.phase : ctx.change.phase);
|
|
82
|
+
const expected = ROLE_BY_PHASE[phase];
|
|
83
|
+
if (expected && expected !== opts.role)
|
|
84
|
+
throw new SboxError('ROLE_MISMATCH', `Фаза ${phase} ожидает роль ${expected}, а не ${opts.role}.`);
|
|
85
|
+
const file = opts.file ? path.resolve(opts.file) : path.join(ctx.dir, 'runs', nextRunId(ctx.change), 'result.md');
|
|
86
|
+
if (!exists(file))
|
|
87
|
+
throw new SboxError('NO_FILE', `Нет файла ${file}`, 'Роль пишет ответ в resultFile из пакета; укажите --file, если ответ лежит в другом месте.');
|
|
88
|
+
const outcome = await applyReport({ ...ctx, role: opts.role, phase, markdown: readText(file), adapter: ctx.adapter, receipt: { runner: opts.runner, model: opts.model, session: opts.session } });
|
|
89
|
+
const rejected = outcome.diagnostics.some((d) => d.severity === 'error');
|
|
90
|
+
emit(g, { runId: outcome.runId, status: outcome.result.status, phaseCompleted: outcome.phaseCompleted, accepted: !rejected, diagnostics: outcome.diagnostics, change: { phase: ctx.change.phase, status: ctx.change.status, blocker: ctx.change.blocker }, next: outcome.next }, (d) => [`Запуск ${d.runId}: статус роли «${d.status}», ${d.accepted ? (d.phaseCompleted ? 'фаза завершена' : 'фаза не завершена') : 'отчёт не принят'}`, formatDiagnostics(d.diagnostics), `Изменение: фаза ${d.change.phase}, статус ${d.change.status}`, `Дальше: ${JSON.stringify(d.next)}`].join('\n'));
|
|
91
|
+
if (rejected)
|
|
92
|
+
process.exitCode = 1;
|
|
93
|
+
}
|
|
94
|
+
catch (e) {
|
|
95
|
+
emitError(g, e);
|
|
96
|
+
process.exitCode = 1;
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
program
|
|
100
|
+
.command('approve <gate>')
|
|
101
|
+
.description('Утвердить гейт (proposal | plan | tests)')
|
|
102
|
+
.option('--change <id>')
|
|
103
|
+
.option('--by <user>', 'кто утвердил', process.env.USER ?? 'human')
|
|
104
|
+
.option('--comment <text>')
|
|
105
|
+
.option('--answer <pairs...>', 'ответы на вопросы: Q1=B Q2=A')
|
|
106
|
+
.action((gate, opts, cmd) => {
|
|
107
|
+
const g = cmd.optsWithGlobals();
|
|
108
|
+
try {
|
|
109
|
+
const ctx = changeContext(g.cwd, opts.change);
|
|
110
|
+
assertGate(gate);
|
|
111
|
+
const answers = Object.fromEntries((opts.answer ?? []).map((p) => { const [k, ...v] = p.split('='); return [k, v.join('=')]; }));
|
|
112
|
+
approveGate(ctx.change, gate, opts.by, opts.comment, Object.keys(answers).length ? answers : undefined);
|
|
113
|
+
saveChange(ctx.dir, ctx.change);
|
|
114
|
+
emit(g, { gate, phase: ctx.change.phase, status: ctx.change.status, next: nextStep(ctx.change, ctx.config) }, (d) => `Гейт ${d.gate} утверждён. Фаза ${d.phase}, статус ${d.status}.`);
|
|
115
|
+
}
|
|
116
|
+
catch (e) {
|
|
117
|
+
emitError(g, e);
|
|
118
|
+
process.exitCode = 1;
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
program
|
|
122
|
+
.command('reject <gate>')
|
|
123
|
+
.description('Отклонить гейт с замечанием')
|
|
124
|
+
.option('--change <id>')
|
|
125
|
+
.option('--by <user>', 'кто отклонил', process.env.USER ?? 'human')
|
|
126
|
+
.requiredOption('--comment <text>', 'замечание для планировщика или тестировщика')
|
|
127
|
+
.action((gate, opts, cmd) => {
|
|
128
|
+
const g = cmd.optsWithGlobals();
|
|
129
|
+
try {
|
|
130
|
+
const ctx = changeContext(g.cwd, opts.change);
|
|
131
|
+
assertGate(gate);
|
|
132
|
+
rejectGate(ctx.change, gate, opts.by, opts.comment);
|
|
133
|
+
saveChange(ctx.dir, ctx.change);
|
|
134
|
+
emit(g, { gate, phase: ctx.change.phase, status: ctx.change.status, next: nextStep(ctx.change, ctx.config) }, (d) => `Гейт ${d.gate} отклонён. Возврат в фазу ${d.phase}.`);
|
|
135
|
+
}
|
|
136
|
+
catch (e) {
|
|
137
|
+
emitError(g, e);
|
|
138
|
+
process.exitCode = 1;
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
function assertGate(gate) {
|
|
143
|
+
if (!GATES.includes(gate))
|
|
144
|
+
throw new SboxError('BAD_GATE', `Неизвестный гейт ${gate}; допустимы: ${GATES.join(', ')}`);
|
|
145
|
+
}
|
|
146
|
+
function pendingQuestions(change) {
|
|
147
|
+
// Вопросы planner лежат в его последнем ответе; для человека их достаточно показать ссылкой на design.md.
|
|
148
|
+
return [];
|
|
149
|
+
}
|
|
150
|
+
export { fs };
|
|
151
|
+
//# sourceMappingURL=protocol.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../../src/cli/commands/protocol.ts"],"names":[],"mappings":"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"}
|