theslopmachine 0.7.0 → 0.7.2

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.
Files changed (30) hide show
  1. package/README.md +1 -1
  2. package/RELEASE.md +2 -2
  3. package/assets/agents/developer.md +13 -13
  4. package/assets/agents/slopmachine-claude.md +7 -5
  5. package/assets/agents/slopmachine.md +6 -5
  6. package/assets/claude/agents/developer.md +6 -6
  7. package/assets/skills/clarification-gate/SKILL.md +9 -18
  8. package/assets/skills/claude-worker-management/SKILL.md +34 -22
  9. package/assets/skills/developer-session-lifecycle/SKILL.md +2 -1
  10. package/assets/skills/development-guidance/SKILL.md +3 -0
  11. package/assets/skills/evaluation-triage/SKILL.md +6 -4
  12. package/assets/skills/final-evaluation-orchestration/SKILL.md +16 -13
  13. package/assets/skills/hardening-gate/SKILL.md +3 -0
  14. package/assets/skills/integrated-verification/SKILL.md +2 -0
  15. package/assets/skills/planning-guidance/SKILL.md +1 -0
  16. package/assets/skills/submission-packaging/SKILL.md +6 -4
  17. package/assets/skills/verification-gates/SKILL.md +7 -2
  18. package/assets/slopmachine/test-coverage-prompt.md +561 -0
  19. package/assets/slopmachine/utils/claude_create_session.mjs +2 -2
  20. package/assets/slopmachine/utils/claude_live_common.mjs +8 -3
  21. package/assets/slopmachine/utils/claude_live_launch.mjs +9 -3
  22. package/assets/slopmachine/utils/claude_live_stop.mjs +1 -0
  23. package/assets/slopmachine/utils/claude_live_turn.mjs +37 -10
  24. package/assets/slopmachine/utils/claude_resume_session.mjs +2 -2
  25. package/assets/slopmachine/utils/claude_worker_common.mjs +140 -3
  26. package/assets/slopmachine/utils/package_claude_session.mjs +35 -8
  27. package/package.json +1 -1
  28. package/src/constants.js +2 -2
  29. package/src/init.js +7 -1
  30. package/src/install.js +94 -21
package/src/install.js CHANGED
@@ -11,7 +11,6 @@ import {
11
11
  OPCODE_VERSION,
12
12
  PACKAGE_ROOT,
13
13
  REQUIRED_SKILL_DIRS,
14
- REQUIRED_SLOPMACHINE_ROOT_FILES,
15
14
  REQUIRED_SLOPMACHINE_FILES,
16
15
  } from './constants.js'
17
16
  import {
@@ -63,6 +62,41 @@ function getUnixBeadsBinDirs() {
63
62
  ]
64
63
  }
65
64
 
