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.
- package/assets/agents/developer.md +6 -7
- package/assets/agents/slopmachine-claude.md +66 -9
- package/assets/agents/slopmachine.md +68 -9
- package/assets/claude/agents/developer.md +5 -1
- package/assets/skills/clarification-gate/SKILL.md +56 -20
- package/assets/skills/claude-worker-management/SKILL.md +14 -4
- package/assets/skills/deep-retrospective/SKILL.md +179 -0
- package/assets/skills/deep-retrospective/run.py +446 -0
- package/assets/skills/deep-retrospective/workflow-reference.md +240 -0
- package/assets/skills/developer-session-lifecycle/SKILL.md +18 -4
- package/assets/skills/development-guidance/SKILL.md +52 -31
- package/assets/skills/evaluation-triage/SKILL.md +21 -7
- package/assets/skills/final-evaluation-orchestration/SKILL.md +92 -28
- package/assets/skills/integrated-verification/SKILL.md +38 -42
- package/assets/skills/p8-readiness-reconciliation/SKILL.md +31 -10
- package/assets/skills/planning-gate/SKILL.md +10 -7
- package/assets/skills/planning-guidance/SKILL.md +60 -52
- package/assets/skills/retrospective-analysis/SKILL.md +172 -58
- package/assets/skills/scaffold-guidance/SKILL.md +18 -6
- package/assets/skills/submission-packaging/SKILL.md +11 -3
- package/assets/slopmachine/clarifier-agent-prompt.md +7 -6
- package/assets/slopmachine/exact-readme-template.md +8 -12
- package/assets/slopmachine/owner-verification-checklist.md +1 -1
- package/assets/slopmachine/phase-1-design-prompt.md +5 -10
- package/assets/slopmachine/phase-1-design-template.md +15 -11
- package/assets/slopmachine/phase-2-execution-planning-prompt.md +5 -2
- package/assets/slopmachine/phase-2-plan-template.md +14 -4
- package/assets/slopmachine/scaffold-playbooks/shared-contract.md +2 -1
- package/assets/slopmachine/templates/AGENTS.md +3 -1
- package/assets/slopmachine/templates/CLAUDE.md +3 -1
- package/assets/slopmachine/test-coverage-prompt.md +8 -1
- package/assets/slopmachine/utils/README.md +1 -5
- package/assets/slopmachine/utils/claude_live_common.mjs +2 -5
- package/assets/slopmachine/utils/prepare_evaluation_send_packet.mjs +3 -3
- package/package.json +1 -1
- package/src/constants.js +0 -9
- package/src/init.js +17 -24
- package/src/install.js +30 -28
- 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
|
-
|
|
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
|
-
-
|
|
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
|
-
-
|
|
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
|
|
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
|
|
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
|
|
54
|
-
|
|
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 &&
|
|
58
|
-
fail('--report-path must
|
|
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', `
|
|
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
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
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
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 (
|
|
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 {
|
|
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
|
-
}
|