compound-workflow 0.1.1

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 (55) hide show
  1. package/.claude-plugin/marketplace.json +11 -0
  2. package/.claude-plugin/plugin.json +12 -0
  3. package/.cursor-plugin/plugin.json +12 -0
  4. package/README.md +155 -0
  5. package/package.json +22 -0
  6. package/scripts/install-cli.mjs +313 -0
  7. package/scripts/sync-into-repo.sh +103 -0
  8. package/src/.agents/agents/research/best-practices-researcher.md +132 -0
  9. package/src/.agents/agents/research/framework-docs-researcher.md +134 -0
  10. package/src/.agents/agents/research/git-history-analyzer.md +62 -0
  11. package/src/.agents/agents/research/learnings-researcher.md +288 -0
  12. package/src/.agents/agents/research/repo-research-analyst.md +146 -0
  13. package/src/.agents/agents/review/agent-native-reviewer.md +299 -0
  14. package/src/.agents/agents/workflow/bug-reproduction-validator.md +87 -0
  15. package/src/.agents/agents/workflow/lint.md +20 -0
  16. package/src/.agents/agents/workflow/spec-flow-analyzer.md +149 -0
  17. package/src/.agents/commands/assess.md +60 -0
  18. package/src/.agents/commands/install.md +53 -0
  19. package/src/.agents/commands/metrics.md +59 -0
  20. package/src/.agents/commands/setup.md +9 -0
  21. package/src/.agents/commands/sync.md +9 -0
  22. package/src/.agents/commands/test-browser.md +393 -0
  23. package/src/.agents/commands/workflow/brainstorm.md +252 -0
  24. package/src/.agents/commands/workflow/compound.md +142 -0
  25. package/src/.agents/commands/workflow/plan.md +737 -0
  26. package/src/.agents/commands/workflow/review-v2.md +148 -0
  27. package/src/.agents/commands/workflow/review.md +110 -0
  28. package/src/.agents/commands/workflow/triage.md +54 -0
  29. package/src/.agents/commands/workflow/work.md +439 -0
  30. package/src/.agents/references/README.md +12 -0
  31. package/src/.agents/references/standards/README.md +9 -0
  32. package/src/.agents/scripts/self-check.mjs +227 -0
  33. package/src/.agents/scripts/sync-opencode.mjs +355 -0
  34. package/src/.agents/skills/agent-browser/SKILL.md +223 -0
  35. package/src/.agents/skills/audit-traceability/SKILL.md +260 -0
  36. package/src/.agents/skills/brainstorming/SKILL.md +250 -0
  37. package/src/.agents/skills/compound-docs/SKILL.md +533 -0
  38. package/src/.agents/skills/compound-docs/assets/critical-pattern-template.md +34 -0
  39. package/src/.agents/skills/compound-docs/assets/resolution-template.md +97 -0
  40. package/src/.agents/skills/compound-docs/references/yaml-schema.md +87 -0
  41. package/src/.agents/skills/compound-docs/schema.project.yaml +18 -0
  42. package/src/.agents/skills/compound-docs/schema.yaml +119 -0
  43. package/src/.agents/skills/data-foundations/SKILL.md +185 -0
  44. package/src/.agents/skills/document-review/SKILL.md +108 -0
  45. package/src/.agents/skills/file-todos/SKILL.md +177 -0
  46. package/src/.agents/skills/file-todos/assets/todo-template.md +106 -0
  47. package/src/.agents/skills/financial-workflow-integrity/SKILL.md +423 -0
  48. package/src/.agents/skills/git-worktree/SKILL.md +268 -0
  49. package/src/.agents/skills/pii-protection-prisma/SKILL.md +629 -0
  50. package/src/.agents/skills/process-metrics/SKILL.md +46 -0
  51. package/src/.agents/skills/process-metrics/assets/daily-template.md +37 -0
  52. package/src/.agents/skills/process-metrics/assets/monthly-template.md +21 -0
  53. package/src/.agents/skills/process-metrics/assets/weekly-template.md +25 -0
  54. package/src/.agents/skills/technical-review/SKILL.md +83 -0
  55. package/src/AGENTS.md +213 -0
