theslopmachine 1.0.13 → 1.0.22

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 +6 -7
  2. package/assets/agents/slopmachine-claude.md +66 -9
  3. package/assets/agents/slopmachine.md +68 -9
  4. package/assets/claude/agents/developer.md +5 -1
  5. package/assets/skills/clarification-gate/SKILL.md +56 -20
  6. package/assets/skills/claude-worker-management/SKILL.md +14 -4
  7. package/assets/skills/deep-retrospective/SKILL.md +179 -0
  8. package/assets/skills/deep-retrospective/run.py +446 -0
  9. package/assets/skills/deep-retrospective/workflow-reference.md +240 -0
  10. package/assets/skills/developer-session-lifecycle/SKILL.md +18 -4
  11. package/assets/skills/development-guidance/SKILL.md +52 -31
  12. package/assets/skills/evaluation-triage/SKILL.md +21 -7
  13. package/assets/skills/final-evaluation-orchestration/SKILL.md +92 -28
  14. package/assets/skills/integrated-verification/SKILL.md +38 -42
  15. package/assets/skills/p8-readiness-reconciliation/SKILL.md +31 -10
  16. package/assets/skills/planning-gate/SKILL.md +10 -7
  17. package/assets/skills/planning-guidance/SKILL.md +60 -52
  18. package/assets/skills/retrospective-analysis/SKILL.md +172 -58
  19. package/assets/skills/scaffold-guidance/SKILL.md +18 -6
  20. package/assets/skills/submission-packaging/SKILL.md +11 -3
  21. package/assets/slopmachine/clarifier-agent-prompt.md +7 -6
  22. package/assets/slopmachine/exact-readme-template.md +8 -12
  23. package/assets/slopmachine/owner-verification-checklist.md +1 -1
  24. package/assets/slopmachine/phase-1-design-prompt.md +5 -10
  25. package/assets/slopmachine/phase-1-design-template.md +15 -11
  26. package/assets/slopmachine/phase-2-execution-planning-prompt.md +5 -2
  27. package/assets/slopmachine/phase-2-plan-template.md +14 -4
  28. package/assets/slopmachine/scaffold-playbooks/shared-contract.md +2 -1
  29. package/assets/slopmachine/templates/AGENTS.md +3 -1
  30. package/assets/slopmachine/templates/CLAUDE.md +3 -1
  31. package/assets/slopmachine/test-coverage-prompt.md +8 -1
  32. package/assets/slopmachine/utils/README.md +1 -5
  33. package/assets/slopmachine/utils/claude_live_common.mjs +2 -5
  34. package/assets/slopmachine/utils/prepare_evaluation_send_packet.mjs +3 -3
  35. package/package.json +1 -1
  36. package/src/constants.js +0 -9
  37. package/src/init.js +17 -24
  38. package/src/install.js +30 -28
  39. package/assets/slopmachine/utils/prepare_evaluation_prompt.mjs +0 -81
@@ -29,14 +29,15 @@ This file is internal guidance. Keep it private. Translate each slice into conci
29
29
  - Runtime/Docker expectation:
30
30
  - Local development test harness:
31
31
  - `./repo/run_tests.sh` expectation:
32
+ - Test directory structure: unit tests under `unit_tests/`, API/integration HTTP tests under `API_tests/` (both directories mandatory when the corresponding test surface exists)
32
33
  - README baseline expectation:
33
34
  - Completion evidence:
34
35
 
35
36
  ## 4. Module Map
36
37
 
37
38
  | Module | Requirements / clarifications | Owned behavior | UI surfaces | API/service/job surfaces | Data owned | Security/failure concerns | Proof required |
38
- |---|---|---|---|---|---|---|---|
39
- | | | | | | | | |
39
+ |---|---|---|---|---|---|---|---|---|---|
40
+ | | | | | | | | | | |
40
41
 
41
42
  ## 4.1 No-Orphan Ledger
