theslopmachine 1.0.2 → 1.0.3

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 (39) hide show
  1. package/assets/agents/developer.md +38 -32
  2. package/assets/agents/slopmachine-claude.md +36 -25
  3. package/assets/agents/slopmachine.md +61 -45
  4. package/assets/claude/agents/developer.md +27 -10
  5. package/assets/skills/claude-worker-management/SKILL.md +4 -4
  6. package/assets/skills/developer-session-lifecycle/SKILL.md +13 -3
  7. package/assets/skills/development-guidance/SKILL.md +24 -5
  8. package/assets/skills/evaluation-triage/SKILL.md +4 -4
  9. package/assets/skills/final-evaluation-orchestration/SKILL.md +29 -3
  10. package/assets/skills/integrated-verification/SKILL.md +24 -23
  11. package/assets/skills/p8-readiness-reconciliation/SKILL.md +98 -0
  12. package/assets/skills/planning-gate/SKILL.md +2 -2
  13. package/assets/skills/planning-guidance/SKILL.md +7 -4
  14. package/assets/skills/scaffold-guidance/SKILL.md +2 -0
  15. package/assets/skills/submission-packaging/SKILL.md +30 -3
  16. package/assets/skills/verification-gates/SKILL.md +11 -7
  17. package/assets/slopmachine/clarification-faithfulness-review-prompt.md +69 -45
  18. package/assets/slopmachine/clarifier-agent-prompt.md +46 -40
  19. package/assets/slopmachine/exact-readme-template.md +38 -11
  20. package/assets/slopmachine/owner-verification-checklist.md +2 -2
  21. package/assets/slopmachine/phase-1-design-prompt.md +94 -17
  22. package/assets/slopmachine/phase-1-design-template.md +124 -21
  23. package/assets/slopmachine/phase-2-execution-planning-prompt.md +155 -87
  24. package/assets/slopmachine/phase-2-plan-template.md +169 -81
  25. package/assets/slopmachine/scaffold-playbooks/selection-matrix.md +8 -1
  26. package/assets/slopmachine/scaffold-playbooks/tech-frontend-vue.md +2 -0
  27. package/assets/slopmachine/scaffold-playbooks/type-web-spa.md +1 -0
  28. package/assets/slopmachine/templates/AGENTS.md +18 -17
  29. package/assets/slopmachine/templates/CLAUDE.md +18 -17
  30. package/assets/slopmachine/templates/plan.md +115 -36
  31. package/package.json +9 -2
  32. package/src/constants.js +1 -0
  33. package/src/init.js +8 -0
  34. package/src/install.js +130 -0
  35. package/assets/slopmachine/utils/__pycache__/claude_live_hook.cpython-311.pyc +0 -0
  36. package/assets/slopmachine/utils/__pycache__/cleanup_delivery_artifacts.cpython-311.pyc +0 -0
  37. package/assets/slopmachine/utils/__pycache__/convert_ai_session.cpython-311.pyc +0 -0
  38. package/assets/slopmachine/utils/__pycache__/normalize_claude_session.cpython-311.pyc +0 -0
  39. package/assets/slopmachine/utils/__pycache__/strip_session_parent.cpython-311.pyc +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "theslopmachine",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "SlopMachine installer and project bootstrap CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -17,7 +17,14 @@