65
+ function getUnixCommonBinDirs() {
66
+ const home = getHomeDir()
67
+ return [
68
+ path.join(home, '.local', 'bin'),
69
+ path.join(home, '.cargo', 'bin'),
70
+ '/opt/homebrew/bin',
71
+ '/usr/local/bin',
72
+ ]
73
+ }
74
+
75
+ function getWindowsCommonBinDirs() {
76
+ if (process.platform !== 'win32') {
77
+ return []
78
+ }
79
+
80
+ const home = getHomeDir()
81
+ return [
82
+ process.env.LOCALAPPDATA ? path.join(process.env.LOCALAPPDATA, 'Programs') : null,
83
+ path.join(home, '.local', 'bin'),
84
+ path.join(home, '.cargo', 'bin'),
85
+ ].filter(Boolean)
86
+ }
87
+
88
+ function getCommonCommandCandidates(command) {
89
+ if (process.platform === 'win32') {
90
+ return getWindowsCommonBinDirs().flatMap((dir) => [
91
+ path.join(dir, `${command}.exe`),
92
+ path.join(dir, `${command}.cmd`),
93
+ path.join(dir, command),
94
+ ])
95
+ }
96
+
97
+ return getUnixCommonBinDirs().map((dir) => path.join(dir, command))
98
+ }
99
+
66
100
  function getWindowsBeadsBinDirs() {
67
101
  if (process.platform !== 'win32') {
68
102
  return []
@@ -309,14 +343,57 @@ async function installBeadsOnUnix() {
309
343
  return result
310
344
  }
311
345
 
346
+ function getVersionArgs(command) {
347
+ if (command === 'tmux') {
348
+ return ['-V']
349
+ }
350
+
351
+ if (command === 'zip') {
352
+ return ['-v']
353
+ }
354
+
355
+ return ['--version']
356
+ }
357
+
312
358
  async function getCommandVersion(command, args = ['--version']) {
313
- const exists = await commandExists(command)
314
- if (!exists) return null
315
- const result = await runCommand(command, args)
359
+ const resolved = await resolveCommand(command, {
360
+ additionalCandidates: getCommonCommandCandidates(command),
361
+ preferCandidates: true,
362
+ })
363
+ if (!resolved) return null
364
+ const versionArgs = args.length === 1 && args[0] === '--version' ? getVersionArgs(command) : args
365
+ const result = await runCommand(resolved, versionArgs)
316
366
  if (result.code !== 0) return null
317
367
  return (result.stdout || result.stderr).trim()
318
368
  }
319
369
 
370
+ function extractSemver(value) {
371
+ const match = String(value || '').match(/\d+\.\d+\.\d+/)
372
+ return match ? match[0] : null
373
+ }
374
+
375
+ function compareSemver(left, right) {
376
+ const leftParts = left.split('.').map((part) => Number.parseInt(part, 10))
377
+ const rightParts = right.split('.').map((part) => Number.parseInt(part, 10))
378
+ const length = Math.max(leftParts.length, rightParts.length)
379
+ for (let index = 0; index < length; index += 1) {
380
+ const a = leftParts[index] || 0
381
+ const b = rightParts[index] || 0
382
+ if (a > b) return 1
383
+ if (a < b) return -1
384
+ }
385
+ return 0
386
+ }
387
+
388
+ function isVersionAtLeast(currentVersion, minimumVersion) {
389
+ const current = extractSemver(currentVersion)
390
+ const minimum = extractSemver(minimumVersion)
391
+ if (!current || !minimum) {
392
+ return false
393
+ }
394
+ return compareSemver(current, minimum) >= 0
395
+ }
396
+
320
397
  async function getPythonVersion() {
321
398
  const python3Version = await getCommandVersion('python3')
322
399
  if (python3Version) {
@@ -430,19 +507,27 @@ async function tryInstallCoreDependency(name) {
430
507
  async function ensureLatestOpencode(requiredVersion) {
431
508
  const npmVersion = await getGlobalNpmPackageVersion('opencode-ai')
432
509
  const commandPath = await resolveCommand('opencode')
510
+ const commandVersion = await getCommandVersion('opencode')
433
511
 
434
512
  if (npmVersion) {
435
513
  log(`opencode detected via global npm package: opencode-ai@${npmVersion}`)
436
- if (requiredVersion && !npmVersion.includes(requiredVersion)) {
437
- warn(`opencode version differs from tested reference ${requiredVersion}`)
514
+ if (!requiredVersion || isVersionAtLeast(npmVersion, requiredVersion)) {
515
+ log(`Using existing opencode-ai@${npmVersion}`)
516
+ return
438
517
  }
439
- log('Refreshing opencode-ai to latest via npm')
518
+ warn(`opencode version ${npmVersion} is below minimum supported version ${requiredVersion}`)
519
+ log('Updating opencode-ai via npm to reach the minimum supported version')
440
520
  } else if (commandPath) {
441
521
  log(`opencode command detected at ${commandPath}`)
442
- log('Installing opencode-ai@latest globally via npm so theslopmachine can manage the current opencode install')
522
+ if (!requiredVersion || (commandVersion && isVersionAtLeast(commandVersion, requiredVersion))) {
523
+ log(`Using existing opencode command${commandVersion ? `: ${commandVersion}` : ''}`)
524
+ return
525
+ }
526
+ warn(`opencode command version${commandVersion ? ` ${commandVersion}` : ''} is below minimum supported version ${requiredVersion}`)
527
+ log('Installing opencode-ai globally via npm so theslopmachine can manage a supported opencode install')
443
528
  } else {
444
529
  warn('opencode is not installed or not available in PATH')
445
- log('Installing opencode-ai@latest globally via npm')
530
+ log('Installing opencode-ai via npm')
446
531
  }
447
532
 
448
533
  const result = await tryInstallCoreDependency('opencode')
@@ -794,18 +879,6 @@ async function installSlopmachineAssets(paths) {
794
879
  }
795
880
  }
796
881
 
797
- for (const relativePath of REQUIRED_SLOPMACHINE_ROOT_FILES) {
798
- const targetPath = path.join(paths.slopmachineDir, relativePath)
799
- const result = await copyFileReplacing(path.join(PACKAGE_ROOT, relativePath), targetPath)
800
- if (result.replaced) {
801
- log(`Refreshed asset: ${relativePath}`)
802
- summary.refreshed.push(relativePath)
803
- } else {
804
- log(`Installed asset: ${relativePath}`)
805
- summary.installed.push(relativePath)
806
- }
807
- }
808
-
809
882
  return summary
810
883
  }
811
884