42
43
 
@@ -46,6 +47,8 @@ Every accepted requirement, clarification, API/interface, data object, actor pat
46
47
  |---|---|---|---|---|---|
47
48
  | | requirement / clarification / API / data / actor path / security / docs / tests | | | | planned |
48
49
 
50
+ The Status column starts as `planned` and must be updated during the development phase to reflect delivery. During the requirements integrity sweep, the owner marks each item as `delivered`, `not-applicable`, or `missing`. No item may remain `planned` after all modules are complete. The status ledger is the single source of truth for whether every requirement survived from design through implementation.
51
+
49
52
  ## 5. Ordered Work Packages
50
53
 
51
54
  | Order | Work package | Depends on | Owned files/surfaces | Required implementation outcome | Tests/proof to land with it | Completion evidence |
@@ -56,6 +59,8 @@ Every accepted requirement, clarification, API/interface, data object, actor pat
56
59
 
57
60
  If not applicable, state `Not Applicable` with the accepted reason.
58
61
 
62
+ Every accepted endpoint and interface must be listed here. Each endpoint must have its own row with the exact METHOD + PATH, its owning module, the work package that implements it, the required tests and proof, and security or validation notes. No endpoint may be omitted.
63
+
59
64
  | Endpoint / interface | Module | Responsible work package | Required tests/proof | Security / validation notes |
60
65
  |---|---|---|---|---|
61
66
  | | | | | |
@@ -130,7 +135,12 @@ Required when backend capabilities exist. If not applicable, state `Not Applicab
130
135
 
131
136
  ## 10. Test Coverage Plan
132
137
 
133
- | Requirement / flow / risk | Unit proof | API/interface proof | Integration proof | E2E/platform proof | Owner |
138
+ - All tests must live under their required directories: unit tests in `unit_tests/`, API/integration HTTP tests in `API_tests/`. Both directories are mandatory when the corresponding test surface exists.
139
+ - Every API endpoint from section 6 must have a row here with its test coverage specified. Every E2E flow from the design must be enumerated with its proof path. Every unit target (service, controller, utility, model) must list the specific test cases it needs. No requirement, endpoint, or E2E flow may be omitted — the coverage plan must be exhaustive.
140
+ - The Key Assertion column must describe what the test asserts at the business-rule level, not just that it calls an endpoint. It must specify the exact expected state transition, status code, response body shape, or side effect. Example: "asserts invoice status changes to `approved` with status 200 and only managers can approve" — not "asserts 200 OK" or "asserts successful response." Avoid permissive assertions that accept multiple valid-ish outcomes without verifying the specific expected result.
141
+ - The Gap column captures what is not yet covered: missing test scenarios, unverified assertion levels, or planned-but-not-yet-implemented proof.
142
+
143
+ | Requirement / flow / risk | Unit proof | API/interface proof | Integration proof | E2E/platform proof | Key Assertion | Gap | Owner |
134
144
  |---|---|---|---|---|---|
135
145
  | | | | | | |
136
146
 
@@ -150,7 +160,7 @@ Required when backend capabilities exist. If not applicable, state `Not Applicab
150
160
  - Unit coverage expectation:
151
161
  - API/interface coverage expectation:
152
162
  - Integration coverage expectation:
153
- - E2E/platform coverage expectation:
163
+ - E2E/platform coverage expectation: every prompt requirement must have an identifiable E2E test that exercises real application behavior and verifies business outcomes. E2E tests must cover every actor path, business rule, authorization rule, error state, and task-closure condition. Tests that only confirm page renders without asserting state changes or data persistence are decorative and insufficient.
154
164
  - Frontend state/component coverage expectation:
155
165
  - Final browser/manual core-flow expectation:
156
166
  - README seeded-value/account verification expectation:
@@ -62,7 +62,6 @@ README must include:
62
62
  - startup instructions with `docker compose up --build`
