@glrs-dev/cli 1.1.0 → 2.0.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.
Files changed (44) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/vendor/harness-opencode/dist/agents/prompts/pilot-assessor.md +77 -0
  3. package/dist/vendor/harness-opencode/dist/agents/prompts/pilot-builder.md +24 -116
  4. package/dist/vendor/harness-opencode/dist/agents/prompts/pilot-planner.md +38 -160
  5. package/dist/vendor/harness-opencode/dist/agents/prompts/pilot-scoper.md +58 -0
  6. package/dist/vendor/harness-opencode/dist/{chunk-BWERBERN.js → chunk-6CZPRUMJ.js} +12 -62
  7. package/dist/vendor/harness-opencode/dist/chunk-DZG4D3OH.js +54 -0
  8. package/dist/vendor/harness-opencode/dist/chunk-OYRKOEXK.js +88 -0
  9. package/dist/vendor/harness-opencode/dist/cli.js +1619 -3930
  10. package/dist/vendor/harness-opencode/dist/index.js +831 -166
  11. package/dist/vendor/harness-opencode/dist/{install-5JKWK6Z4.js → install-6775ZBDG.js} +1 -1
  12. package/dist/vendor/harness-opencode/dist/paths-WZ23ZQOV.js +18 -0
  13. package/dist/vendor/harness-opencode/dist/skills/code-quality/SKILL.md +45 -0
  14. package/dist/vendor/harness-opencode/dist/skills/code-quality/rules/building.md +125 -0
  15. package/dist/vendor/harness-opencode/dist/skills/code-quality/rules/gap-analysis.md +92 -0
  16. package/dist/vendor/harness-opencode/dist/skills/code-quality/rules/planning.md +96 -0
  17. package/dist/vendor/harness-opencode/dist/skills/code-quality/rules/review.md +104 -0
  18. package/dist/vendor/harness-opencode/package.json +1 -1
  19. package/package.json +1 -1
  20. package/dist/vendor/harness-opencode/dist/agents/prompts/pilot-builder.open.md +0 -129
  21. package/dist/vendor/harness-opencode/dist/chunk-57EOY72Y.js +0 -174
  22. package/dist/vendor/harness-opencode/dist/chunk-5TAMY7P6.js +0 -67
  23. package/dist/vendor/harness-opencode/dist/chunk-BKTFWXLG.js +0 -204
  24. package/dist/vendor/harness-opencode/dist/chunk-EK7K4NTV.js +0 -747
  25. package/dist/vendor/harness-opencode/dist/chunk-KB7M7JXU.js +0 -145
  26. package/dist/vendor/harness-opencode/dist/chunk-RNRCXQ65.js +0 -56
  27. package/dist/vendor/harness-opencode/dist/paths-LT3QQKCF.js +0 -18
  28. package/dist/vendor/harness-opencode/dist/pilot/mcp/status-server.d.ts +0 -1
  29. package/dist/vendor/harness-opencode/dist/pilot/mcp/status-server.js +0 -228
  30. package/dist/vendor/harness-opencode/dist/pilot-config-7LJZ23YK.js +0 -55
  31. package/dist/vendor/harness-opencode/dist/runs-QWPL3TKV.js +0 -18
  32. package/dist/vendor/harness-opencode/dist/safety-gate-WM3EWOCY.js +0 -10
  33. package/dist/vendor/harness-opencode/dist/setup-hook-FHTXMAQL.js +0 -88
  34. package/dist/vendor/harness-opencode/dist/skills/pilot-planning/SKILL.md +0 -80
  35. package/dist/vendor/harness-opencode/dist/skills/pilot-planning/rules/dag-shape.md +0 -47
  36. package/dist/vendor/harness-opencode/dist/skills/pilot-planning/rules/decomposition.md +0 -63
  37. package/dist/vendor/harness-opencode/dist/skills/pilot-planning/rules/first-principles.md +0 -29
  38. package/dist/vendor/harness-opencode/dist/skills/pilot-planning/rules/milestones.md +0 -57
  39. package/dist/vendor/harness-opencode/dist/skills/pilot-planning/rules/qa-expectations.md +0 -120
  40. package/dist/vendor/harness-opencode/dist/skills/pilot-planning/rules/self-review.md +0 -46
  41. package/dist/vendor/harness-opencode/dist/skills/pilot-planning/rules/task-context.md +0 -47
  42. package/dist/vendor/harness-opencode/dist/skills/pilot-planning/rules/touches-scope.md +0 -81
  43. package/dist/vendor/harness-opencode/dist/skills/pilot-planning/rules/verify-design.md +0 -121
  44. package/dist/vendor/harness-opencode/dist/tasks-KJ3WN2KY.js +0 -32