17
17
  "files": [
18
18
  "bin",
19
19
  "src",
20
- "assets",
20
+ "assets/agents",
21
+ "assets/claude",
22
+ "assets/skills",
23
+ "assets/slopmachine/**/*.md",
24
+ "assets/slopmachine/**/*.js",
25
+ "assets/slopmachine/**/*.mjs",
26
+ "assets/slopmachine/**/*.py",
27
+ "assets/slopmachine/**/*.sh",
21
28
  "README.md",
22
29
  "RELEASE.md",
23
30
  "MANUAL.md"
package/src/constants.js CHANGED
@@ -42,6 +42,7 @@ export const REQUIRED_SLOPMACHINE_FILES = [
42
42
  "frontend-evaluation-prompt.md",
43
43
  "test-coverage-prompt.md",
44
44
  "clarifier-agent-prompt.md",
45
+ "clarification-faithfulness-review-prompt.md",
45
46
  "phase-1-design-prompt.md",
46
47
  "phase-1-design-template.md",
47
48
  "phase-2-execution-planning-prompt.md",
package/src/init.js CHANGED
@@ -134,6 +134,12 @@ const PHASE_LABELS = {
134
134
  P10: 'P10 Retrospective',
135
135
  }
136
136
 
137
+ function assertSupportedPlatform() {
138
+ if (process.platform === 'win32') {
139
+ throw new Error('Native Windows init is not supported. Run theslopmachine from WSL, Linux, or macOS so tmux, Claude live lanes, RTK hooks, and Unix workflow tooling work reliably.')
140
+ }
141
+ }
142
+
137
143
  function getUnixBrCommandCandidates(paths) {
138
144
  return [
139
145
  path.join(paths.home, '.local', 'bin', 'br'),
@@ -688,6 +694,8 @@ async function maybeOpenOpencode(targetPath, openAfterInit) {
688
694
  }
689
695
 
690
696
  export async function runInit(args = []) {
697
+ assertSupportedPlatform()
698
+
691
699
  const paths = buildPaths()
692
700
  const { openAfterInit, targetInput, adoptExisting, continueFromExisting, requestedStartPhase: rawRequestedStartPhase } = parseInitArgs(args)
693
701
  const requestedStartPhase = normalizeRequestedStartPhase(rawRequestedStartPhase)
package/src/install.js CHANGED
@@ -44,6 +44,12 @@ function assetsRoot() {
44
44
  return path.join(PACKAGE_ROOT, 'assets')
45
45
  }
46
46
 
47
+ function assertSupportedPlatform() {
48
+ if (process.platform === 'win32') {
49
+ throw new Error('Native Windows setup is not supported. Run theslopmachine from WSL, Linux, or macOS so tmux, Claude live lanes, RTK hooks, and Unix workflow tooling work reliably.')
50
+ }
51
+ }
52
+
47
53
  async function listSkillDirs(root) {
48
54
  const entries = await fs.readdir(root, { withFileTypes: true })
49
55
  return entries
@@ -147,6 +153,10 @@ function getCommonCommandCandidates(command) {
147
153
  return getUnixCommonBinDirs().map((dir) => path.join(dir, command))
148
154
  }
149
155
 
156
+ function getRtkCommandCandidates() {
157
+ return getCommonCommandCandidates('rtk')
158
+ }
159
+
150
160
  function getWindowsBeadsBinDirs() {
151
161
  if (process.platform !== 'win32') {
152
162
  return []
@@ -277,6 +287,34 @@ async function ensureUnixBeadsPath() {
277
287
  }
278
288
  }
279
289
 
290
+ async function ensureUnixLocalBinPath() {
291
+ if (process.platform === 'win32') {
292
+ return
293
+ }
294
+
295
+ const localBin = path.join(getHomeDir(), '.local', 'bin')
296
+ prependToProcessPath(localBin)
297
+
298
+ const shellProfile = process.env.SHELL && path.basename(process.env.SHELL) === 'bash'
299
+ ? path.join(getHomeDir(), '.bashrc')
300
+ : path.join(getHomeDir(), '.zshrc')
301
+ const exportLine = 'export PATH="$HOME/.local/bin:$PATH"'
302
+
303
+ try {
304
+ const existing = await fs.readFile(shellProfile, 'utf8').catch((error) => {
305
+ if (error && error.code === 'ENOENT') return ''
306
+ throw error
307
+ })
308
+ if (!existing.includes(exportLine)) {
309
+ const prefix = existing.endsWith('\n') || existing.length === 0 ? '' : '\n'
310
+ await fs.appendFile(shellProfile, `${prefix}${exportLine}\n`, 'utf8')
311
+ log(`Added ~/.local/bin to PATH in ${shellProfile}`)
312
+ }
313
+ } catch (error) {
314
+ warn(`Unable to persist ~/.local/bin in shell profile.${error instanceof Error ? ` ${error.message}` : ''}`)
315
+ }
316
+ }
317
+
280
318
  async function installBeadsOnWindows() {
281
319
  const shell = await resolveCommand('pwsh') || await resolveCommand('powershell')
282
320
  if (!shell) {
@@ -393,6 +431,92 @@ async function installBeadsOnUnix() {
393
431
  return result
394
432
  }
395
433
 
434
+ async function resolveRtkCommand() {
435
+ return resolveCommand('rtk', { additionalCandidates: getRtkCommandCandidates(), preferCandidates: true })
436
+ }
437
+
438
+ async function installRtk() {
439
+ const managers = await detectPackageManagers()
440
+
441
+ if (process.platform === 'darwin' && managers.brew) {
442
+ log('Installing rtk via Homebrew')
443
+ return runCommand('brew', ['install', 'rtk'], { stdio: 'inherit' })
444
+ }
445
+
446
+ if (process.platform !== 'win32') {
447
+ const shell = await resolveCommand('sh') || await findBashExecutable()
448
+ if (!shell) {
449
+ return { code: 1, stdout: '', stderr: 'sh or bash is required to run the rtk installer' }
450
+ }
451
+ if (!(await commandExists('curl'))) {
452
+ return { code: 1, stdout: '', stderr: 'curl is required to install rtk automatically' }
453
+ }
454
+
455
+ log('Installing rtk with the upstream install script')
456
+ const result = await runCommand(shell, ['-c', 'curl -fsSL https://raw.githubusercontent.com/rtk-ai/rtk/refs/heads/master/install.sh | sh'], { stdio: 'inherit' })
457
+ await ensureUnixLocalBinPath()
458
+ return result
459
+ }
460
+
461
+ return { code: 1, stdout: '', stderr: 'No automated rtk install path for Windows. Install rtk.exe manually and add it to PATH.' }
462
+ }
463
+
464
+ async function ensureRtkInstalled() {
465
+ const existing = await resolveRtkCommand()
466
+ if (existing) {
467
+ const version = await getCommandVersion('rtk')
468
+ log(`rtk detected via ${existing}${version ? `: ${version}` : ''}`)
469
+ return existing
470
+ }
471
+
472
+ warn('rtk is not installed or not available in PATH')
473
+ const shouldInstall = await promptYesNo('Attempt to install rtk automatically?', true)
474
+ if (!shouldInstall) {
475
+ warn('Skipping rtk installation. Install rtk manually if you want token-compressed shell output.')
476
+ return null
477
+ }
478
+
479
+ const result = await installRtk()
480
+ if (result.code !== 0) {
481
+ warn(`Automatic rtk installation failed.${result.stderr ? ` ${result.stderr}` : ''}`)
482
+ return null
483
+ }
484
+
485
+ const installed = await resolveRtkCommand()
486
+ if (!installed) {
487
+ warn('rtk installation completed, but the `rtk` command is not visible in this shell PATH yet. Open a new terminal or ensure ~/.local/bin is in PATH.')
488
+ return null
489
+ }
490
+
491
+ const version = await getCommandVersion('rtk')
492
+ log(`Installed rtk via ${installed}${version ? `: ${version}` : ''}`)
493
+ return installed
494
+ }
495
+
496
+ async function runRtkInit(command, args, label) {
497
+ const result = await runCommand(command, args, { stdio: 'inherit' })
498
+ if (result.code !== 0) {
499
+ warn(`rtk ${label} initialization failed. Run \`${['rtk', ...args].join(' ')}\` manually after setup.`)
500
+ return false
501
+ }
502
+
503
+ log(`rtk ${label} initialized`)
504
+ return true
505
+ }
506
+
507
+ async function initializeRtk() {
508
+ const command = await ensureRtkInstalled()
509
+ if (!command) {
510
+ return { available: false, claude: false, opencode: false }
511
+ }
512
+
513
+ const nonInteractiveArgs = process.env.SLOPMACHINE_NONINTERACTIVE === '1' ? ['--auto-patch'] : []
514
+ const claude = await runRtkInit(command, ['init', '-g', ...nonInteractiveArgs], 'global Claude/default')
515
+ const opencode = await runRtkInit(command, ['init', '-g', '--opencode', ...nonInteractiveArgs], 'global OpenCode')
516
+
517
+ return { available: true, claude, opencode }
518
+ }
519
+
396
520
  function getVersionArgs(command) {
397
521
  if (command === 'tmux') {
398
522
  return ['-V']
@@ -1132,6 +1256,8 @@ async function maybeCollectUploadToken() {
1132
1256
  }
1133
1257
 
1134
1258
  export async function runInstall() {
1259
+ assertSupportedPlatform()
1260
+
1135
1261
  const paths = buildPaths()
1136
1262
  section('Setup')
1137
1263
  log(`Configuring theslopmachine in ${paths.home}`)
@@ -1151,6 +1277,7 @@ export async function runInstall() {
1151
1277
  }
1152
1278
  await ensureDependency({ name: 'opencode', checkCommand: 'opencode', requiredVersion: OPCODE_VERSION, installable: true })
1153
1279
  await ensureDependency({ name: 'beads_rust (br)', checkCommand: 'br', requiredVersion: null, installable: true })
1280
+ const rtkSummary = await initializeRtk()
1154
1281
  await checkDocker()
1155
1282
  await ensureDependency({ name: 'tmux', checkCommand: 'tmux', requiredVersion: null, installable: process.platform !== 'win32' })
1156
1283
  await checkClaudeCli()
@@ -1195,6 +1322,9 @@ export async function runInstall() {
1195
1322
  console.log(`- Obsolete assets removed: ${obsoleteAssetRemovals.length}`)
1196
1323
  console.log(`- Legacy items removed: ${legacySummary.removed.length}`)
1197
1324
  console.log(`- Legacy items preserved: ${legacySummary.kept.length}`)
1325
+ console.log(`- RTK available: ${rtkSummary.available ? 'yes' : 'no'}`)
1326
+ console.log(`- RTK Claude/default hook initialized: ${rtkSummary.claude ? 'yes' : 'no'}`)
1327
+ console.log(`- RTK OpenCode hook initialized: ${rtkSummary.opencode ? 'yes' : 'no'}`)
1198
1328
  if (archivedObsoleteItems.archiveRoot) {
1199
1329
  console.log(`- Obsolete archive root: ${archivedObsoleteItems.archiveRoot}`)
1200
1330
  }