63
63
  - legacy string `docker-compose up` for backend/fullstack/web projects
64
64
  - verification method and `./run_tests.sh`
65
- - local development test harness command
66
65
  - access method
67
66
  - auth credentials for every role or exact `No authentication required`
68
67
  - mock/stub/local-data/debug/demo disclosure
@@ -73,6 +72,8 @@ README must include:
73
72
 
74
73
  The scaffold must include at least one real narrow test and one honest local verification path. No-source, placeholder, or print-only wrappers are not acceptable.
75
74
 
75
+ The scaffold must create `unit_tests/` for unit tests and `API_tests/` for API/integration HTTP tests when those test surfaces exist. Both directories are mandatory when the corresponding surface is present.
76
+
76
77
  ## Lifecycle floor
77
78
 
78
79
  If the stack includes workers, schedulers, queues, imports, exports, generated secrets, DB init, polling/realtime, or cleanup, scaffold must name the entrypoint and later proof target. Feature work should not have to rediscover where lifecycle code starts.
@@ -39,12 +39,13 @@ This file contains product engineering rules for the current project.
39
39
  - Keep product repo root `./repo/run_tests.sh` meaningful if it exists or if you are explicitly asked to create it; it must not be a no-op, smoke-only placeholder, or wrapper that silently skips major suites.
40
40
  - Do not run Docker or `run_tests.sh` unless asked.
41
41
  - For Android and iOS projects, document native build/run/debug/verification paths; do not force Docker as the primary runtime when platform tooling is inherently native.
42
- - Use `unit_tests/` for unit tests and `API_tests/` for API/integration HTTP tests when those surfaces exist.
42
+ - Place all unit tests under `unit_tests/`. Place all API/integration HTTP tests under `API_tests/`. Both directories are required when a test surface exists.
43
43
  - Every implementation change should include tests for the behavior it owns. Target full meaningful coverage across unit, API/integration, and E2E/platform layers where those surfaces exist.
44
44
  - API/interface endpoints should have real positive and negative tests for exact behavior. User-facing flows should have E2E/platform coverage for the main journeys and important failure/recovery states.
45
45
  - API/interface tests should hit the real route/interface and real business logic without mocking transport/controllers/execution-path services unless there is a documented exception. Frontend unit tests should import or render real components/modules so coverage is directly reviewable.
46
46
  - Prefer the fastest meaningful targeted checks during ordinary implementation.
47
47
  - Never claim a command passed unless you actually ran it and saw the result.
48
+ - For fullstack or web projects, start the application locally and verify it is reachable before reporting work as complete.
48
49
  - If required verification cannot run in the current environment, report it as unverified with the exact risk.
49
50
 
50
51
  ## Frontend And API Discipline
@@ -61,6 +62,7 @@ This file contains product engineering rules for the current project.
61
62
  - For forms, wire UI, route/client, handler/service, persistence/state, response, validation, authorization, and tests together.
62
63
  - For jobs, schedulers, imports/exports, polling, or generated artifacts, wire a real entrypoint and prove the state/artifact effect.
63
64
  - Every changed file should be imported/referenced, integrated, and covered by the strongest relevant checks for its surface.
65
+ - When building a feature that connects to existing components, write integration tests proving the data and behavior flow between them. Do not build features in isolation — verify they work with what is already there.
64
66
  - Before calling a workstream complete, verify owned behavior, tests/proof, docs impact, security/negative paths, and unresolved risks.
65
67
 
66
68
  ## Security And Reliability
@@ -39,12 +39,13 @@ This file contains product engineering rules for the current project.
39
39
  - Keep product repo root `./repo/run_tests.sh` meaningful if it exists or if you are explicitly asked to create it; it must not be a no-op, smoke-only placeholder, or wrapper that silently skips major suites.
40
40
  - Do not run Docker or `run_tests.sh` unless asked.
