| 280 | const OPENCODE_RUN = 'opencode run'; |
| 281 | |
| 282 | function firstLoopCommand(pattern: Pattern, tool: Tool): string { |
| 283 | const cmds: Record<Pattern, Record<Tool, string>> = { |
| 284 | 'daily-triage': { |
| 285 | grok: '/loop 1d Run loop-triage. Update STATE.md. No auto-fix in week one.', |
| 286 | claude: '/loop 1d $loop-triage — update STATE.md. Report-only week one.', |
| 287 | codex: 'Automation daily: $loop-triage → update STATE.md. Report-only.', |
| 288 | opencode: `${OPENCODE_RUN} "Run loop-triage. Read STATE.md first. Update High Priority and Watch List. No auto-fix in week one." --agent loop-triage`, |
| 289 | }, |
| 290 | 'pr-babysitter': { |
| 291 | grok: '/loop 10m Run pr-review-triage. Update pr-babysitter-state.md. Worktree + minimal-fix + verifier for allowlisted PRs only. Escalate after 3 attempts.', |
| 292 | claude: '/loop 10m $pr-review-triage — update pr-babysitter-state.md. No auto-merge.', |
| 293 | codex: 'Automation 10m: pr-review-triage → pr-babysitter-state.md. No auto-merge.', |
| 294 | opencode: `${OPENCODE_RUN} "Run PR babysitter triage. Read pr-babysitter-state.md first. Report only — no code edits." --title "PR babysitter"`, |
| 295 | }, |
| 296 | 'ci-sweeper': { |
| 297 | grok: '/loop 15m Run ci-triage on failing CI. Update ci-sweeper-state.md. Fix only regressions in worktree. Max 3 attempts.', |
| 298 | claude: '/loop 15m $ci-triage — update ci-sweeper-state.md. Max 3 fix attempts.', |
| 299 | codex: 'Automation 15m: ci-triage on CI failures. Max 3 attempts.', |
| 300 | opencode: `${OPENCODE_RUN} "Run ci-triage on failing CI. Update ci-sweeper-state.md. Report only in week one."`, |
| 301 | }, |
| 302 | 'dependency-sweeper': { |
| 303 | grok: '/loop 6h Run dependency-triage. Patch-only auto-fix in worktree + verifier. Escalate majors and denylist.', |
| 304 | claude: '/loop 6h $dependency-triage — patch-only with verifier. Escalate risky bumps.', |
| 305 | codex: 'Automation 6h: dependency-triage. Patch-only with verifier.', |
| 306 | opencode: `${OPENCODE_RUN} "Run dependency-triage. Update dependency-sweeper-state.md. Report only — escalate majors."`, |
| 307 | }, |
| 308 | 'post-merge-cleanup': { |
| 309 | grok: '/loop 1d Run post-merge-scan on recent merges. Update post-merge-state.md. Small fixes only in worktree.', |
| 310 | claude: '/loop 1d $post-merge-scan — update post-merge-state.md. Small fixes only.', |
| 311 | codex: 'Automation daily: post-merge-scan → post-merge-state.md.', |
| 312 | opencode: `${OPENCODE_RUN} "Run post-merge-scan. Update post-merge-state.md. Report only in week one."`, |
| 313 | }, |
| 314 | 'changelog-drafter': { |
| 315 | grok: '/loop 1d Run changelog-scan on merges since last tag. Produce categorized draft in RELEASE_NOTES_DRAFT.md using draft-release-notes. Update changelog-drafter-state.md. Human review only.', |
| 316 | claude: '/loop 1d $changelog-scan + draft-release-notes — write RELEASE_NOTES_DRAFT.md and update state. Human approves before publish.', |
| 317 | codex: 'Automation daily: changelog-scan + draft-release-notes → RELEASE_NOTES_DRAFT.md. Human review.', |
| 318 | opencode: `${OPENCODE_RUN} "Run changelog-scan. Draft RELEASE_NOTES_DRAFT.md. Human review only — no publish."`, |
| 319 | }, |
| 320 | 'issue-triage': { |
| 321 | grok: '/loop 2h Run issue-triage. Update issue-triage-state.md. Propose labels and priority only. No auto-apply. Human reviews the needs-human slice.', |
| 322 | claude: '/loop 2h $issue-triage — update issue-triage-state.md. Suggest labels on allowlisted areas only. Report mode week one.', |
| 323 | codex: 'Automation 2h: issue-triage → issue-triage-state.md. Propose only.', |
| 324 | opencode: `${OPENCODE_RUN} "Run issue-triage. Update issue-triage-state.md. Propose labels only — no auto-apply."`, |
| 325 | }, |
| 326 | }; |
| 327 | return cmds[pattern][tool]; |
| 328 | } |
| 329 | |
| 330 | async function resolveAuditCli(): Promise<string | null> { |
| 331 | const monorepo = path.resolve(PACKAGE_ROOT, '../loop-audit/dist/cli.js'); |