@@ -1,747 +0,0 @@
1
- // src/agents/shared/index.ts
2
- import { readFileSync } from "fs";
3
- import { fileURLToPath } from "url";
4
- import { dirname, join } from "path";
5
- var HERE = dirname(fileURLToPath(import.meta.url));
6
- function readMd(name) {
7
- const candidates = [
8
- join(HERE, name),
9
- // dev: src/agents/shared/
10
- join(HERE, "agents", "shared", name),
11
- // dist: dist/ → dist/agents/shared/
12
- join(HERE, "..", "..", "..", "src", "agents", "shared", name)
13
- // fallback dev
14
- ];
15
- for (const p of candidates) {
16
- try {
17
- return readFileSync(p, "utf8");
18
- } catch {
19
- }
20
- }
21
- throw new Error(`Could not find shared file: ${name}`);
22
- }
23
- var WORKFLOW_MECHANICS_RULE = readMd("workflow-mechanics.md");
24
-
25
- // src/agents/index.ts
26
- import { readFileSync as readFileSync2 } from "fs";
27
- import { fileURLToPath as fileURLToPath2 } from "url";
28
- import { dirname as dirname2, join as join2 } from "path";
29
- var HERE2 = dirname2(fileURLToPath2(import.meta.url));
30
- function readPrompt(name) {
31
- const candidates = [
32
- join2(HERE2, "prompts", name),
33
- // dev: src/agents/prompts/
34
- join2(HERE2, "agents", "prompts", name),
35
- // dist: dist/ → dist/agents/prompts/
36
- join2(HERE2, "..", "..", "src", "agents", "prompts", name)
37
- // fallback dev
38
- ];
39
- for (const p of candidates) {
40
- try {
41
- return readFileSync2(p, "utf8");
42
- } catch {
43
- }
44
- }
45
- throw new Error(`Could not find prompt file: ${name}`);
46
- }
47
- var primePrompt = readPrompt("prime.md");
48
- var planPrompt = readPrompt("plan.md");
49
- var buildPrompt = readPrompt("build.md");
50
- var buildOpenPrompt = readPrompt("build.open.md");
51
- var qaReviewerPrompt = readPrompt("qa-reviewer.md");
52
- var qaReviewerOpenPrompt = readPrompt("qa-reviewer.open.md");
53
- var qaThoroughPrompt = readPrompt("qa-thorough.md");
54
- var planReviewerPrompt = readPrompt("plan-reviewer.md");
55
- var codeSearcherPrompt = readPrompt("code-searcher.md");
56
- var gapAnalyzerPrompt = readPrompt("gap-analyzer.md");
57
- var architectureAdvisorPrompt = readPrompt("architecture-advisor.md");
58
- var docsMaintainerPrompt = readPrompt("docs-maintainer.md");
59
- var libReaderPrompt = readPrompt("lib-reader.md");
60
- var agentsMdWriterPrompt = readPrompt("agents-md-writer.md");
61
- var pilotBuilderPrompt = readPrompt("pilot-builder.md");
62
- var pilotBuilderOpenPrompt = readPrompt("pilot-builder.open.md");
63
- var pilotPlannerPrompt = readPrompt("pilot-planner.md");
64
- var researchPrompt = readPrompt("research.md");
65
- var researchWebPrompt = readPrompt("research-web.md");
66
- var researchLocalPrompt = readPrompt("research-local.md");
67
- var researchAutoPrompt = readPrompt("research-auto.md");
68
- var EXECUTOR_VARIANT_AGENTS = {
69
- build: { reasoning: buildPrompt, strict: buildOpenPrompt },
70
- "qa-reviewer": { reasoning: qaReviewerPrompt, strict: qaReviewerOpenPrompt },
71
- "pilot-builder": { reasoning: pilotBuilderPrompt, strict: pilotBuilderOpenPrompt }
72
- };
73
- function getStrictPrompt(agentName) {
74
- const variants = EXECUTOR_VARIANT_AGENTS[agentName];
75
- if (!variants) {
76
- throw new Error(`getStrictPrompt: no strict variant registered for agent "${agentName}"`);
77
- }
78
- return variants.strict;
79
- }
80
- function stripFrontmatter(md) {
81
- if (!md.startsWith("---")) return md;
82
- const end = md.indexOf("\n---", 3);
83
- if (end === -1) return md;
84
- return md.slice(end + 4).trimStart();
85
- }
86
- function parseFrontmatter(md) {
87
- if (!md.startsWith("---")) return {};
88
- const end = md.indexOf("\n---", 3);
89
- if (end === -1) return {};
90
- const block = md.slice(4, end);
91
- const result = {};
92
- let currentKey = null;
93
- let currentValue = [];
94
- const flush = () => {
95
- if (currentKey) {
96
- result[currentKey] = currentValue.join(" ").trim();
97
- }
98
- };
99
- for (const line of block.split("\n")) {
100
- if (currentKey && (line.startsWith(" ") || line.startsWith(" "))) {
101
- currentValue.push(line.trim());
102
- continue;
103
- }
104
- const colon = line.indexOf(":");
105
- if (colon === -1) {
106
- flush();
107
- currentKey = null;
108
- currentValue = [];
109
- continue;
110
- }
111
- flush();
112
- currentKey = line.slice(0, colon).trim();
113
- const value = line.slice(colon + 1).trim();
114
- currentValue = value ? [value] : [];
115
- }
116
- flush();
117
- return result;
118
- }
119
- function injectWorkflowMechanics(prompt) {
120
- return prompt.replace("{WORKFLOW_MECHANICS_RULE}", WORKFLOW_MECHANICS_RULE);
121
- }
122
- function agentFromPrompt(raw, overrides = {}) {
123
- const fm = parseFrontmatter(raw);
124
- const body = stripFrontmatter(raw);
125
- const prompt = injectWorkflowMechanics(body);
126
- const base = {
127
- description: fm["description"] ?? "",
128
- mode: fm["mode"] ?? "subagent",
129
- model: fm["model"] ?? void 0,
130
- prompt
131
- };
132
- return { ...base, ...overrides };
133
- }
134
- var CORE_BASH_ALLOW_LIST = {
135
- // File inspection — safe read-only commands the reviewers use heavily.
136
- "ls *": "allow",
137
- "cat *": "allow",
138
- "head *": "allow",
139
- "tail *": "allow",
140
- "wc *": "allow",
141
- "grep *": "allow",
142
- "rg *": "allow",
143
- "find *": "allow",
144
- "file *": "allow",
145
- "stat *": "allow",
146
- "which *": "allow",
147
- "whereis *": "allow",
148
- "basename *": "allow",
149
- "dirname *": "allow",
150
- "realpath *": "allow",
151
- "readlink *": "allow",
152
- "diff *": "allow",
153
- "sort *": "allow",
154
- "uniq *": "allow",
155
- "xxd *": "allow",
156
- "tree *": "allow",
157
- "date *": "allow",
158
- "echo *": "allow",
159
- // Git read-only subcommands (explicit rather than `git *` so we don't
160
- // accidentally whitelist `git push` variants the destructive-deny
161
- // table counteracts via longer-pattern matches — but clarity > trust).
162
- "git status *": "allow",
163
- "git log *": "allow",
164
- "git diff *": "allow",
165
- "git show *": "allow",
166
- "git branch *": "allow",
167
- "git merge-base *": "allow",
168
- "git rev-parse *": "allow",
169
- "git rev-list *": "allow",
170
- "git blame *": "allow",
171
- "git config --get *": "allow",
172
- "git config --get": "allow",
173
- "git remote *": "allow",
174
- "git stash list *": "allow",
175
- "git stash list": "allow",
176
- "git ls-files *": "allow",
177
- "git describe *": "allow",
178
- "git tag *": "allow",
179
- "git fetch *": "allow",
180
- // Package/build tooling — the reviewers run lint/test/typecheck.
181
- "pnpm lint *": "allow",
182
- "pnpm test *": "allow",
183
- "pnpm typecheck *": "allow",
184
- "pnpm build *": "allow",
185
- "pnpm run *": "allow",
186
- "pnpm install *": "allow",
187
- "pnpm --filter *": "allow",
188
- "pnpm -w *": "allow",
189
- "bun run *": "allow",
190
- "bun test *": "allow",
191
- "bun install *": "allow",
192
- "bunx *": "allow",
193
- "npm run *": "allow",
194
- "npm test *": "allow",
195
- "npx *": "allow",
196
- "yarn *": "allow",
197
- "tsc *": "allow",
198
- "eslint *": "allow",
199
- "prettier *": "allow",
200
- "biome *": "allow",
201
- // Our own CLI — the plan agent and qa-reviewer both call plan-check/plan-dir.
202
- "bunx @glrs-dev/harness-plugin-opencode *": "allow",
203
- "glrs-oc *": "allow",
204
- // GitHub CLI — read-only gh calls are fine; destructive `gh pr merge`
205
- // is gated at the PRIME level by human intent (user runs /ship).
206
- "gh pr view *": "allow",
207
- "gh pr list *": "allow",
208
- "gh issue view *": "allow",
209
- "gh issue list *": "allow",
210
- "gh api *": "allow"
211
- };
212
- var CORE_DESTRUCTIVE_BASH_DENIES = {
213
- "rm -rf /*": "deny",
214
- "rm -rf ~*": "deny",
215
- "chmod *": "deny",
216
- "chown *": "deny",
217
- "sudo *": "deny",
218
- "git push --force*": "deny",
219
- "git push -f *": "deny",
220
- "git push * --force*": "deny",
221
- "git push * -f": "deny",
222
- "git push * main*": "deny",
223
- "git push * master*": "deny",
224
- // --force-with-lease is the safe variant — explicit allow rule sorts
225
- // after the broad --force deny so the lease variant survives.
226
- "git push --force-with-lease*": "allow",
227
- "git push * --force-with-lease*": "allow"
228
- };
229
- var PRIME_PERMISSIONS = {
230
- edit: "allow",
231
- bash: {
232
- "*": "allow",
233
- ...CORE_BASH_ALLOW_LIST,
234
- ...CORE_DESTRUCTIVE_BASH_DENIES,
235
- // git clean & git reset --hard are allowed for prime because
236
- // /fresh runs them after its own question-tool confirmation gate;
237
- // a permission-layer prompt on top is redundant noise (see issue #54).
238
- // BUILD keeps the stricter default (deny/ask).
239
- "git clean *": "allow",
240
- "git reset --hard*": "allow"
241
- },
242
- webfetch: "allow",
243
- // Per-tool permissions (index signature on AgentConfig allows these)
244
- ast_grep: "allow",
245
- tsc_check: "allow",
246
- eslint_check: "allow",
247
- todo_scan: "allow",
248
- comment_check: "allow",
249
- question: "allow",
250
- serena: "allow",
251
- memory: "allow",
252
- git: "allow",
253
- playwright: "allow",
254
- linear: "allow"
255
- };
256
- var PLAN_PERMISSIONS = {
257
- edit: "allow",
258
- // Plan agent is read-only aside from writing under the plan dir — but
259
- // it does need to RESOLVE the plan dir via the `plan-dir` CLI
260
- // subcommand (returns an absolute path derived from the worktree's
261
- // repo-folder key; see src/plan-paths.ts and src/cli.ts). The object-
262
- // form denies bash broadly and re-allows only `bunx
263
- // @glrs-dev/harness-plugin-opencode plan-dir[...]`. No other bash invocation
264
- // is permitted, so the read-only-aside-from-plans invariant holds.
265
- bash: {
266
- "*": "deny",
267
- "bunx @glrs-dev/harness-plugin-opencode plan-dir": "allow",
268
- "bunx @glrs-dev/harness-plugin-opencode plan-dir *": "allow",
269
- "glrs-oc plan-dir": "allow",
270
- "glrs-oc plan-dir *": "allow"
271
- },
272
- webfetch: "allow",
273
- ast_grep: "deny",
274
- tsc_check: "deny",
275
- eslint_check: "deny",
276
- todo_scan: "allow",
277
- comment_check: "allow",
278
- question: "allow",
279
- serena: "allow",
280
- memory: "allow",
281
- git: "allow",
282
- playwright: "deny",
283
- linear: "allow"
284
- };
285
- var BUILD_PERMISSIONS = {
286
- edit: "allow",
287
- bash: {
288
- "*": "allow",
289
- ...CORE_BASH_ALLOW_LIST,
290
- ...CORE_DESTRUCTIVE_BASH_DENIES,
291
- // Build is stricter than prime on mutation: no `git clean`
292
- // (build shouldn't wipe worktree mid-execution), and
293
- // `git reset --hard` must prompt explicitly.
294
- "git clean *": "deny",
295
- "git reset --hard*": "ask"
296
- },
297
- webfetch: "allow",
298
- ast_grep: "allow",
299
- tsc_check: "allow",
300
- eslint_check: "allow",
301
- todo_scan: "allow",
302
- comment_check: "allow",
303
- question: "allow",
304
- serena: "allow",
305
- memory: "allow",
306
- git: "allow",
307
- playwright: "allow",
308
- linear: "allow"
309
- };
310
- var QA_REVIEWER_PERMISSIONS = {
311
- edit: "deny",
312
- // Object-form bash: the scalar `"allow"` shape loses to OpenCode's
313
- // upstream subagent-default `{bash, *, ask}` via last-match-wins (see
314
- // the root-cause comment near PRIME_PERMISSIONS). Enumerated
315
- // specific patterns in CORE_BASH_ALLOW_LIST sort AFTER the upstream
316
- // wildcard ask and win for the commands they match. `"*": "allow"`
317
- // is kept as a backstop but may still lose to the upstream rule for
318
- // commands not in the enumerated list; those are the known blind spot.
319
- bash: {
320
- "*": "allow",
321
- ...CORE_BASH_ALLOW_LIST,
322
- ...CORE_DESTRUCTIVE_BASH_DENIES
323
- },
324
- webfetch: "deny",
325
- ast_grep: "allow",
326
- tsc_check: "allow",
327
- eslint_check: "allow",
328
- todo_scan: "allow",
329
- comment_check: "allow",
330
- question: "allow",
331
- serena: "allow",
332
- memory: "deny",
333
- git: "allow",
334
- playwright: "allow",
335
- linear: "deny"
336
- };
337
- var QA_THOROUGH_PERMISSIONS = {
338
- edit: "deny",
339
- // Same object-form as QA_REVIEWER_PERMISSIONS — see the shape rationale
340
- // there. qa-thorough re-runs the full suite unconditionally (per its
341
- // prompt), so it touches the same command surface as qa-reviewer and
342
- // needs the identical bash allow-list.
343
- bash: {
344
- "*": "allow",
345
- ...CORE_BASH_ALLOW_LIST,
346
- ...CORE_DESTRUCTIVE_BASH_DENIES
347
- },
348
- webfetch: "deny",
349
- ast_grep: "allow",
350
- tsc_check: "allow",
351
- eslint_check: "allow",
352
- todo_scan: "allow",
353
- comment_check: "allow",
354
- question: "allow",
355
- serena: "allow",
356
- memory: "deny",
357
- git: "allow",
358
- playwright: "allow",
359
- linear: "deny"
360
- };
361
- var PLAN_REVIEWER_PERMISSIONS = {
362
- edit: "deny",
363
- bash: "deny",
364
- webfetch: "deny",
365
- ast_grep: "allow",
366
- tsc_check: "deny",
367
- eslint_check: "deny",
368
- todo_scan: "allow",
369
- comment_check: "allow",
370
- question: "allow",
371
- serena: "allow",
372
- memory: "deny",
373
- git: "allow",
374
- playwright: "deny",
375
- linear: "deny"
376
- };
377
- var GAP_ANALYZER_PERMISSIONS = {
378
- edit: "deny",
379
- bash: "deny",
380
- webfetch: "deny",
381
- ast_grep: "deny",
382
- tsc_check: "deny",
383
- eslint_check: "deny",
384
- todo_scan: "allow",
385
- comment_check: "allow",
386
- question: "allow",
387
- serena: "allow",
388
- memory: "allow",
389
- git: "deny",
390
- playwright: "deny",
391
- linear: "allow"
392
- };
393
- var CODE_SEARCHER_PERMISSIONS = {
394
- edit: "deny",
395
- bash: "deny",
396
- webfetch: "deny",
397
- ast_grep: "allow",
398
- tsc_check: "deny",
399
- eslint_check: "deny",
400
- todo_scan: "deny",
401
- comment_check: "deny",
402
- question: "allow",
403
- serena: "allow",
404
- memory: "deny",
405
- git: "deny",
406
- playwright: "deny",
407
- linear: "deny"
408
- };
409
- var ARCHITECTURE_ADVISOR_PERMISSIONS = {
410
- edit: "deny",
411
- bash: "deny",
412
- webfetch: "deny",
413
- ast_grep: "allow",
414
- tsc_check: "deny",
415
- eslint_check: "deny",
416
- todo_scan: "allow",
417
- comment_check: "allow",
418
- question: "allow",
419
- serena: "allow",
420
- memory: "allow",
421
- git: "allow",
422
- playwright: "deny",
423
- linear: "allow"
424
- };
425
- var LIB_READER_PERMISSIONS = {
426
- edit: "deny",
427
- bash: "deny",
428
- webfetch: "deny",
429
- ast_grep: "deny",
430
- tsc_check: "deny",
431
- eslint_check: "deny",
432
- todo_scan: "deny",
433
- comment_check: "deny",
434
- question: "allow",
435
- serena: "deny",
436
- memory: "allow",
437
- git: "deny",
438
- playwright: "deny",
439
- linear: "deny"
440
- };
441
- var AGENTS_MD_WRITER_PERMISSIONS = {
442
- edit: "allow",
443
- bash: "ask",
444
- // preserve ask-semantics from frontmatter
445
- webfetch: "deny",
446
- ast_grep: "allow",
447
- tsc_check: "deny",
448
- eslint_check: "deny",
449
- todo_scan: "allow",
450
- comment_check: "allow",
451
- question: "allow",
452
- serena: "allow",
453
- memory: "deny",
454
- git: "allow",
455
- playwright: "deny",
456
- linear: "deny"
457
- };
458
- var PILOT_BUILDER_PERMISSIONS = {
459
- edit: "allow",
460
- bash: {
461
- "*": "allow",
462
- ...CORE_BASH_ALLOW_LIST,
463
- ...CORE_DESTRUCTIVE_BASH_DENIES,
464
- // Pilot-specific destructive denies — the builder NEVER commits,
465
- // pushes, switches branches, or opens PRs. The worker does this
466
- // for the agent.
467
- "git commit*": "deny",
468
- "git push*": "deny",
469
- "git tag*": "deny",
470
- "git checkout *": "deny",
471
- "git switch *": "deny",
472
- "git branch *": "deny",
473
- "git restore --source*": "deny",
474
- "git reset *": "deny",
475
- "gh pr *": "deny",
476
- "gh release *": "deny"
477
- },
478
- webfetch: "allow",
479
- ast_grep: "allow",
480
- tsc_check: "allow",
481
- eslint_check: "allow",
482
- todo_scan: "allow",
483
- comment_check: "allow",
484
- // Builder is unattended — must never call the question tool. (The
485
- // worker enforces this via the prompt + STOP protocol; permission
486
- // denial is a backstop.)
487
- question: "deny",
488
- serena: "allow",
489
- memory: "deny",
490
- // pilot tasks are stateless; no per-session memory.
491
- git: "allow",
492
- // read-only git tools (status, log, diff).
493
- playwright: "deny",
494
- linear: "deny"
495
- };
496
- var PILOT_PLANNER_PERMISSIONS = {
497
- edit: "allow",
498
- bash: {
499
- "*": "deny",
500
- // Read-only inspection — same surface as PLAN_PERMISSIONS, plus a few.
501
- "ls *": "allow",
502
- "cat *": "allow",
503
- "head *": "allow",
504
- "tail *": "allow",
505
- "wc *": "allow",
506
- "grep *": "allow",
507
- "rg *": "allow",
508
- "find *": "allow",
509
- "git status *": "allow",
510
- "git log *": "allow",
511
- "git diff *": "allow",
512
- "git show *": "allow",
513
- "git branch *": "allow",
514
- "git rev-parse *": "allow",
515
- // Pilot CLI: validate, plan-dir for self-check + path resolution.
516
- "bunx @glrs-dev/harness-plugin-opencode pilot validate *": "allow",
517
- "bunx @glrs-dev/harness-plugin-opencode pilot validate": "allow",
518
- "bunx @glrs-dev/harness-plugin-opencode pilot plan-dir": "allow",
519
- "bunx @glrs-dev/harness-plugin-opencode pilot plan-dir *": "allow",
520
- "bunx @glrs-dev/harness-plugin-opencode plan-dir": "allow",
521
- "bunx @glrs-dev/harness-plugin-opencode plan-dir *": "allow",
522
- "glrs-oc pilot validate *": "allow",
523
- "glrs-oc pilot validate": "allow",
524
- "glrs-oc pilot plan-dir": "allow",
525
- "glrs-oc pilot plan-dir *": "allow",
526
- "glrs-oc plan-dir": "allow",
527
- "glrs-oc plan-dir *": "allow"
528
- },
529
- // No webfetch by default — the planner reads tickets via the linear
530
- // MCP. If the user invokes with a GitHub URL, they need the linear
531
- // / webfetch combination explicitly. Mark deny here and the operator
532
- // can override per-session.
533
- webfetch: "deny",
534
- ast_grep: "allow",
535
- tsc_check: "deny",
536
- // no need to typecheck; we're writing YAML.
537
- eslint_check: "deny",
538
- todo_scan: "allow",
539
- comment_check: "allow",
540
- question: "allow",
541
- // the planner CAN ask the human (interactive).
542
- serena: "allow",
543
- memory: "deny",
544
- git: "allow",
545
- // read-only git tools.
546
- playwright: "deny",
547
- linear: "allow"
548
- };
549
- var RESEARCH_PERMISSIONS = {
550
- edit: "allow",
551
- bash: {
552
- "*": "allow",
553
- ...CORE_BASH_ALLOW_LIST,
554
- ...CORE_DESTRUCTIVE_BASH_DENIES
555
- },
556
- webfetch: "allow",
557
- ast_grep: "allow",
558
- tsc_check: "deny",
559
- eslint_check: "deny",
560
- todo_scan: "allow",
561
- comment_check: "allow",
562
- question: "allow",
563
- serena: "allow",
564
- memory: "allow",
565
- git: "allow",
566
- playwright: "deny",
567
- linear: "allow"
568
- };
569
- var AGENT_TIERS = {
570
- prime: "deep",
571
- plan: "deep",
572
- "qa-thorough": "deep",
573
- "architecture-advisor": "deep",
574
- "plan-reviewer": "deep",
575
- "gap-analyzer": "deep",
576
- "pilot-planner": "deep",
577
- research: "deep",
578
- "research-web": "deep",
579
- "research-local": "deep",
580
- "research-auto": "deep",
581
- build: "mid-execute",
582
- "qa-reviewer": "mid-execute",
583
- "pilot-builder": "mid-execute",
584
- "docs-maintainer": "mid",
585
- "lib-reader": "mid",
586
- "agents-md-writer": "mid",
587
- "code-searcher": "fast"
588
- };
589
- function createAgents() {
590
- return {
591
- // Primary agents
592
- prime: agentFromPrompt(primePrompt, {
593
- description: "End-to-end PRIME (Primary Routing and Intelligence Management Entity). Takes a request from intent to ready-to-ship in one session. Default primary agent.",
594
- mode: "primary",
595
- model: "anthropic/claude-opus-4-7",
596
- temperature: 0.2,
597
- permission: PRIME_PERMISSIONS
598
- }),
599
- plan: agentFromPrompt(planPrompt, {
600
- description: "Interactive planner. Orchestrates gap analysis and adversarial review. Produces a written plan in the repo-shared plan directory (resolve via `bunx @glrs-dev/harness-plugin-opencode plan-dir`).",
601
- mode: "all",
602
- model: "anthropic/claude-opus-4-7",
603
- temperature: 0.3,
604
- permission: PLAN_PERMISSIONS
605
- }),
606
- build: agentFromPrompt(buildPrompt, {
607
- description: "Executes a written plan. Runs tests inline, gates completion on QA review.",
608
- mode: "all",
609
- model: "anthropic/claude-sonnet-4-6",
610
- temperature: 0.1,
611
- permission: BUILD_PERMISSIONS
612
- }),
613
- // Subagents — model/mode/description from frontmatter, permissions
614
- // via overrides (see permission blocks above). docs-maintainer has no
615
- // frontmatter permission declaration and keeps that behavior.
616
- "qa-reviewer": agentFromPrompt(qaReviewerPrompt, {
617
- permission: QA_REVIEWER_PERMISSIONS
618
- }),
619
- "qa-thorough": agentFromPrompt(qaThoroughPrompt, {
620
- permission: QA_THOROUGH_PERMISSIONS
621
- }),
622
- "plan-reviewer": agentFromPrompt(planReviewerPrompt, {
623
- permission: PLAN_REVIEWER_PERMISSIONS
624
- }),
625
- "code-searcher": agentFromPrompt(codeSearcherPrompt, {
626
- permission: CODE_SEARCHER_PERMISSIONS
627
- }),
628
- "gap-analyzer": agentFromPrompt(gapAnalyzerPrompt, {
629
- permission: GAP_ANALYZER_PERMISSIONS
630
- }),
631
- "architecture-advisor": agentFromPrompt(architectureAdvisorPrompt, {
632
- permission: ARCHITECTURE_ADVISOR_PERMISSIONS
633
- }),
634
- "docs-maintainer": agentFromPrompt(docsMaintainerPrompt),
635
- "lib-reader": agentFromPrompt(libReaderPrompt, {
636
- permission: LIB_READER_PERMISSIONS
637
- }),
638
- "agents-md-writer": agentFromPrompt(agentsMdWriterPrompt, {
639
- permission: AGENTS_MD_WRITER_PERMISSIONS
640
- }),
641
- // Pilot subsystem agents (Phase F1 + F2). The frontmatter sets
642
- // mode/model/description; temperature is passed via override
643
- // because `agentFromPrompt` doesn't currently parse the
644
- // temperature field (and we don't want to change that helper for
645
- // every agent at once — out of scope for F1/F2).
646
- "pilot-builder": agentFromPrompt(pilotBuilderPrompt, {
647
- mode: "subagent",
648
- model: "anthropic/claude-sonnet-4-6",
649
- temperature: 0.1,
650
- permission: PILOT_BUILDER_PERMISSIONS
651
- }),
652
- "pilot-planner": agentFromPrompt(pilotPlannerPrompt, {
653
- mode: "subagent",
654
- model: "anthropic/claude-opus-4-7",
655
- temperature: 0.3,
656
- permission: PILOT_PLANNER_PERMISSIONS
657
- }),
658
- // Research agent — mode:all for both primary invocation and task-tool dispatch
659
- research: agentFromPrompt(researchPrompt, {
660
- description: "Research orchestrator \u2014 decomposes a research query into parallel workstreams, dispatches research skills (research / research-web / research-local / research-auto) as subagents, reviews findings for gaps, iterates, and synthesizes. Use when the user asks to investigate, explore, deep-dive, or understand a complex topic that needs multiple workstreams.",
661
- mode: "all",
662
- model: "anthropic/claude-opus-4-7",
663
- temperature: 0.3,
664
- permission: RESEARCH_PERMISSIONS
665
- }),
666
- // Research subagents — thin shims that load the bundled skills
667
- "research-web": agentFromPrompt(researchWebPrompt, {
668
- description: "Research orchestrator subagent \u2014 Multi-agent web research orchestrator. Decomposes a research question into parallel agent workstreams, launches them, monitors progress, and synthesizes results. Use when user says 'research this topic', 'I need to understand', 'deep dive into', 'investigate the market for', 'what do we know about'. Provide the research topic and context.",
669
- mode: "all",
670
- model: "anthropic/claude-opus-4-7",
671
- temperature: 0.3,
672
- permission: RESEARCH_PERMISSIONS
673
- }),
674
- "research-local": agentFromPrompt(researchLocalPrompt, {
675
- description: "Research orchestrator subagent \u2014 Deep codebase research using parallel Explore subagents. Decomposes a question about the local codebase into research tasks, launches parallel explorations, reviews for gaps, iterates, and synthesizes findings with specific file paths and line numbers. Use when user says 'how does X work in this codebase', 'where is Y implemented', 'trace the data flow for Z', 'what patterns does this repo use', 'explain the architecture of'. Provide the research topic as arguments.",
676
- mode: "all",
677
- model: "anthropic/claude-opus-4-7",
678
- temperature: 0.3,
679
- permission: RESEARCH_PERMISSIONS
680
- }),
681
- "research-auto": agentFromPrompt(researchAutoPrompt, {
682
- description: "Research orchestrator subagent \u2014 Autonomous experimentation skill. Agent interviews the user, sets up a lab, then explores freely (think, test, reflect) until stopped or a target is hit. Works for any domain where you can measure or evaluate a result. Use when user says 'optimize this', 'experiment with', 'find the best approach', 'iterate on', 'research mode'. Do NOT use for binary validation tests (use /spec-lab instead). Based on ResearcherSkill v1.4.4 by krzysztofdudek.",
683
- mode: "all",
684
- model: "anthropic/claude-opus-4-7",
685
- temperature: 0.3,
686
- permission: RESEARCH_PERMISSIONS
687
- })
688
- };
689
- }
690
-
691
- // src/model-validator.ts
692
- var CATWALK_PROVIDER_PATTERN = /^(?:bedrock|vertex|vertexai)\//;
693
- var LEGACY_PRE_100_PATTERN = /^(bedrock|vertex|vertexai)\/claude-(opus|sonnet|haiku)(-\d+)?$/;
694
- var LEGACY_TO_MODELS_DEV = {
695
- // --- Pre-PR-#100 Bedrock (no subpath) ---
696
- "bedrock/claude-opus": "amazon-bedrock/global.anthropic.claude-opus-4-7",
697
- "bedrock/claude-opus-4": "amazon-bedrock/global.anthropic.claude-opus-4-7",
698
- "bedrock/claude-sonnet": "amazon-bedrock/global.anthropic.claude-sonnet-4-6",
699
- "bedrock/claude-sonnet-4": "amazon-bedrock/global.anthropic.claude-sonnet-4-6",
700
- "bedrock/claude-haiku": "amazon-bedrock/global.anthropic.claude-haiku-4-5-20251001-v1:0",
701
- "bedrock/claude-haiku-4": "amazon-bedrock/global.anthropic.claude-haiku-4-5-20251001-v1:0",
702
- // --- Pre-Models.dev Bedrock (had subpath, but wrong provider prefix) ---
703
- "bedrock/anthropic.claude-opus-4-6": "amazon-bedrock/global.anthropic.claude-opus-4-7",
704
- "bedrock/anthropic.claude-opus-4-7": "amazon-bedrock/global.anthropic.claude-opus-4-7",
705
- "bedrock/anthropic.claude-sonnet-4-6": "amazon-bedrock/global.anthropic.claude-sonnet-4-6",
706
- "bedrock/anthropic.claude-haiku-4-5-20251001-v1:0": "amazon-bedrock/global.anthropic.claude-haiku-4-5-20251001-v1:0",
707
- // --- Pre-PR-#100 Vertex (no @date suffix) ---
708
- "vertex/claude-opus": "google-vertex-anthropic/claude-opus-4-7@default",
709
- "vertex/claude-opus-4": "google-vertex-anthropic/claude-opus-4-7@default",
710
- "vertex/claude-sonnet": "google-vertex-anthropic/claude-sonnet-4-6@default",
711
- "vertex/claude-sonnet-4": "google-vertex-anthropic/claude-sonnet-4-6@default",
712
- "vertex/claude-haiku": "google-vertex-anthropic/claude-haiku-4-5@20251001",
713
- "vertex/claude-haiku-4": "google-vertex-anthropic/claude-haiku-4-5@20251001",
714
- "vertexai/claude-opus": "google-vertex-anthropic/claude-opus-4-7@default",
715
- "vertexai/claude-opus-4": "google-vertex-anthropic/claude-opus-4-7@default",
716
- "vertexai/claude-sonnet": "google-vertex-anthropic/claude-sonnet-4-6@default",
717
- "vertexai/claude-sonnet-4": "google-vertex-anthropic/claude-sonnet-4-6@default",
718
- "vertexai/claude-haiku": "google-vertex-anthropic/claude-haiku-4-5@20251001",
719
- "vertexai/claude-haiku-4": "google-vertex-anthropic/claude-haiku-4-5@20251001",
720
- // --- Pre-Models.dev Vertex (had @date suffix, wrong provider prefix) ---
721
- "vertexai/claude-opus-4-6@20250610": "google-vertex-anthropic/claude-opus-4-6@default",
722
- "vertexai/claude-opus-4-7@20250610": "google-vertex-anthropic/claude-opus-4-7@default",
723
- "vertexai/claude-sonnet-4-6@20250725": "google-vertex-anthropic/claude-sonnet-4-6@default",
724
- "vertexai/claude-haiku-4-5@20251001": "google-vertex-anthropic/claude-haiku-4-5@20251001"
725
- };
726
- function validateModelOverride(id) {
727
- if (typeof id !== "string") return { valid: true };
728
- if (id.length === 0) return { valid: true };
729
- if (CATWALK_PROVIDER_PATTERN.test(id)) {
730
- const suggestion = LEGACY_TO_MODELS_DEV[id] ?? "run `bunx @glrs-dev/harness-plugin-opencode install` to pick a current preset";
731
- const reason = LEGACY_PRE_100_PATTERN.test(id) ? `"${id}" is a pre-PR-#100 model ID format that does not resolve in OpenCode. Bedrock IDs need the \`amazon-bedrock\` provider prefix (not \`bedrock\`); Vertex Claude IDs need the \`google-vertex-anthropic\` provider prefix (not \`vertex\` / \`vertexai\`).` : `"${id}" uses a provider prefix (\`${id.split("/")[0]}\`) that does not exist in OpenCode's runtime. AWS Bedrock's provider ID is \`amazon-bedrock\`; Vertex Claude's is \`google-vertex-anthropic\`.`;
732
- return { valid: false, reason, suggestion };
733
- }
734
- return { valid: true };
735
- }
736
- function formatModelOverrideWarning(id, source, suggestion) {
737
- const suggestionText = suggestion ? ` Suggested replacement: \`${suggestion}\`.` : "";
738
- return `[@glrs-dev/harness-plugin-opencode] Warning: invalid model override "${id}" (from ${source}).${suggestionText} Run \`bunx @glrs-dev/harness-plugin-opencode doctor\` for details.`;
739
- }
740
-
741
- export {
742
- getStrictPrompt,
743
- AGENT_TIERS,
744
- createAgents,
745
- validateModelOverride,
746
- formatModelOverrideWarning
747
- };