41
41
  - For Android and iOS projects, document native build/run/debug/verification paths; do not force Docker as the primary runtime when platform tooling is inherently native.
42
- - Use `unit_tests/` for unit tests and `API_tests/` for API/integration HTTP tests when those surfaces exist.
42
+ - Place all unit tests under `unit_tests/`. Place all API/integration HTTP tests under `API_tests/`. Both directories are required when a test surface exists.
43
43
  - Every implementation change should include tests for the behavior it owns. Target full meaningful coverage across unit, API/integration, and E2E/platform layers where those surfaces exist.
44
44
  - API/interface endpoints should have real positive and negative tests for exact behavior. User-facing flows should have E2E/platform coverage for the main journeys and important failure/recovery states.
45
45
  - API/interface tests should hit the real route/interface and real business logic without mocking transport/controllers/execution-path services unless there is a documented exception. Frontend unit tests should import or render real components/modules so coverage is directly reviewable.
46
46
  - Prefer the fastest meaningful targeted checks during ordinary implementation.
47
47
  - Never claim a command passed unless you actually ran it and saw the result.
48
+ - For fullstack or web projects, start the application locally and verify it is reachable before reporting work as complete.
48
49
  - If required verification cannot run in the current environment, report it as unverified with the exact risk.
49
50
 
50
51
  ## Frontend And API Discipline
@@ -61,6 +62,7 @@ This file contains product engineering rules for the current project.
61
62
  - For forms, wire UI, route/client, handler/service, persistence/state, response, validation, authorization, and tests together.
62
63
  - For jobs, schedulers, imports/exports, polling, or generated artifacts, wire a real entrypoint and prove the state/artifact effect.
63
64
  - Every changed file should be imported/referenced, integrated, and covered by the strongest relevant checks for its surface.
65
+ - When building a feature that connects to existing components, write integration tests proving the data and behavior flow between them. Do not build features in isolation — verify they work with what is already there.
64
66
  - Before calling a workstream complete, verify owned behavior, tests/proof, docs impact, security/negative paths, and unresolved risks.
65
67
 
66
68
  ## Security And Reliability
@@ -92,11 +92,18 @@ If unclear → assume **fullstack (strict mode)**
92
92
  * treat different HTTP methods separately
93
93
  * normalize parameterized paths (e.g., `/users/:id`)
94
94
 
95
- * **Endpoint is covered ONLY if:**
95
+ * **Endpoint is "covered" ONLY if:**
96
96
 
97
97
  * a test sends a request to that exact `METHOD + PATH`
98
98
  * request reaches the real route handler
99
99
 
100
+ * **Test directory structure (Mandatory)**:
101
+
102
+ * All unit tests must live under `unit_tests/`
103
+ * All API/integration HTTP tests must live under `API_tests/`
104
+ * Both directories are mandatory when the corresponding test surface exists
105
+ * If unit or API test files exist outside these directories, flag as **STRUCTURE VIOLATION**
106
+
100
107
  * **True No-Mock API Test requires ALL:**
101
108
 
102
109
  * app/server is bootstrapped
@@ -205,13 +205,9 @@ Bash wrapper that invokes `claude_wait_for_rate_limit_reset.mjs` through Node.
205
205
 
206
206
  ## Non-Claude Workflow Helpers
207
207
 
208
- ### `prepare_evaluation_prompt.mjs`
209
-
210
- Builds an owner-side prepared evaluation prompt under workflow-private `.ai` state from a task root. Use `--report-path ./.tmp/<report>.md` to append an owner-required exact report path without editing the canonical prompt text.
211
-
212
208
  ### `prepare_evaluation_send_packet.mjs`
213
209
 