@@ -0,0 +1,439 @@
1
+ ---
2
+ name: work
3
+ invocation: workflow:work
4
+ description: Execute a plan file systematically (implementation + verification) without auto-shipping
5
+ argument-hint: "<required: plan file path>"
6
+ ---
7
+
8
+ # /workflow:work
9
+
10
+ Execute a work plan efficiently while maintaining quality and finishing features.
11
+
12
+ ## Introduction
13
+
14
+ This command takes a plan file and executes it systematically. The focus is on completing the work while understanding requirements quickly, following existing patterns, and maintaining quality throughout.
15
+
16
+ Non-goals (unless explicitly requested):
17
+
18
+ - Creating commits
19
+ - Pushing branches
20
+ - Creating pull requests
21
+
22
+ ## Input Document
23
+
24
+ <input_document> #$ARGUMENTS </input_document>
25
+
26
+ The input must be a plan file path.
27
+
28
+ - If it is empty, ask the user for the plan file path.
29
+ - If it does not exist or is not readable, stop and ask for the correct path.
30
+ - Read the plan file completely before starting work.
31
+
32
+ ## Execution Workflow
33
+
34
+ ### Phase 1: Quick Start
35
+
36
+ 1. **Read Plan and Clarify**
37
+
38
+ - Read the work document completely
39
+ - Review any references or links provided in the plan
40
+ - If anything is unclear or ambiguous, ask clarifying questions now
41
+ - Get user approval to proceed
42
+ - **Do not skip this** - better to ask questions now than build the wrong thing
43
+
44
+ 1.25. **Resolve Repo Defaults (ALWAYS FIRST)**
45
+
46
+ Read `AGENTS.md` and look for the "Repo Config Block" YAML.
47
+
48
+ Use it to resolve:
49
+
50
+ - `test_command`
51
+ - `test_fast_command` (optional)
52
+ - `lint_command` (optional)
53
+ - `format_command` (optional)
54
+
55
+ If not present, ask once for the project's test command and suggest adding it to `AGENTS.md`.
56
+
57
+ 1.5. **Determine Testing Mode (Risk-Based)**
58
+
59
+ Infer a testing cadence from the plan's risk.
60
+
61
+ Inputs:
62
+
63
+ - If the plan file has frontmatter `fidelity` and `confidence`, use them.
64
+ - Otherwise default to `fidelity=medium`, `confidence=medium`.
65
+
66
+ Testing modes:
67
+
68
+ - Low risk: fast checks per todo, full suite at end
69
+ - Medium risk (default): fast checks per todo, full suite at milestones + end
70
+ - High risk: fast checks per todo, full suite frequently (every 1-2 todos) + end
71
+
72
+ Command sources:
73
+
74
+ - Prefer `test_command` and optional `test_fast_command` from `AGENTS.md`.
75
+ - If missing, ask once for the repo's test command and suggest adding it to `AGENTS.md`.
76
+
77
+ 2. **Setup Environment**
78
+
79
+ Determine how to isolate the work for this plan.
80
+
81
+ Default: use a worktree (recommended). The user may opt out.
82
+
83
+ 1) Resolve your current branch (this is the default worktree base):
84
+
85
+ - If you are already on a branch that clearly matches this plan, continue.
86
+ - Otherwise, continue anyway — the current active branch remains the reference/base for a new worktree unless the user explicitly requests a different base.
87
+
88
+ 2) Ask the user (opt-out prompt):
89
+
90
+ - "Use a worktree for this work? (default: Yes; recommended for isolation)"
91
+ - Options:
92
+ - Yes (worktree)
93
+ - No (stay in current checkout; create/switch to a feature branch)
94
+
95
+ If Yes: ask for the new branch name (e.g., `feat/<slug>`, `fix/<slug>`).
96
+
97
+ 3) If worktree is chosen, run:
98
+
99
+ ```bash
100
+ skill: git-worktree
101
+ # Provide:
102
+ # - branch-name: <new branch name>
103
+ # - from-branch: <current active branch> (ALWAYS, unless the user overrides)
104
+ ```
105
+
106
+ 3.5) Worktree bootstrap (REQUIRED when worktree created)
107
+
108
+ Immediately after entering the new worktree, run bootstrap per the `git-worktree` skill (AGENTS keys + autodetect). See `.agents/skills/git-worktree/SKILL.md` for the canonical algorithm (copy env/config, install deps, and `worktree_bootstrap_notes`).
109
+
110
+ 3.6) Record worktree path (REQUIRED when worktree created)
111
+
112
+ When a worktree was created, record the worktree path (e.g. `<worktree_dir>/<sanitized-branch-name>`) in a single visible place (e.g. at the top of the plan frontmatter as `worktree_path: .worktrees/feat-xyz` or in the first Phase 2 step). All subsequent steps assume this path as the implementation root.
113
+
114
+ 4) If worktree is not chosen (opt-out):
115
+
116
+ - Create or switch to a feature branch (never work directly on the default branch).
117
+
118
+ 3. **Create Todo List**
119
+
120
+ Run:
121
+
122
+ ```bash
123
+ skill: file-todos
124
+ # Input: plan file path (the input document)
125
+ # Output: todos/*-ready-*.md and/or todos/*-pending-*.md per skill rules
126
+ ```
127
+
128
+ - Break the plan into actionable, persistent todo files under `todos/`
129
+ - Include dependencies between tasks
130
+ - Prioritize based on what needs to be done first
131
+ - Include testing and quality check tasks
132
+ - Keep tasks specific and completable
133
+
134
+ Prerequisites:
135
+
136
+ - Ensure `todos/` exists.
137
+ - Ensure the todo template exists at `.agents/skills/file-todos/assets/todo-template.md`.
138
+
139
+ If `todos/` does not exist, create it and proceed.
140
+
141
+ Plan -> todos mapping (default behavior):
142
+
143
+ - If the plan contains checkboxes (`- [ ]`), create one todo per checkbox (group only when items are tightly coupled).
144
+ - If the plan has no checkboxes, create 3-7 todos based on the plan's major phases/sections.
145
+ - Each todo MUST include a link back to the plan file in `Resources` and reference the specific section(s) it implements.
146
+ - Default todo `status`:
147
+ - `ready` when the plan is approved and confidence is not low
148
+ - `pending` when plan confidence is low or requires explicit triage
149
+ - Default todo `priority`: `p2` unless the plan indicates urgency/risk.
150
+
151
+ After creating todos:
152
+
153
+ - If any todos are `pending`, stop and offer `/workflow:triage` to approve and prioritize before execution.
154
+ - If all todos are `ready`, proceed to Phase 2.
155
+
156
+ ### Phase 2: Execute
157
+
158
+ 1. **Task Execution Loop**
159
+
160
+ **When a worktree was created for this run:** All implementation edits (file reads/writes) and all terminal commands (run tests, install, lint, etc.) MUST be performed with the worktree directory as the working context: use the worktree path for file paths and set terminal cwd to the worktree root. Do not make code changes in the main repo checkout.
161
+
162
+ Todo selection rules (default):
163
+
164
+ - Consider only `todos/*-ready-*.md` items. Do not execute `pending` or `deferred` todos.
165
+ - Skip blocked todos:
166
+ - blocked if `dependencies` is non-empty and any dependency does not have a corresponding `*-complete-*.md` file.
167
+ - Prioritize by priority then id:
168
+ - `p1` before `p2` before `p3`
169
+ - lower `issue_id` first
170
+
171
+ Stop condition:
172
+
173
+ - If no unblocked `ready` todos remain:
174
+ - summarize remaining `pending`, `deferred` (parked for reference), and blocked items
175
+ - recommend running `/workflow:triage` for pending items
176
+ - stop (do not invent work)
177
+
178
+ For each task in priority order:
179
+
180
+ ```
181
+ while (tasks remain):
182
+ - Select the next `*-ready-*.md` todo that is unblocked
183
+ - Read any referenced files from the plan
184
+ - Look for similar patterns in codebase
185
+ - Implement following existing conventions
186
+ - Write tests for new functionality
187
+ - Run tests after changes according to the selected testing mode
188
+ - REQUIRED: Validation Gate (prove acceptance criteria + record evidence)
189
+ - Update the todo file Work Log and Acceptance Criteria (include evidence)
190
+ - Mark off the corresponding checkbox in the plan file ([ ] → [x])
191
+ - When a todo is complete, rename it to `*-complete-*.md` and update frontmatter
192
+ ```
193
+
194
+ Unblocked definition:
195
+
196
+ - `dependencies: []`, or
197
+ - all dependency issue_ids have a corresponding `*-complete-*.md` file
198
+
199
+ Plan sync rules:
200
+
201
+ - If the plan contains checkboxes, each todo should include one of:
202
+ - `Resources -> Plan checkbox:` with the exact checkbox text, or
203
+ - `Resources -> Plan section:` with a heading reference.
204
+ - When a todo completes, update the plan:
205
+ - Prefer matching the exact checkbox line and flipping `[ ]` -> `[x]`.
206
+ - If only a section pointer exists, add a short "Completed" note under that section.
207
+ - If the plan has no checkboxes, do not invent a new checklist in the plan by default.
208
+
209
+ IMPORTANT: Keep the plan accurate. It should reflect what is done vs remaining.
210
+
211
+ Minimum work log requirement (per todo):
212
+
213
+ - At least one Work Log entry per session containing:
214
+ - actions (file references)
215
+ - commands executed
216
+ - tests run
217
+ - results
218
+ - next steps
219
+
220
+ Discovery + scope changes (ask each time):
221
+
222
+ - If new, non-critical work is discovered, do NOT silently expand scope.
223
+ - Ask the user to choose one:
224
+ 1) Do now (scope increase): only if small + tightly coupled
225
+ 2) Create a triage item: create a new `pending` todo (default `p3` unless urgent) to be approved or deferred via `/workflow:triage`
226
+ 3) Park for reference: create a todo with Problem Statement + Findings + rationale, then mark it **deferred** (`*-deferred-*.md`, `status: deferred`) so it is kept for future reference but not in the executable queue
227
+ 4) Compound candidate only: capture as a `/workflow:compound` documentation candidate (no todo by default)
228
+ - Always record the decision in the todo Work Log.
229
+
230
+ **Validation Gate (per todo)**
231
+
232
+ Before marking a todo complete, you MUST prove the acceptance criteria are met.
233
+
234
+ For each todo:
235
+ - Re-state the acceptance criteria being validated (1–3 bullets)
236
+ - Run the smallest verification that proves it (tests, command output, UI check)
237
+ - Record evidence in the todo Work Log:
238
+ - commands run + results
239
+ - files changed (paths)
240
+ - if UI: route(s) validated + screenshots/logs when applicable
241
+
242
+ If validation fails:
243
+ - stop and fix immediately, or
244
+ - if blocked, follow the Blocker Protocol.
245
+
246
+ **Blocker Protocol (pause implementation)**
247
+
248
+ Trigger: you cannot proceed safely due to ambiguity, missing info, failing approach, or environment/tooling issue.
249
+
250
+ Rules:
251
+ - Pause implementation. Do not “push through” with guesses.
252
+ - Timebox investigation to reach options (not a full rewrite).
253
+ - Produce at least 3 viable options.
254
+
255
+ Output format (always):
256
+ - Blocker summary (1–2 sentences)
257
+ - Constraints discovered (bullets)
258
+ - Options (>=3): each with pros/cons, risks, effort
259
+ - Recommendation: one option + why (2–4 bullets)
260
+ - Decision prompt (single question): “Which option should we take?”
261
+
262
+ After decision:
263
+ - Convert the decision into explicit todos (implementation/investigation/deferral).
264
+ - If the chosen option is to run a timeboxed investigation or prototype, follow the **Spike Protocol** below.
265
+ - Record the decision + rationale in the todo Work Log.
266
+
267
+ **Spike Protocol (allocate a spike)**
268
+
269
+ Trigger: the plan includes spike/discussion todos (e.g. `tags: [spike]`), or the Blocker Protocol decision is to run a timeboxed investigation/prototype to de-risk.
270
+
271
+ Steps:
272
+
273
+ 1. **Spike todo:** Create a new `todos/*-pending-*.md` todo tagged `tags: [spike]` (or convert the current blocked todo to a spike todo). Fill Problem Statement, Proposed Solutions (options), and Acceptance Criteria (deliverable). If triage has not been run, recommend `/workflow:triage` to approve the spike and set timebox + deliverable; then treat the spike as `ready` once approved.
274
+ 2. **Isolated execution:** Recommend a dedicated spike worktree. Use `skill: git-worktree` with branch name `spike/<todo_id>-<slug>` (e.g. `spike/003-auth-approach`). Run worktree bootstrap per the git-worktree skill. Execute the spike in that worktree so build work is not mixed with exploration.
275
+ 3. **Research subagents (per spike):** Run in parallel when useful:
276
+ - Always (when agents exist): Task repo-research-analyst(context), Task learnings-researcher(context)
277
+ - Conditional: Task framework-docs-researcher(topic), Task best-practices-researcher(topic), Task git-history-analyzer(context) when touching existing behavior or framework choices
278
+ 4. **Spike deliverable (required in spike todo Work Log):**
279
+ - Options (>=3) with pros/cons, risks, effort
280
+ - Recommendation (one option + why)
281
+ - Concrete next steps: create or update build todos (or plan checkbox to flip) so the main plan can proceed
282
+ - **Should we compound this?** yes/no + one-line why (if yes, recommend `/workflow:compound` with spike context after the spike is complete)
283
+ 5. **Multiple spikes:** If there are N approved spike todos and they are independent, create N worktrees (one per spike, under configured `worktree_dir`). Run one spike per worktree; when the environment supports multiple agents, spikes may run in parallel.
284
+ 6. **After spike completion:** Mark the spike todo complete (`*-complete-*.md`). If the deliverable said "compound: yes", recommend running `/workflow:compound` with the spike context so the learning is captured in `docs/solutions/` with `tags: [..., spike]`.
285
+
286
+ 2. **Follow Existing Patterns**
287
+
288
+ - The plan should reference similar code - read those files first
289
+ - Match naming conventions exactly
290
+ - Reuse existing components where possible
291
+ - Follow project coding standards (see AGENTS.md)
292
+ - When in doubt, grep for similar implementations
293
+
294
+ 3. **Test Continuously**
295
+
296
+ - Run relevant tests after each significant change
297
+ - Don't wait until the end to test
298
+ - Fix failures immediately
299
+ - Add new tests for new functionality
300
+
301
+ 4. **UI Validation (Optional)**
302
+
303
+ If the plan includes UI changes:
304
+
305
+ - Validate key flows and critical screens.
306
+ - Use `/test-browser` for snapshots and basic interaction checks when applicable.
307
+
308
+ 5. **Track Progress**
309
+ - Keep todo files updated as you complete work
310
+ - Note any blockers or unexpected discoveries
311
+ - Create new tasks if scope expands
312
+ - Keep user informed of major milestones
313
+
314
+ ### Phase 3: Quality Check
315
+
316
+ 1. **Run Core Quality Checks**
317
+
318
+ Always run before declaring the work complete:
319
+
320
+ ```bash
321
+ # Run full test suite (use project's test command)
322
+ # Examples: bin/rails test, npm test, pytest, go test, etc.
323
+
324
+ # Run linting (per AGENTS.md)
325
+ ```
326
+
327
+ Prefer running the configured commands from `AGENTS.md`:
328
+
329
+ - `test_command` (required when available)
330
+ - `test_fast_command` (optional)
331
+ - `lint_command` (optional)
332
+ - `format_command` (optional)
333
+
334
+ If `test_command` is not configured, ask once for the project's test command and suggest adding it to `AGENTS.md`.
335
+
336
+ 2. **Consider Reviewer Agents** (Optional)
337
+
338
+ Use for complex, risky, or large changes.
339
+
340
+ If this repo defines preferred review agents in `AGENTS.md`, follow that.
341
+
342
+ If not configured, skip specialist reviewers by default.
343
+
344
+ 3. **Final Validation**
345
+ - All todo files created for this plan are marked complete
346
+ - All tests pass
347
+ - Linting/formatting checks pass (if configured)
348
+ - Code follows existing patterns
349
+ - UI validation completed (if applicable)
350
+ - No console errors or warnings
351
+
352
+ 4. **Update Plan Status**
353
+
354
+ If the input document has YAML frontmatter with a `status` field, update it to `completed`:
355
+ ```
356
+ status: active → status: completed
357
+ ```
358
+
359
+ 5. **Notify User**
360
+ - Summarize what was completed
361
+ - Note any follow-up work needed
362
+ - Suggest next steps if applicable
363
+
364
+ Risk-based recommendation:
365
+
366
+ - If the plan fidelity is `high` or confidence is `low`, recommend running `/workflow:review current` before considering the work complete.
367
+
368
+ Stop here by default.
369
+
370
+ If the user wants to ship (commits/PR/screenshots), handle that as a separate explicit request or a separate command.
371
+
372
+ ---
373
+
374
+ ## Key Principles
375
+
376
+ ### Start Fast, Execute Faster
377
+
378
+ - Get clarification once at the start, then execute
379
+ - Don't wait for perfect understanding - ask questions and move
380
+ - The goal is to **finish the feature**, not create perfect process
381
+
382
+ ### The Plan is Your Guide
383
+
384
+ - Work documents should reference similar code and patterns
385
+ - Load those references and follow them
386
+ - Don't reinvent - match what exists
387
+
388
+ ### Test As You Go
389
+
390
+ - Run tests after each change, not at the end
391
+ - Fix failures immediately
392
+ - Continuous testing prevents big surprises
393
+
394
+ ### Quality is Built In
395
+
396
+ - Follow existing patterns
397
+ - Write tests for new code
398
+ - Run linting/formatting as configured in `AGENTS.md`
399
+ - Use reviewer agents for complex/risky changes only
400
+
401
+ ### Ship Complete Features
402
+
403
+ - Mark all tasks completed before moving on
404
+ - Don't leave features 80% done
405
+ - A finished feature that ships beats a perfect feature that doesn't
406
+
407
+ ## Quality Checklist
408
+
409
+ Before marking work complete, verify:
410
+
411
+ - [ ] All clarifying questions asked and answered
412
+ - [ ] All todo files created for this plan are marked complete
413
+ - [ ] Tests pass (run `test_command`)
414
+ - [ ] Linting/formatting passes (run `lint_command` / `format_command` if configured)
415
+ - [ ] Code follows existing patterns
416
+ - [ ] UI validation completed (if applicable; use `/test-browser` when useful)
417
+ - [ ] If shipping is requested, capture any required artifacts (screenshots, release notes) per repo conventions
418
+
419
+ ## When to Use Reviewer Agents
420
+
421
+ **Don't use by default.** Use reviewer agents only when:
422
+
423
+ - Large refactor affecting many files (10+)
424
+ - Security-sensitive changes (authentication, permissions, data access)
425
+ - Performance-critical code paths
426
+ - Complex algorithms or business logic
427
+ - User explicitly requests thorough review
428
+
429
+ For most features: tests + linting + following patterns is sufficient.
430
+
431
+ ## Common Pitfalls to Avoid
432
+
433
+ - **Analysis paralysis** - Don't overthink, read the plan and execute
434
+ - **Skipping clarifying questions** - Ask now, not after building wrong thing
435
+ - **Ignoring plan references** - The plan has links for a reason
436
+ - **Testing at the end** - Test continuously or suffer later
437
+ - **Forgetting todo updates** - Update todo files and plan checkboxes or lose track of progress
438
+ - **80% done syndrome** - Finish the feature, don't move on early
439
+ - **Over-reviewing simple changes** - Save reviewer agents for complex work
@@ -0,0 +1,12 @@
1
+ ## References
2
+
3
+ This directory contains non-skill reference material.
4
+
5
+ Rules of thumb:
6
+
7
+ - Prefer skills for enforceable standards (MUST/MUST NOT + checklists + runbooks).
8
+ - Use references for supporting examples, provider-specific notes, or one-off guidance that should not become a skill.
9
+
10
+ Indexing:
11
+
12
+ - Link relevant reference docs from `src/AGENTS.md` (Skill Index) or from the owning skill under `src/.agents/skills/`.
@@ -0,0 +1,9 @@
1
+ ## Standards (Reference)
2
+
3
+ Place supporting standards docs here when they do not qualify as a standalone skill.
4
+
5
+ Examples:
6
+
7
+ - provider-specific webhook gotchas
8
+ - canonical JSON hashing guidelines
9
+ - Prisma + Postgres implementation notes for RLS/view/function boundaries
@@ -0,0 +1,227 @@
1
+ #!/usr/bin/env node
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+
5
+ function usage(exitCode = 0) {
6
+ const msg = `
7
+ Usage:
8
+ node .agents/scripts/self-check.mjs [--root <repoRoot>]
9
+
10
+ Checks:
11
+ - Every .agents/commands/**/*.md and .agents/agents/**/*.md is registered in opencode.json
12
+ - Managed entries in opencode.json point to existing source files
13
+ - Flags missing required frontmatter fields:
14
+ - commands: description (all)
15
+ - commands/workflow/**: invocation (recommended/expected)
16
+ - agents: description (all)
17
+ `;
18
+ (exitCode === 0 ? console.log : console.error)(msg.trimStart());
19
+ process.exit(exitCode);
20
+ }
21
+
22
+ function parseArgs(argv) {
23
+ const out = { root: process.cwd() };
24
+ for (let i = 2; i < argv.length; i++) {
25
+ const a = argv[i];
26
+ if (a === "--root") {
27
+ const v = argv[i + 1];
28
+ if (!v) usage(1);
29
+ out.root = v;
30
+ i++;
31
+ } else if (a === "-h" || a === "--help") usage(0);
32
+ else usage(1);
33
+ }
34
+ return out;
35
+ }
36
+
37
+ function realpathSafe(p) {
38
+ try {
39
+ return fs.realpathSync(p);
40
+ } catch {
41
+ return path.resolve(p);
42
+ }
43
+ }
44
+
45
+ function walkFiles(dirAbs, predicate) {
46
+ const out = [];
47
+ const stack = [dirAbs];
48
+ while (stack.length) {
49
+ const cur = stack.pop();
50
+ let entries;
51
+ try {
52
+ entries = fs.readdirSync(cur, { withFileTypes: true });
53
+ } catch {
54
+ continue;
55
+ }
56
+ for (const e of entries) {
57
+ const p = path.join(cur, e.name);
58
+ if (e.isDirectory()) stack.push(p);
59
+ else if (e.isFile() && predicate(p)) out.push(p);
60
+ }
61
+ }
62
+ out.sort();
63
+ return out;
64
+ }
65
+
66
+ function stripJsonc(input) {
67
+ let out = "";
68
+ let i = 0;
69
+ let inStr = false;
70
+ let strQuote = "";
71
+ let escape = false;
72
+ while (i < input.length) {
73
+ const c = input[i];
74
+ const n = input[i + 1];
75
+ if (inStr) {
76
+ out += c;
77
+ if (escape) escape = false;
78
+ else if (c === "\\") escape = true;
79
+ else if (c === strQuote) inStr = false;
80
+ i++;
81
+ continue;
82
+ }
83
+ if (c === '"' || c === "'") {
84
+ inStr = true;
85
+ strQuote = c;
86
+ out += c;
87
+ i++;
88
+ continue;
89
+ }
90
+ if (c === "/" && n === "/") {
91
+ while (i < input.length && input[i] !== "\n") i++;
92
+ continue;
93
+ }
94
+ if (c === "/" && n === "*") {
95
+ i += 2;
96
+ while (i < input.length && !(input[i] === "*" && input[i + 1] === "/")) i++;
97
+ i += 2;
98
+ continue;
99
+ }
100
+ out += c;
101
+ i++;
102
+ }
103
+ return out;
104
+ }
105
+
106
+ function parseFrontmatter(md) {
107
+ if (!md.startsWith("---\n") && !md.startsWith("---\r\n")) return {};
108
+ const end = md.indexOf("\n---", 4);
109
+ if (end === -1) return {};
110
+ const block = md.slice(4, end + 1);
111
+ const out = {};
112
+ for (const line of block.split(/\r?\n/)) {
113
+ const m = line.match(/^([A-Za-z0-9_-]+):\s*(.*)\s*$/);
114
+ if (!m) continue;
115
+ const k = m[1];
116
+ let v = m[2] ?? "";
117
+ v = v.replace(/^"(.*)"$/, "$1").replace(/^'(.*)'$/, "$1");
118
+ out[k] = v;
119
+ }
120
+ return out;
121
+ }
122
+
123
+ function discoverCommands(rootAbs) {
124
+ const dir = path.join(rootAbs, ".agents", "commands");
125
+ const files = walkFiles(dir, (p) => p.endsWith(".md"));
126
+ const out = [];
127
+ for (const fileAbs of files) {
128
+ const rel = path.relative(rootAbs, fileAbs).replaceAll(path.sep, "/");
129
+ const md = fs.readFileSync(fileAbs, "utf8");
130
+ const fm = parseFrontmatter(md);
131
+ const id = (fm.invocation || fm.name || path.basename(fileAbs, ".md")).trim();
132
+ out.push({ fileAbs, rel, fm, id });
133
+ }
134
+ return out;
135
+ }
136
+
137
+ function discoverAgents(rootAbs) {
138
+ const dir = path.join(rootAbs, ".agents", "agents");
139
+ const files = walkFiles(dir, (p) => p.endsWith(".md"));
140
+ const out = [];
141
+ for (const fileAbs of files) {
142
+ const rel = path.relative(rootAbs, fileAbs).replaceAll(path.sep, "/");
143
+ const md = fs.readFileSync(fileAbs, "utf8");
144
+ const fm = parseFrontmatter(md);
145
+ const id = (fm.name || path.basename(fileAbs, ".md")).trim();
146
+ out.push({ fileAbs, rel, fm, id });
147
+ }
148
+ return out;
149
+ }
150
+
151
+ function fileExists(rootAbs, rel) {
152
+ return fs.existsSync(path.join(rootAbs, rel));
153
+ }
154
+
155
+ function main() {
156
+ const args = parseArgs(process.argv);
157
+ const rootAbs = realpathSafe(args.root);
158
+ const opencodeAbs = path.join(rootAbs, "opencode.json");
159
+
160
+ console.log(`Resolved root: ${rootAbs}`);
161
+ console.log(`Checking opencode.json: ${opencodeAbs}`);
162
+
163
+ if (!fs.existsSync(opencodeAbs)) {
164
+ console.error("Error: missing opencode.json");
165
+ process.exit(2);
166
+ }
167
+
168
+ const opencode = JSON.parse(stripJsonc(fs.readFileSync(opencodeAbs, "utf8")));
169
+ const commandsReg = opencode.command ?? {};
170
+ const agentsReg = opencode.agent ?? {};
171
+
172
+ const errors = [];
173
+ const warnings = [];
174
+
175
+ const cmds = discoverCommands(rootAbs);
176
+ const ags = discoverAgents(rootAbs);
177
+
178
+ for (const c of cmds) {
179
+ if (!c.id) errors.push(`Command missing id (name/invocation): ${c.rel}`);
180
+ if (!c.fm.description) errors.push(`Command missing frontmatter description: ${c.rel} (${c.id || "?"})`);
181
+ if (c.rel.startsWith(".agents/commands/workflow/") && !c.fm.invocation) {
182
+ errors.push(`Workflow command missing frontmatter invocation: ${c.rel} (${c.id || "?"})`);
183
+ }
184
+ if (c.id && !commandsReg[c.id]) errors.push(`Command not registered in opencode.json: ${c.id} (source: ${c.rel})`);
185
+ }
186
+
187
+ for (const a of ags) {
188
+ if (!a.id) errors.push(`Agent missing id (name): ${a.rel}`);
189
+ if (!a.fm.description) errors.push(`Agent missing frontmatter description: ${a.rel} (${a.id || "?"})`);
190
+ if (a.id && !agentsReg[a.id]) errors.push(`Agent not registered in opencode.json: ${a.id} (source: ${a.rel})`);
191
+ }
192
+
193
+ // Validate managed template/prompt pointers exist
194
+ for (const [id, entry] of Object.entries(commandsReg)) {
195
+ const tpl = entry?.template;
196
+ if (typeof tpl !== "string") continue;
197
+ if (!tpl.includes("@.agents/commands/")) continue;
198
+ const m = tpl.match(/@(\.agents\/commands\/[^\n\r]+)/);
199
+ const rel = m?.[1];
200
+ if (rel && !fileExists(rootAbs, rel)) errors.push(`Managed command '${id}' points to missing file: ${rel}`);
201
+ }
202
+
203
+ for (const [id, entry] of Object.entries(agentsReg)) {
204
+ const p = entry?.prompt;
205
+ if (typeof p !== "string") continue;
206
+ if (!p.includes("{file:.agents/agents/")) continue;
207
+ const m = p.match(/\{file:(\.agents\/agents\/[^}]+)\}/);
208
+ const rel = m?.[1];
209
+ if (rel && !fileExists(rootAbs, rel)) errors.push(`Managed agent '${id}' points to missing file: ${rel}`);
210
+ }
211
+
212
+ if (warnings.length) {
213
+ console.log("\nWarnings:");
214
+ for (const w of warnings) console.log(`- ${w}`);
215
+ }
216
+
217
+ if (errors.length) {
218
+ console.error("\nSelf-check failed:");
219
+ for (const e of errors) console.error(`- ${e}`);
220
+ process.exit(2);
221
+ }
222
+
223
+ console.log("Self-check passed.");
224
+ }
225
+
226
+ main();
227
+