theslopmachine 0.3.7 → 0.4.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/MANUAL.md +13 -9
- package/README.md +163 -3
- package/RELEASE.md +11 -3
- package/assets/agents/developer-v2.md +86 -0
- package/assets/agents/developer.md +21 -23
- package/assets/agents/slopmachine-v2.md +219 -0
- package/assets/agents/slopmachine.md +56 -38
- package/assets/skills/beads-operations/SKILL.md +32 -31
- package/assets/skills/beads-operations-v2/SKILL.md +82 -0
- package/assets/skills/clarification-gate/SKILL.md +8 -1
- package/assets/skills/clarification-gate-v2/SKILL.md +74 -0
- package/assets/skills/developer-session-lifecycle/SKILL.md +45 -14
- package/assets/skills/developer-session-lifecycle-v2/SKILL.md +148 -0
- package/assets/skills/development-guidance-v2/SKILL.md +60 -0
- package/assets/skills/evaluation-triage-v2/SKILL.md +38 -0
- package/assets/skills/final-evaluation-orchestration/SKILL.md +9 -11
- package/assets/skills/final-evaluation-orchestration-v2/SKILL.md +57 -0
- package/assets/skills/get-overlays/SKILL.md +77 -6
- package/assets/skills/hardening-gate-v2/SKILL.md +64 -0
- package/assets/skills/integrated-verification-v2/SKILL.md +47 -0
- package/assets/skills/owner-evidence-discipline-v2/SKILL.md +15 -0
- package/assets/skills/planning-gate/SKILL.md +6 -4
- package/assets/skills/planning-gate-v2/SKILL.md +91 -0
- package/assets/skills/planning-guidance-v2/SKILL.md +100 -0
- package/assets/skills/remediation-guidance-v2/SKILL.md +31 -0
- package/assets/skills/report-output-discipline-v2/SKILL.md +15 -0
- package/assets/skills/scaffold-guidance-v2/SKILL.md +57 -0
- package/assets/skills/session-rollover-v2/SKILL.md +41 -0
- package/assets/skills/submission-packaging/SKILL.md +147 -115
- package/assets/skills/submission-packaging-v2/SKILL.md +142 -0
- package/assets/skills/verification-gates/SKILL.md +44 -16
- package/assets/skills/verification-gates-v2/SKILL.md +102 -0
- package/assets/slopmachine/backend-evaluation-prompt.md +9 -2
- package/assets/slopmachine/frontend-evaluation-prompt.md +9 -2
- package/assets/slopmachine/templates/AGENTS-v2.md +55 -0
- package/assets/slopmachine/templates/AGENTS.md +20 -17
- package/assets/slopmachine/tracker-init.js +104 -0
- package/assets/slopmachine/workflow-init-v2.js +99 -0
- package/package.json +1 -1
- package/src/constants.js +22 -3
- package/src/init.js +33 -28
- package/src/install.js +186 -140
- package/src/utils.js +19 -0
- package/assets/slopmachine/beads-init.js +0 -439
|
@@ -1,439 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import fs from 'node:fs/promises'
|
|
4
|
-
import path from 'node:path'
|
|
5
|
-
import { spawn } from 'node:child_process'
|
|
6
|
-
|
|
7
|
-
const targetInput = process.argv[2] || '.'
|
|
8
|
-
const target = path.resolve(process.cwd(), targetInput)
|
|
9
|
-
const bdCommand = process.env.BD_COMMAND || 'bd'
|
|
10
|
-
|
|
11
|
-
function log(message) {
|
|
12
|
-
console.log(`[beads-init] ${message}`)
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function die(message) {
|
|
16
|
-
console.error(`[beads-init] ERROR: ${message}`)
|
|
17
|
-
process.exit(1)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function quoteShellArg(value) {
|
|
21
|
-
if (/^[A-Za-z0-9_./:-]+$/.test(value)) {
|
|
22
|
-
return value
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
return `'${value.replaceAll(`'`, `'\\''`)}'`
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function run(command, args, options = {}) {
|
|
29
|
-
return new Promise((resolve, reject) => {
|
|
30
|
-
const child = spawn(command, args, {
|
|
31
|
-
cwd: options.cwd,
|
|
32
|
-
env: options.env || process.env,
|
|
33
|
-
stdio: options.stdio || 'pipe',
|
|
34
|
-
shell: false,
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
let stdout = ''
|
|
38
|
-
let stderr = ''
|
|
39
|
-
|
|
40
|
-
if (child.stdout) child.stdout.on('data', (chunk) => { stdout += chunk.toString() })
|
|
41
|
-
if (child.stderr) child.stderr.on('data', (chunk) => { stderr += chunk.toString() })
|
|
42
|
-
|
|
43
|
-
if (options.input !== undefined && child.stdin) {
|
|
44
|
-
child.stdin.write(options.input)
|
|
45
|
-
child.stdin.end()
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
child.on('error', reject)
|
|
49
|
-
child.on('close', (code) => resolve({ code: code ?? 1, stdout, stderr }))
|
|
50
|
-
})
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
async function commandExists(command) {
|
|
54
|
-
const checker = process.platform === 'win32' ? 'where' : 'which'
|
|
55
|
-
const result = await run(checker, [command])
|
|
56
|
-
return result.code === 0
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
async function pathExists(targetPath) {
|
|
60
|
-
try {
|
|
61
|
-
await fs.access(targetPath)
|
|
62
|
-
return true
|
|
63
|
-
} catch {
|
|
64
|
-
return false
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
async function runBd(args, options = {}) {
|
|
69
|
-
return run(bdCommand, args, { cwd: target, ...options })
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
async function runBdNoninteractive(args) {
|
|
73
|
-
return run(bdCommand, args, {
|
|
74
|
-
cwd: target,
|
|
75
|
-
env: { ...process.env, CI: '1' },
|
|
76
|
-
input: '',
|
|
77
|
-
})
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
async function supportsInitFlag(flag) {
|
|
81
|
-
const help = await run(bdCommand, ['init', '--help'])
|
|
82
|
-
return `${help.stdout}${help.stderr}`.includes(flag)
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
async function chooseNoninteractiveInitModeFlag(isGitRepo) {
|
|
86
|
-
if (!isGitRepo) return null
|
|
87
|
-
const help = await run(bdCommand, ['init', '--help'])
|
|
88
|
-
const text = `${help.stdout}${help.stderr}`
|
|
89
|
-
if (text.includes('--setup-exclude')) return '--setup-exclude'
|
|
90
|
-
if (text.includes('--stealth')) return '--stealth'
|
|
91
|
-
return null
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
async function configureGitMergeDriver() {
|
|
95
|
-
const attributesFile = path.join(target, '.git', 'info', 'attributes')
|
|
96
|
-
const attributesLine = '.beads/*.jsonl merge=beads'
|
|
97
|
-
const mergeDriverCommand = `${quoteShellArg(bdCommand)} merge %A %O %A %B`
|
|
98
|
-
|
|
99
|
-
log('Configuring local git merge driver for Beads')
|
|
100
|
-
let result = await run('git', ['-C', target, 'config', 'merge.beads.driver', mergeDriverCommand])
|
|
101
|
-
if (result.code !== 0) die(result.stderr || 'Failed configuring git merge driver')
|
|
102
|
-
|
|
103
|
-
await fs.mkdir(path.dirname(attributesFile), { recursive: true })
|
|
104
|
-
if (!(await pathExists(attributesFile))) {
|
|
105
|
-
await fs.writeFile(attributesFile, '', 'utf8')
|
|
106
|
-
}
|
|
107
|
-
const content = await fs.readFile(attributesFile, 'utf8')
|
|
108
|
-
const lines = new Set(content.split(/\r?\n/))
|
|
109
|
-
if (!lines.has(attributesLine)) {
|
|
110
|
-
const prefix = content.endsWith('\n') || content.length === 0 ? '' : '\n'
|
|
111
|
-
await fs.appendFile(attributesFile, `${prefix}${attributesLine}\n`, 'utf8')
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
async function configureGitRoleMaintainer() {
|
|
116
|
-
log('Setting local Beads role to maintainer')
|
|
117
|
-
const result = await run('git', ['-C', target, 'config', 'beads.role', 'maintainer'])
|
|
118
|
-
if (result.code !== 0) die(result.stderr || 'Failed setting beads.role maintainer')
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
function parseDoctorJson(raw) {
|
|
122
|
-
if (!raw.trim()) {
|
|
123
|
-
return { errors: -1, warnings: 0, known: 0, warnMissingJsonl: 0, warnDoltDirty: 0, warnSyncBranch: 0 }
|
|
124
|
-
}
|
|
125
|
-
let data
|
|
126
|
-
try {
|
|
127
|
-
data = JSON.parse(raw)
|
|
128
|
-
} catch {
|
|
129
|
-
return { errors: -1, warnings: 0, known: 0, warnMissingJsonl: 0, warnDoltDirty: 0, warnSyncBranch: 0 }
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const checks = Array.isArray(data.checks) ? data.checks : []
|
|
133
|
-
let errors = 0
|
|
134
|
-
let warnings = 0
|
|
135
|
-
let known = 0
|
|
136
|
-
let warnMissingJsonl = 0
|
|
137
|
-
let warnDoltDirty = 0
|
|
138
|
-
let warnSyncBranch = 0
|
|
139
|
-
|
|
140
|
-
for (const check of checks) {
|
|
141
|
-
const name = `${check.name || ''}`.trim()
|
|
142
|
-
const status = check.status
|
|
143
|
-
const text = `${check.message || ''} ${check.detail || ''}`.toLowerCase()
|
|
144
|
-
|
|
145
|
-
if (status === 'error') {
|
|
146
|
-
errors += 1
|
|
147
|
-
if (text.includes('database not found: beads')) known = 1
|
|
148
|
-
if (name === 'Dolt Schema' && ['issues', 'dependencies', 'config', 'labels', 'events'].every((term) => text.includes(term))) {
|
|
149
|
-
known = 1
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
if (status === 'warning') {
|
|
154
|
-
warnings += 1
|
|
155
|
-
if (name === 'Dolt-JSONL Sync' && (text.includes('could not read jsonl file') || text.includes('no such file or directory'))) {
|
|
156
|
-
warnMissingJsonl = 1
|
|
157
|
-
}
|
|
158
|
-
if (name === 'Dolt Status' || name === 'Dolt Locks') {
|
|
159
|
-
warnDoltDirty = 1
|
|
160
|
-
}
|
|
161
|
-
if (name === 'Sync Branch Config' && text.includes('not configured')) {
|
|
162
|
-
warnSyncBranch = 1
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
return { errors, warnings, known, warnMissingJsonl, warnDoltDirty, warnSyncBranch }
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
async function getActiveDbName() {
|
|
171
|
-
const metadataPath = path.join(target, '.beads', 'metadata.json')
|
|
172
|
-
if (await pathExists(metadataPath)) {
|
|
173
|
-
try {
|
|
174
|
-
const metadata = JSON.parse(await fs.readFile(metadataPath, 'utf8'))
|
|
175
|
-
if (metadata.dolt_database) {
|
|
176
|
-
return metadata.dolt_database
|
|
177
|
-
}
|
|
178
|
-
} catch {
|
|
179
|
-
// ignore and fall through
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
const showDatabases = await runBd(['sql', '-q', 'SHOW DATABASES;'])
|
|
184
|
-
const names = `${showDatabases.stdout}${showDatabases.stderr}`
|
|
185
|
-
.split(/\r?\n/)
|
|
186
|
-
.map((line) => line.trim())
|
|
187
|
-
.filter((line) => line && !/^[-]+$/.test(line))
|
|
188
|
-
.filter((line) => !['database', 'information_schema', '(2 rows)', '(1 row)'].includes(line.toLowerCase()))
|
|
189
|
-
.filter((line) => !(line.startsWith('(') && line.endsWith('rows)')))
|
|
190
|
-
|
|
191
|
-
return names.find((name) => !['beads', 'information_schema'].includes(name)) || ''
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
async function knownDoltFix(sourceDb) {
|
|
195
|
-
if (!sourceDb) return false
|
|
196
|
-
log(`Applying known Dolt doctor fix using source DB '${sourceDb}'`)
|
|
197
|
-
let result = await runBd(['sql', '-q', 'CREATE DATABASE IF NOT EXISTS beads;'])
|
|
198
|
-
if (result.code !== 0) return false
|
|
199
|
-
for (const table of ['issues', 'dependencies', 'config', 'labels', 'events']) {
|
|
200
|
-
result = await runBd(['sql', '-q', `CREATE TABLE IF NOT EXISTS beads.${table} LIKE \`${sourceDb}\`.${table};`])
|
|
201
|
-
if (result.code !== 0) return false
|
|
202
|
-
}
|
|
203
|
-
return true
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
async function ensureBeadsJsonl() {
|
|
207
|
-
const jsonlPath = path.join(target, '.beads', 'beads.jsonl')
|
|
208
|
-
if (await pathExists(jsonlPath)) return true
|
|
209
|
-
log('Ensuring .beads/beads.jsonl exists')
|
|
210
|
-
const exportResult = await runBd(['export', '--force', '-o', '.beads/beads.jsonl'])
|
|
211
|
-
if (exportResult.code === 0) return true
|
|
212
|
-
await fs.writeFile(jsonlPath, '', 'utf8')
|
|
213
|
-
return true
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
async function getPendingDoltSchemaCount() {
|
|
217
|
-
const result = await runBd(['--json', 'sql', 'SELECT COUNT(*) AS pending FROM beads.dolt_status;'])
|
|
218
|
-
if (result.code !== 0 || !result.stdout.trim()) return 0
|
|
219
|
-
try {
|
|
220
|
-
const data = JSON.parse(result.stdout)
|
|
221
|
-
if (Array.isArray(data) && data[0] && typeof data[0] === 'object') {
|
|
222
|
-
return Number(data[0].pending || 0)
|
|
223
|
-
}
|
|
224
|
-
} catch {
|
|
225
|
-
return 0
|
|
226
|
-
}
|
|
227
|
-
return 0
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
async function commitPendingDoltSchema(activeDb) {
|
|
231
|
-
const pending = await getPendingDoltSchemaCount()
|
|
232
|
-
if (pending <= 0) return true
|
|
233
|
-
log("Committing pending Dolt schema changes in fallback 'beads' DB")
|
|
234
|
-
|
|
235
|
-
let switched = false
|
|
236
|
-
if (activeDb && activeDb !== 'beads') {
|
|
237
|
-
const setResult = await runBd(['dolt', 'set', 'database', 'beads'])
|
|
238
|
-
if (setResult.code !== 0) return false
|
|
239
|
-
switched = true
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
const commitResult = await runBd(['vc', 'commit', '-m', 'Auto-commit initial fallback schema tables for bd doctor'])
|
|
243
|
-
|
|
244
|
-
if (switched) {
|
|
245
|
-
await runBd(['dolt', 'set', 'database', activeDb])
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
if (commitResult.code === 0) return true
|
|
249
|
-
const lower = `${commitResult.stdout}${commitResult.stderr}`.toLowerCase()
|
|
250
|
-
if (lower.includes('nothing to commit') || lower.includes('no changes') || lower.includes('clean working set')) {
|
|
251
|
-
return true
|
|
252
|
-
}
|
|
253
|
-
console.error(commitResult.stdout || commitResult.stderr)
|
|
254
|
-
return false
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
async function configureSyncBranchReconciled() {
|
|
258
|
-
const syncBranchName = 'beads-sync'
|
|
259
|
-
log(`Reconciling sync.branch (${syncBranchName})`)
|
|
260
|
-
|
|
261
|
-
let result = await runBd(['config', 'set', 'sync.branch', syncBranchName])
|
|
262
|
-
if (result.code !== 0) return false
|
|
263
|
-
|
|
264
|
-
result = await runBdNoninteractive(['migrate', 'sync', syncBranchName, '--yes'])
|
|
265
|
-
if (result.code !== 0) {
|
|
266
|
-
result = await runBdNoninteractive(['migrate', 'sync', syncBranchName])
|
|
267
|
-
if (result.code !== 0) {
|
|
268
|
-
if (`${result.stdout}${result.stderr}`.trim()) {
|
|
269
|
-
console.error(`${result.stdout}${result.stderr}`.trim())
|
|
270
|
-
}
|
|
271
|
-
log("WARNING: 'bd migrate sync' failed; validating config directly")
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
const configResult = await runBd(['config', 'get', 'sync.branch'])
|
|
276
|
-
const combined = `${configResult.stdout}${configResult.stderr}`
|
|
277
|
-
if (!combined.includes(syncBranchName)) {
|
|
278
|
-
if (combined.trim()) console.error(combined.trim())
|
|
279
|
-
return false
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
log(`Verified sync.branch: ${combined.trim()}`)
|
|
283
|
-
return true
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
async function installGitHooksNonfatal() {
|
|
287
|
-
log('Installing Beads git hooks')
|
|
288
|
-
const result = await runBd(['hooks', 'install'])
|
|
289
|
-
if (result.code === 0) {
|
|
290
|
-
if (`${result.stdout}`.trim()) {
|
|
291
|
-
console.log(result.stdout.trim())
|
|
292
|
-
}
|
|
293
|
-
return true
|
|
294
|
-
}
|
|
295
|
-
if (`${result.stdout}${result.stderr}`.trim()) {
|
|
296
|
-
console.error(`${result.stdout}${result.stderr}`.trim())
|
|
297
|
-
}
|
|
298
|
-
return false
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
async function main() {
|
|
302
|
-
const bdAvailable = bdCommand !== 'bd' ? await pathExists(bdCommand) : await commandExists('bd')
|
|
303
|
-
if (!bdAvailable) {
|
|
304
|
-
die(`'${bdCommand}' is not available. Install Beads first.`)
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
if (!(await pathExists(target))) {
|
|
308
|
-
die(`Target directory '${targetInput}' does not exist or is not accessible.`)
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
const gitCheck = await run('git', ['-C', target, 'rev-parse', '--is-inside-work-tree'])
|
|
312
|
-
const isGitRepo = gitCheck.code === 0
|
|
313
|
-
|
|
314
|
-
log(`Target: ${target}`)
|
|
315
|
-
log(`Mode: ${isGitRepo ? 'git repository' : 'non-git directory'}`)
|
|
316
|
-
|
|
317
|
-
const beadsDir = path.join(target, '.beads')
|
|
318
|
-
if (!(await pathExists(beadsDir))) {
|
|
319
|
-
if (isGitRepo) {
|
|
320
|
-
await configureGitRoleMaintainer()
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
const initArgs = ['init', '--quiet']
|
|
324
|
-
const initModeFlag = await chooseNoninteractiveInitModeFlag(isGitRepo)
|
|
325
|
-
if (initModeFlag) initArgs.push(initModeFlag)
|
|
326
|
-
if (await supportsInitFlag('--skip-hooks')) initArgs.push('--skip-hooks')
|
|
327
|
-
|
|
328
|
-
log(`Running non-interactive 'bd ${initArgs.join(' ')}' (CI=1, stdin=/dev/null)`)
|
|
329
|
-
const initResult = await runBdNoninteractive(initArgs)
|
|
330
|
-
if (initResult.code !== 0) {
|
|
331
|
-
console.error(`${initResult.stdout}${initResult.stderr}`.trim())
|
|
332
|
-
die("'bd init' failed. Review output above.")
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
if (isGitRepo) {
|
|
336
|
-
await configureGitMergeDriver()
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
if (initResult.stdout.trim()) {
|
|
340
|
-
console.log(initResult.stdout.trim())
|
|
341
|
-
}
|
|
342
|
-
} else {
|
|
343
|
-
log('Found existing .beads; skipping init to avoid destructive re-initialization')
|
|
344
|
-
if (isGitRepo) {
|
|
345
|
-
await configureGitMergeDriver()
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
let hooksInstallStatus = 'not-applicable'
|
|
350
|
-
if (isGitRepo) {
|
|
351
|
-
if (await installGitHooksNonfatal()) {
|
|
352
|
-
hooksInstallStatus = 'installed'
|
|
353
|
-
} else {
|
|
354
|
-
hooksInstallStatus = 'failed'
|
|
355
|
-
log("WARNING: 'bd hooks install' failed; continuing to doctor")
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
if (!(await configureSyncBranchReconciled())) {
|
|
359
|
-
die('Failed to reconcile sync.branch to beads-sync')
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
const doctorBefore = await runBd(['doctor'])
|
|
364
|
-
const doctorJson = await runBd(['doctor', '--json'])
|
|
365
|
-
const parsedBefore = parseDoctorJson(doctorJson.stdout)
|
|
366
|
-
if (parsedBefore.errors === -1) {
|
|
367
|
-
console.log(doctorBefore.stdout)
|
|
368
|
-
die("Unable to parse 'bd doctor --json'. Run 'bd doctor --verbose' manually.")
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
if (parsedBefore.errors > 0 && parsedBefore.known === 1) {
|
|
372
|
-
const sourceDb = await getActiveDbName()
|
|
373
|
-
if (!sourceDb) {
|
|
374
|
-
console.log(doctorBefore.stdout)
|
|
375
|
-
die('Detected known Dolt issue but could not determine active DB name from .beads/metadata.json or SHOW DATABASES.')
|
|
376
|
-
}
|
|
377
|
-
if (!(await knownDoltFix(sourceDb))) {
|
|
378
|
-
console.log(doctorBefore.stdout)
|
|
379
|
-
die('Detected known Dolt issue, but auto-fix failed while creating fallback schema.')
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
const doctorPostFix = await runBd(['doctor', '--json'])
|
|
384
|
-
const parsedPostFix = parseDoctorJson(doctorPostFix.stdout)
|
|
385
|
-
if (parsedPostFix.warnings === -1 || parsedPostFix.known === -1) {
|
|
386
|
-
console.log(doctorBefore.stdout)
|
|
387
|
-
die("Unable to parse post-fix 'bd doctor --json'.")
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
if (parsedPostFix.warnMissingJsonl === 1) {
|
|
391
|
-
if (!(await ensureBeadsJsonl())) {
|
|
392
|
-
die('Failed to ensure .beads/beads.jsonl exists')
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
if (parsedPostFix.warnDoltDirty === 1) {
|
|
397
|
-
const activeDb = await getActiveDbName()
|
|
398
|
-
if (!(await commitPendingDoltSchema(activeDb))) {
|
|
399
|
-
die('Failed to auto-commit pending Dolt schema changes')
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
if (parsedPostFix.warnSyncBranch === 1) {
|
|
404
|
-
if (!(await configureSyncBranchReconciled())) {
|
|
405
|
-
die('Failed to configure sync.branch')
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
const doctorAfter = await runBd(['doctor'])
|
|
410
|
-
const doctorAfterJson = await runBd(['doctor', '--json'])
|
|
411
|
-
const parsedAfter = parseDoctorJson(doctorAfterJson.stdout)
|
|
412
|
-
|
|
413
|
-
if (doctorAfter.stdout.trim()) {
|
|
414
|
-
console.log(doctorAfter.stdout.trim())
|
|
415
|
-
}
|
|
416
|
-
if (parsedAfter.errors === -1) {
|
|
417
|
-
die("Initialization finished, but doctor JSON parse failed. Run: bd doctor --verbose")
|
|
418
|
-
}
|
|
419
|
-
if (parsedAfter.warnings === -1 || parsedAfter.known === -1) {
|
|
420
|
-
die("Initialization finished, but post-init warning parse failed. Run: bd doctor --verbose")
|
|
421
|
-
}
|
|
422
|
-
if (parsedAfter.errors > 0) {
|
|
423
|
-
die(`'bd doctor' still reports ${parsedAfter.errors} error(s). Run 'bd doctor --verbose' and inspect .beads/metadata.json.`)
|
|
424
|
-
}
|
|
425
|
-
if (isGitRepo && parsedAfter.warnSyncBranch === 1) {
|
|
426
|
-
die("'bd doctor' still reports Sync Branch Config warning: sync-branch not configured.")
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
log('Success: bd initialized and doctor reports zero errors')
|
|
430
|
-
if (hooksInstallStatus === 'installed') {
|
|
431
|
-
log('Hooks: Beads git hooks installed')
|
|
432
|
-
} else if (hooksInstallStatus === 'failed') {
|
|
433
|
-
log('Hooks: WARNING - installation failed (non-fatal)')
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
main().catch((error) => {
|
|
438
|
-
die(error instanceof Error ? error.message : String(error))
|
|
439
|
-
})
|