214
- Builds the exact saved evaluator-send packet for Phase 5/Phase 4 workflows from a task root. Use `--report-path ./.tmp/<report>.md` to append an owner-required exact report path without editing the canonical prompt text.
210
+ Builds the exact saved evaluator-send packet for evaluation workflows from a task root. Interpolates `{prompt}` from `./metadata.json`, appends a required report path, and writes the complete packet to workflow-private `.ai/`. Use `--report-path ./.tmp/<report>.md` to append an owner-required exact report path without editing the canonical prompt text. This is the single consolidated script for all evaluation prompt preparation; use it in Phase 4 internal evaluator loops and Phase 5 audit cycles.
215
211
 
216
212
  ### `prepare_strict_audit_workspace.mjs`
217
213
 
@@ -50,11 +50,8 @@ export async function ensureRuntimeDirs(paths) {
50
50
  export async function readJsonIfExists(filePath) {
51
51
  try {
52
52
  return await readJsonFile(filePath)
53
- } catch (error) {
54
- if (error && typeof error === 'object' && error.code === 'ENOENT') {
55
- return null
56
- }
57
- throw error
53
+ } catch {
54
+ return null
58
55
  }
59
56
  }
60
57
 
@@ -54,13 +54,13 @@ try {
54
54
  fail(`Unsupported --mode '${mode}'. Use initial or rerun.`)
55
55
  }
56
56
 
57
- if (reportPath && (!reportPath.startsWith('./.tmp/') || !reportPath.endsWith('.md'))) {
58
- fail('--report-path must be a markdown path under ./.tmp/, for example ./.tmp/audit_report-1.md')
57
+ if (reportPath && !reportPath.endsWith('.md')) {
58
+ fail('--report-path must end with .md')
59
59
  }
60
60
 
61
61
  const workflowRoot = path.dirname(taskRoot)
62
62
  const metadataPath = path.join(taskRoot, 'metadata.json')
63
- const defaultOutputPath = path.join(workflowRoot, '.ai', `evaluation-send-${path.basename(promptFile)}`)
63
+ const defaultOutputPath = path.join(workflowRoot, '.ai', `prepared-${path.basename(promptFile)}`)
64
64
 
65
65
  let promptText = await fs.readFile(promptFile, 'utf8')
66
66
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "theslopmachine",
3
- "version": "1.0.13",
3
+ "version": "1.0.22",
4
4
  "description": "SlopMachine installer and project bootstrap CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/src/constants.js CHANGED
@@ -69,7 +69,6 @@ export const REQUIRED_SLOPMACHINE_FILES = [
69
69
  "utils/convert_ai_session.py",
70
70
  "utils/package_claude_session.mjs",
71
71
  "utils/analyze_claude_project_dir.mjs",
72
- "utils/prepare_evaluation_prompt.mjs",
73
72
  "utils/prepare_evaluation_send_packet.mjs",
74
73
  "utils/prepare_strict_audit_workspace.mjs",
75
74
  "utils/run_with_timeout.mjs",
@@ -110,14 +109,6 @@ export const REQUIRED_SLOPMACHINE_FILES = [
110
109
  ];
111
110
 
112
111
  export const MCP_ENTRIES = {
113
- context7: {
114
- enabled: true,
115
- type: "remote",
116
- url: "https://mcp.context7.com/mcp",
117
- headers: {
118
- CONTEXT7_API_KEY: "",
119
- },
120
- },
121
112
  exa: {
122
113
  enabled: true,
123
114
  type: "remote",
package/src/init.js CHANGED
@@ -628,30 +628,23 @@ async function createRepoStructure(workflowRoot, taskRoot, runtimeAssetRoot, age
628
628
  run_id: randomUUID(),
629
629
  current_phase: initialPhase,
630
630
  awaiting_human: false,
631
- clarification_approved: false,
632
- evaluation_prompt_kind: null,
633
- active_evaluator_session_id: null,
634
- task_root: 'task',
635
- evaluation_reports_root: 'task/.tmp',
636
- evaluation_audit_count: 0,
637
- evaluation_runs: [],
638
- completed_bugfix_session_count: 0,
639
- required_bugfix_session_count: 2,
640
- coverage_readme_audit_completed: false,
641
- coverage_readme_audit_report_path: null,
642
- developer_sessions: [],
643
- developer_rulebook_file: developerRulebookFile,
644
- current_developer_lane: null,
645
- active_developer_session_id: null,
646
- primary_develop_session_id: null,
647
- latest_develop_session_id: null,
648
- next_develop_session_number: 1,
649
- next_bugfix_session_number: 1,
650
- packaging_completed: false,
651
- claude_live_root: '.ai/claude-live',
652
- bootstrap_mode: options.adoptExisting ? 'adopt' : 'new',
653
- requested_start_phase: options.requestedStartPhase,
654
- }, null, 2)}\n`, 'utf8')
631
+ evaluation_prompt_kind: null,
632
+ active_evaluator_session_id: null,
633
+ task_root: 'task',
634
+ evaluation_reports_root: 'task/.tmp',
635
+ developer_sessions: [],
636
+ developer_rulebook_file: developerRulebookFile,
637
+ current_developer_lane: null,
638
+ active_developer_session_id: null,
639
+ primary_develop_session_id: null,
640
+ latest_develop_session_id: null,
641
+ next_develop_session_number: 1,
642
+ next_bugfix_session_number: 1,
643
+ packaging_completed: false,
644
+ claude_live_root: '.ai/claude-live',
645
+ bootstrap_mode: options.adoptExisting ? 'adopt' : 'new',
646
+ requested_start_phase: options.requestedStartPhase,
647
+ }, null, 2)}\n`, 'utf8')
655
648
  }
656
649
 
657
650
  await createInitialPhaseArtifacts(taskRoot, workflowRoot, runtimeAssetRoot, options)
package/src/install.js CHANGED
@@ -209,14 +209,6 @@ const OPENCODE_EVALUATOR_AGENT = {
209
209
  model: 'openai/gpt-5.3-codex',
210
210
  variant: 'medium',
211
211
  thinkingLevel: 'medium',
212
- permission: {
213
- bash: 'deny',
214
- edit: 'deny',
215
- write: 'allow',
216
- read: 'allow',
217
- grep: 'allow',
218
- glob: 'allow',
219
- },
220
212
  }
221
213
 
222
214
  function getHomeDir() {
@@ -1270,6 +1262,33 @@ async function installClaudeRuntimeAssets(paths) {
1270
1262
  return summary
1271
1263
  }
1272
1264
 
1265
+ async function resolveNpmGlobalRoot() {
1266
+ const result = await runCommand('npm', ['root', '-g'])
1267
+ if (result.code !== 0 || !result.stdout.trim()) {
1268
+ return null
1269
+ }
1270
+ return result.stdout.trim()
1271
+ }
1272
+
1273
+ async function installAgentBrowserSkill(paths) {
1274
+ const npmRoot = await resolveNpmGlobalRoot()
1275
+ if (!npmRoot) {
1276
+ warn('Could not resolve npm global root to install agent-browser skill')
1277
+ return
1278
+ }
1279
+ const agentBrowserSkillSrc = path.join(npmRoot, 'agent-browser', 'skills', 'agent-browser')
1280
+ if (!(await pathExists(agentBrowserSkillSrc))) {
1281
+ return
1282
+ }
1283
+ const agentBrowserSkillDest = path.join(paths.globalSkillsDir, 'agent-browser')
1284
+ const result = await copyDirReplacing(agentBrowserSkillSrc, agentBrowserSkillDest)
1285
+ if (result.replaced) {
1286
+ log('Refreshed agent-browser skill')
1287
+ } else {
1288
+ log('Installed agent-browser skill')
1289
+ }
1290
+ }
1291
+
1273
1292
  async function installSkills(paths) {
1274
1293
  const sourceSkills = path.join(assetsRoot(), 'skills')
1275
1294
  await ensureDir(paths.globalSkillsDir)
@@ -1333,15 +1352,6 @@ async function mergeOpencodeConfig(paths, options) {
1333
1352
  delete mcp['chrome-devtools']
1334
1353
  delete mcp.shadcn
1335
1354
 
1336
- if (!mcp.context7) {
1337
- mcp.context7 = {
1338
- ...MCP_ENTRIES.context7,
1339
- headers: {
1340
- CONTEXT7_API_KEY: options.context7ApiKey,
1341
- },
1342
- }
1343
- }
1344
-
1345
1355
  if (!mcp.exa) {
1346
1356
  mcp.exa = {
1347
1357
  ...MCP_ENTRIES.exa,
@@ -1395,34 +1405,25 @@ async function maybeInstallPluginBinary(existingConfig) {
1395
1405
  }
1396
1406
 
1397
1407
  async function collectApiKeys(existingConfig) {
1398
- const forcedContext7 = process.env.SLOPMACHINE_CONTEXT7_API_KEY
1399
1408
  const forcedExa = process.env.SLOPMACHINE_EXA_API_KEY
1400
1409
  const nonInteractive = process.env.SLOPMACHINE_NONINTERACTIVE === '1'
1401
1410
  const existingMcp = typeof existingConfig?.mcp === 'object' && existingConfig.mcp !== null ? existingConfig.mcp : {}
1402
- const needsContext7 = !existingMcp.context7
1403
1411
  const needsExa = !existingMcp.exa
1404
1412
 
1405
- if ((!needsContext7 && !needsExa) || forcedContext7 !== undefined || forcedExa !== undefined || nonInteractive) {
1413
+ if (!needsExa || forcedExa !== undefined || nonInteractive) {
1406
1414
  return {
1407
- context7ApiKey: needsContext7 ? (forcedContext7 || '') : '',
1408
1415
  exaApiKey: needsExa ? (forcedExa || '') : '',
1409
1416
  }
1410
1417
  }
1411
1418
 
1412
- let context7ApiKey = ''
1413
1419
  let exaApiKey = ''
1414
1420
 
1415
- if (needsContext7) {
1416
- console.log('Context7 API key: https://context7.com')
1417
- context7ApiKey = await promptSecret('Paste Context7 API key or leave blank to skip')
1418
- }
1419
-
1420
1421
  if (needsExa) {
1421
1422
  console.log('Exa API key: https://exa.ai')
1422
1423
  exaApiKey = await promptSecret('Paste Exa API key or leave blank to skip')
1423
1424
  }
1424
1425
 
1425
- return { context7ApiKey, exaApiKey }
1426
+ return { exaApiKey }
1426
1427
  }
1427
1428
 
1428
1429
  async function maybeCollectUploadToken() {
@@ -1465,6 +1466,7 @@ export async function runInstall() {
1465
1466
  }
1466
1467
  await ensureDependency({ name: 'opencode', checkCommand: 'opencode', requiredVersion: OPCODE_VERSION, installable: true })
1467
1468
  await ensureDependency({ name: 'agent-browser', checkCommand: 'agent-browser', requiredVersion: null, installable: true })
1469
+ await installAgentBrowserSkill(paths)
1468
1470
  await ensureDependency({ name: 'beads_rust (br)', checkCommand: 'br', requiredVersion: null, installable: true })
1469
1471
  const rtkSummary = await initializeRtk()
1470
1472
  await checkDocker()
@@ -1,81 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import fs from 'node:fs/promises'
4
- import path from 'node:path'
5
-
6
- import { parseArgs, printUsageAndExit, readJsonFile, writeFileIfNeeded } from './claude_worker_common.mjs'
7
-
8
- const argv = parseArgs(process.argv.slice(2))
9
-
10
- if (argv.help === '1') {
11
- printUsageAndExit(`Usage:
12
- node ~/slopmachine/utils/prepare_evaluation_prompt.mjs --task-root <task-root> --prompt-file <template-file> [--mode <initial|rerun>] [--report-path <./.tmp/report.md>] [--output-file <prepared-file>]
13
- `)
14
- }
15
-
16
- const SAME_SESSION_RERUN_FOOTER = 'Check the entire current project again against the full prompt above and regenerate the complete report from scratch. Save the report to the same required path. Make the report read as a fresh standalone audit of the current repo state and do not mention or imply any previous run, rerun, regeneration, prior inspection, earlier fixes, or earlier remaining items.\n'
17
-
18
- function fail(message) {
19
- process.stderr.write(`${message}\n`)
20
- process.exit(1)
21
- }
22
-
23
- try {
24
- const taskRoot = argv['task-root'] ? path.resolve(argv['task-root']) : null
25
- const promptFile = argv['prompt-file'] ? path.resolve(argv['prompt-file']) : null
26
- const outputFile = argv['output-file'] ? path.resolve(argv['output-file']) : null
27
- const reportPath = argv['report-path'] ? String(argv['report-path']).trim() : ''
28
- const mode = argv.mode ? String(argv.mode).trim().toLowerCase() : 'initial'
29
-
30
- if (!taskRoot) {
31
- fail('Missing --task-root')
32
- }
33
-
34
- if (!promptFile) {
35
- fail('Missing --prompt-file')
36
- }
37
-
38
- if (mode !== 'initial' && mode !== 'rerun') {
39
- fail(`Unsupported --mode '${mode}'. Use initial or rerun.`)
40
- }
41
-
42
- if (reportPath && (!reportPath.startsWith('./.tmp/') || !reportPath.endsWith('.md'))) {
43
- fail('--report-path must be a markdown path under ./.tmp/, for example ./.tmp/audit_report-1.md')
44
- }
45
-
46
- const workflowRoot = path.dirname(taskRoot)
47
- const metadataPath = path.join(taskRoot, 'metadata.json')
48
- const defaultOutputPath = path.join(workflowRoot, '.ai', `prepared-${path.basename(promptFile)}`)
49
-
50
- let promptText = await fs.readFile(promptFile, 'utf8')
51
-
52
- if (promptText.includes('{prompt}')) {
53
- const metadata = await readJsonFile(metadataPath)
54
- const projectPrompt = typeof metadata?.prompt === 'string' ? metadata.prompt : ''
55
- if (!projectPrompt.trim()) {
56
- fail(`Missing non-empty metadata.json prompt at ${metadataPath} for a prompt template that requires {prompt}.`)
57
- }
58
- promptText = promptText.replaceAll('{prompt}', projectPrompt)
59
- }
60
-
61
- if (reportPath) {
62
- promptText = promptText.endsWith('\n')
63
- ? `${promptText}\nOwner-required report path: write/save the final report exactly to \`${reportPath}\`.\n`
64
- : `${promptText}\n\nOwner-required report path: write/save the final report exactly to \`${reportPath}\`.\n`
65
- }
66
-
67
- const unresolvedPlaceholders = [...promptText.matchAll(/\{[a-z_]+\}/g)].map((match) => match[0])
68
- if (unresolvedPlaceholders.length > 0) {
69
- fail(`Unsupported unresolved prompt placeholders remain: ${[...new Set(unresolvedPlaceholders)].join(', ')}`)
70
- }
71
-
72
- if (mode === 'rerun') {
73
- promptText = promptText.endsWith('\n') ? `${promptText}\n${SAME_SESSION_RERUN_FOOTER}` : `${promptText}\n\n${SAME_SESSION_RERUN_FOOTER}`
74
- }
75
-
76
- const resolvedOutputPath = outputFile || defaultOutputPath
77
- await writeFileIfNeeded(resolvedOutputPath, promptText)
78
- process.stdout.write(`${resolvedOutputPath}\n`)
79
- } catch (error) {
80
- fail(error instanceof Error ? error.message : String(error))
81
- }