opensddrag 0.1.1 → 0.2.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.
@@ -1,20 +1,29 @@
1
1
  /**
2
2
  * OpenCode command templates
3
- * These commands are identical to Claude Code commands
4
- * Installed to .opencode/commands/opsr/ when OpenCode is selected
3
+ * Installed to .opencode/commands/opsr/ when OpenCode is selected.
4
+ * Uses a compact openCodeHeader() (project_slug only) instead of the Claude Code
5
+ * IMPORTANT/tool-list/STOP block — MCP tools are auto-available in OpenCode.
6
+ *
7
+ * Per the command-skill-separation-contract, every command is a pure pointer:
8
+ * Purpose + Input + a single "Load the skill" step. The complete workflow
9
+ * (MCP calls, templates, examples, edge cases) lives in the matching
10
+ * opensddrag-<name> skill. Do NOT add workflow steps here.
5
11
  */
6
12
 
7
- export function getOpenCodeCommands(slug, serverUrl) {
8
- const header = (name) => `> **IMPORTANT — ${name}**
9
- > This command requires the **\`opensddrag\`** MCP server (${serverUrl}), configured in \`opencode.json\`.
10
- > MCP tools provided by this server: \`create_artifact\`, \`read_artifact\`, \`list_artifacts\`, \`update_artifact\`, \`validate_artifact\`, \`link_artifacts\`, \`get_relationships\`, \`search_semantic\`, \`recall_episodes\`, \`get_working_context\`, \`update_working_context\`, \`record_trace\`
11
- > **If these tools are NOT in your active tool list**: STOP immediately. Do NOT investigate or try alternatives. Tell the user: "The opensddrag MCP server is not connected. Please start it (\`docker compose up -d\`) and reload the project."
12
- > All artifact reads/writes go through these MCP tools. DO NOT create local files. DO NOT write markdown to disk.
13
- > **project_slug for every call: \`${slug}\`**
14
-
15
- ---
13
+ export function getOpenCodeCommands(slug, _serverUrl) {
14
+ const fm = (description) => `---\ndescription: ${description}\n---\n\n`;
16
15
 
16
+ const openCodeHeader = () => `> **project_slug for every call:** \`${slug}\`\n\n---\n\n\n`;
17
17
 
18
+ /**
19
+ * Standard pointer tail for OpenCode commands. Tells the agent to load the
20
+ * corresponding skill (the single source of truth for the workflow) via the
21
+ * `skill` tool and follow it. No workflow detail is duplicated here.
22
+ */
23
+ const pointerTail = (skillName) => `
24
+ ## Step 1 — Load the skill
25
+ Invoke the \`${skillName}\` skill (OpenCode loads it from \`.opencode/skills/${skillName}/SKILL.md\` via the \`skill\` tool).
26
+ The skill contains the complete workflow — MCP calls, templates, examples, edge cases. Follow it verbatim and do not duplicate its steps here.
18
27
  `;
19
28
 
20
29
  return [
@@ -22,792 +31,189 @@ export function getOpenCodeCommands(slug, serverUrl) {
22
31
  {
23
32
  folder: "opsr",
24
33
  name: "propose",
25
- content: `${header("/opsr:propose")}## Purpose
34
+ content: `${fm("Create a named change proposal")}${openCodeHeader()}## Purpose
26
35
  Create a named change with a proposal artifact. This is the entry point for every new feature or change.
27
36
  The proposal defines WHY, WHAT changes, WHICH capabilities are affected, and the IMPACT.
28
37
  After this command, /opsr:spec and /opsr:design become available.
29
38
 
30
39
  ## Input
31
40
  $ARGUMENTS = change name (kebab-case) or plain description. If plain description, derive a kebab-case name.
32
-
33
- ## Step 1 — Derive change name
34
- If $ARGUMENTS is a plain description (contains spaces), convert to kebab-case.
35
- Example: "add user authentication" → "add-user-authentication"
36
-
37
- ## Step 2 — Search for existing work (avoid duplication)
38
- Call MCP tool:
39
- \`search_semantic(query="$ARGUMENTS", project_slug="${slug}", limit=5)\`
40
- If relevant artifacts are found, show them and ask the user to confirm this is new work.
41
-
42
- ## Step 3 — Write the proposal content
43
- Compose the following structure (do NOT skip any section):
44
-
45
- \`\`\`markdown
46
- # <change-name>
47
-
48
- ## Why
49
- [1-2 sentences on the problem or opportunity being addressed]
50
-
51
- ## What Changes
52
- - [Specific change 1]
53
- - [Specific change 2]
54
- - **BREAKING** [Breaking change if any]
55
-
56
- ## Capabilities
57
- ### New Capabilities
58
- - [capability-name] — brief description
59
-
60
- ### Modified Capabilities
61
- - [existing-capability] — what changes
62
-
63
- ## Impact
64
- [Affected code, APIs, dependencies, systems]
65
- \`\`\`
66
-
67
- ## Step 4 — Save proposal to database
68
- Call MCP tool:
69
- \`create_artifact(name="<change-name>-proposal", type="proposal", content="<full proposal markdown>", metadata={"change_name": "<change-name>", "status_phase": "planning"}, project_slug="${slug}")\`
70
- Note the returned artifact ID.
71
-
72
- ## Step 5 — Create spec drafts for each capability
73
- Parse the "## Capabilities" section. For each capability listed in "New Capabilities" or "Modified Capabilities":
74
- 1. Check if a spec for this capability already exists:
75
- \`read_artifact(name="<change-name>-<capability-name>-spec", project_slug="${slug}")\`
76
- If it exists and is not empty, skip creating a draft.
77
-
78
- 2. If no spec exists, create a draft spec:
79
- \`create_artifact(name="<change-name>-<capability-name>-spec", type="spec", status="draft", content="# <capability-name> Specification
80
-
81
- [TODO: Define purpose, requirements, and scenarios for this capability]
82
-
83
- ## Purpose
84
- [TODO: Describe what this capability enables]
85
-
86
- ## Requirements
87
- [TODO: List requirements with REQ-NNN format]
88
-
89
- ### Requirement: <REQ-001>
90
- [TODO: Describe requirement using SHALL/MUST language]
91
-
92
- #### Scenario: <Name>
93
- - **WHEN** [condition]
94
- - **THEN** [expected outcome]", metadata={"change_name": "<change-name>", "capability": "<capability-name>", "is_delta": true}, project_slug="${slug}")\`
95
-
96
- ## Step 6 — Create design skeleton
97
- Create a draft design document:
98
- \`create_artifact(name="<change-name>-design", type="design", status="draft", content="# Design: <change-name>
99
-
100
- [TODO: Document technical decisions, architecture, trade-offs]
101
-
102
- ## Context
103
- [TODO: Background and constraints]
104
-
105
- ## Goals / Non-Goals
106
- **Goals:**
107
- - [Goal 1]
108
-
109
- **Non-Goals:**
110
- - [Non-goal 1]
111
-
112
- ## Decisions
113
- ### Decision: <Title>
114
- **Chosen:** [What was chosen]
115
- **Alternatives:**
116
- - [Alternative 1] — rejected because [reason]
117
-
118
- ## Architecture
119
- [TODO: Components and data flow]
120
-
121
- ## Risks / Trade-offs
122
- | Risk | Mitigation |
123
- |------|------------|
124
- | [Risk] | [Mitigation] |
125
-
126
- ## Open Questions
127
- - [ ] [Question]
128
- ", metadata={"change_name": "<change-name>"}, project_slug="${slug}")\`
129
-
130
- ## Step 7 — Record the action
131
- Call MCP tool:
132
- \`record_trace(action="propose", result_summary="Created proposal: <change-name>-proposal", project_slug="${slug}")\`
133
-
134
- ## Step 8 — Show what is now available
135
- Tell the user:
136
- - "Proposal saved with full scaffolding. The following commands are now available:"
137
- - \`/opsr:spec <change-name>\` — formalize requirements (draft specs already created for each capability)
138
- - \`/opsr:design <change-name>\` — document technical approach (draft design already created)
139
- - Or run \`/opsr:flow <change-name>\` to continue the full flow automatically.
140
- `,
41
+ ${pointerTail("opensddrag-propose")}`,
141
42
  },
142
43
 
143
44
  // ── /opsr:spec ─────────────────────────────────────────────────────────────
144
45
  {
145
46
  folder: "opsr",
146
47
  name: "spec",
147
- content: `${header("/opsr:spec")}## Purpose
48
+ content: `${fm("Write capability specs with requirements and scenarios")}${openCodeHeader()}## Purpose
148
49
  Create one or more spec artifacts for the capabilities listed in a proposal.
149
50
  Each capability in "New Capabilities" or "Modified Capabilities" gets its own spec artifact.
150
51
  Specs use SHALL/MUST language and must have Scenarios with WHEN/THEN format.
151
52
 
152
53
  ## Input
153
54
  $ARGUMENTS = change name. If not provided, list proposals and ask.
154
-
155
- ## Step 1 — Read the proposal from the database
156
- Call MCP tool:
157
- \`list_artifacts(type="proposal", project_slug="${slug}")\`
158
- Then read the selected proposal:
159
- \`read_artifact(name="<change-name>-proposal", project_slug="${slug}")\`
160
-
161
- ## Step 2 — Identify capabilities from the proposal
162
- Parse the "## Capabilities" section. Each capability in "New Capabilities" and "Modified Capabilities" needs a spec.
163
-
164
- **New capability** → create a full spec (Purpose + Requirements + Scenarios)
165
- **Modified capability** → check if a main spec exists first:
166
- \`search_semantic(query="<capability-name> spec", project_slug="${slug}", limit=3)\`
167
- If main spec exists → create a DELTA spec with ADDED/MODIFIED/REMOVED/RENAMED sections.
168
- If no main spec → create BOTH:
169
- 1. The main spec with metadata={"capability": "<capability-name>", "is_delta": false}
170
- 2. The delta spec with metadata={"change_name": "<change-name>", "capability": "<capability-name>", "is_delta": true}
171
-
172
- ## Step 3 — Write spec content for EACH capability
173
-
174
- ### Full spec structure (new capabilities):
175
- \`\`\`markdown
176
- # <capability-name> Specification
177
-
178
- ## Purpose
179
- [High-level description of this capability]
180
-
181
- ## Requirements
182
-
183
- ### Requirement: <REQ-001 Name>
184
- [Description using SHALL/MUST language]
185
-
186
- #### Scenario: <Happy path name>
187
- - **WHEN** [condition]
188
- - **THEN** [expected outcome]
189
-
190
- #### Scenario: <Edge case name>
191
- - **WHEN** [edge condition]
192
- - **THEN** [expected outcome]
193
-
194
- ### Requirement: <REQ-002 Name>
195
- [Description]
196
-
197
- #### Scenario: <Name>
198
- - **WHEN** [condition]
199
- - **THEN** [outcome]
200
- \`\`\`
201
-
202
- ### Delta spec structure (modified capabilities):
203
- \`\`\`markdown
204
- # <capability-name> Specification — Delta
205
-
206
- ## ADDED Requirements
207
- ### Requirement: <New requirement name>
208
- [Full requirement with scenarios]
209
-
210
- ## MODIFIED Requirements
211
- ### Requirement: <Existing requirement name>
212
- [Updated requirement — include FULL updated text with all scenarios]
213
-
214
- ## REMOVED Requirements
215
- ### Requirement: <Removed requirement name>
216
- **Reason:** [Why this is being removed]
217
- **Migration:** [How consumers should migrate]
218
-
219
- ## RENAMED Requirements
220
- - FROM: \`### Requirement: Old Name\`
221
- - TO: \`### Requirement: New Name\`
222
- \`\`\`
223
-
224
- ## Step 4 — Save each spec to the database
225
- For each capability spec:
226
- \`create_artifact(name="<change-name>-<capability-name>-spec", type="spec", content="<full spec markdown>", metadata={"change_name": "<change-name>", "capability": "<capability-name>", "is_delta": true/false}, project_slug="${slug}")\`
227
-
228
- ## Step 5 — Link each spec to the proposal
229
- \`link_artifacts(source_name="<spec-name>", target_name="<change-name>-proposal", relationship_type="implements", project_slug="${slug}")\`
230
-
231
- ## Step 6 — Validate each spec
232
- \`validate_artifact(name="<spec-name>", project_slug="${slug}")\`
233
- Fix any validation errors before continuing.
234
-
235
- ## Step 7 — Record the action
236
- \`record_trace(action="spec", result_summary="Created specs for: <capability-list>", project_slug="${slug}")\`
237
-
238
- ## Step 8 — Show what is now available
239
- - "Specs saved. You can now run:"
240
- - \`/opsr:design <change-name>\` — document technical decisions
241
- `,
55
+ ${pointerTail("opensddrag-spec")}`,
242
56
  },
243
57
 
244
58
  // ── /opsr:design ───────────────────────────────────────────────────────────
245
59
  {
246
60
  folder: "opsr",
247
61
  name: "design",
248
- content: `${header("/opsr:design")}## Purpose
62
+ content: `${fm("Document technical decisions and architecture")}${openCodeHeader()}## Purpose
249
63
  Create a design document that captures technical decisions, architecture, trade-offs, and open questions.
250
64
  The design must be based on the proposal and spec artifacts already in the database.
251
65
 
252
66
  ## Input
253
67
  $ARGUMENTS = change name.
254
-
255
- ## Step 1 — Read proposal and all specs from the database
256
- \`read_artifact(name="<change-name>-proposal", project_slug="${slug}")\`
257
- \`list_artifacts(type="spec", project_slug="${slug}")\`
258
- Read each spec linked to this change:
259
- \`get_relationships(name="<change-name>-proposal", project_slug="${slug}")\`
260
-
261
- ## Step 2 — Search for related prior designs
262
- \`search_semantic(query="<change topic> design decisions", project_slug="${slug}", limit=3)\`
263
- Use findings as context — don't duplicate prior work.
264
-
265
- ## Step 3 — Write the design content
266
- \`\`\`markdown
267
- # Design: <change-name>
268
-
269
- ## Context
270
- [Background, current state, constraints that shaped this design]
271
-
272
- ## Goals / Non-Goals
273
- **Goals:**
274
- - [What this design achieves]
275
-
276
- **Non-Goals:**
277
- - [What this design deliberately does NOT address]
278
-
279
- ## Decisions
280
-
281
- ### Decision: <Title>
282
- **Chosen:** [What was chosen and why]
283
- **Alternatives considered:**
284
- - [Alternative 1] — rejected because [reason]
285
- - [Alternative 2] — rejected because [reason]
286
-
287
- ### Decision: <Title>
288
- ...
289
-
290
- ## Architecture
291
- [Components, data flow, integration points — use ASCII diagrams if helpful]
292
-
293
- ## Risks / Trade-offs
294
- | Risk | Mitigation |
295
- |------|------------|
296
- | [Risk] | [Mitigation] |
297
-
298
- ## Migration Plan
299
- [Deployment steps, backward compatibility, rollback plan]
300
-
301
- ## Open Questions
302
- - [ ] [Question that still needs resolution]
303
- \`\`\`
304
-
305
- ## Step 4 — Save design to database
306
- \`create_artifact(name="<change-name>-design", type="design", content="<full design markdown>", metadata={"change_name": "<change-name>"}, project_slug="${slug}")\`
307
-
308
- ## Step 5 — Link design to proposal
309
- \`link_artifacts(source_name="<change-name>-design", target_name="<change-name>-proposal", relationship_type="depends_on", project_slug="${slug}")\`
310
-
311
- ## Step 6 — Record and show next steps
312
- \`record_trace(action="design", result_summary="Created design: <change-name>-design", project_slug="${slug}")\`
313
- Tell the user: "Design saved. Run \`/opsr:tasks <change-name>\` to decompose into tasks."
314
- `,
68
+ ${pointerTail("opensddrag-design")}`,
315
69
  },
316
70
 
317
71
  // ── /opsr:tasks ────────────────────────────────────────────────────────────
318
72
  {
319
73
  folder: "opsr",
320
74
  name: "tasks",
321
- content: `${header("/opsr:tasks")}## Purpose
75
+ content: `${fm("Break a design into atomic implementation tasks")}${openCodeHeader()}## Purpose
322
76
  Decompose the specs and design into atomic, verifiable task artifacts.
323
77
  Each task must map to one or more spec requirements (REQ-NNN) and be completable in under 4 hours.
324
78
  Tasks depend on BOTH specs AND design being in the database.
325
79
 
326
80
  ## Input
327
81
  $ARGUMENTS = change name.
328
-
329
- ## Step 1 — Read all planning artifacts from the database
330
- \`read_artifact(name="<change-name>-proposal", project_slug="${slug}")\`
331
- \`read_artifact(name="<change-name>-design", project_slug="${slug}")\`
332
- Get all specs for this change:
333
- \`get_relationships(name="<change-name>-proposal", project_slug="${slug}")\`
334
- Read each linked spec artifact.
335
-
336
- ## Step 2 — Plan task groups from the design and specs
337
- Group tasks by logical phase. Each task must have:
338
- - A clear **Goal** (what it accomplishes)
339
- - **Acceptance criteria** referencing spec REQ-NNN items (not vague)
340
- - **Dependencies** on other tasks (if any)
341
- - Estimated effort: < 4 hours
342
-
343
- ## Step 3 — Create each task artifact in the database
344
- For each task (name as \`<change-name>-task-<group>-<N>\`):
345
- \`create_artifact(name="<change-name>-task-<group>-<N>", type="task", content="## Goal\\n<what this task accomplishes>\\n\\n## Acceptance Criteria\\n- [ ] REQ-NNN: <criterion>\\n- [ ] <criterion>\\n\\n## Dependencies\\n- <other task name or 'none'>", metadata={"change_name": "<change-name>", "group": "<group-name>", "order": <N>}, project_slug="${slug}")\`
346
-
347
- ## Step 4 — Link each task to its spec(s)
348
- \`link_artifacts(source_name="<task-name>", target_name="<spec-name>", relationship_type="implements", project_slug="${slug}")\`
349
-
350
- ## Step 5 — Update working context with the task list
351
- \`update_working_context(context={"change_name": "<change-name>", "tasks": ["<task-1>", "<task-2>", "..."], "current_task": null}, project_slug="${slug}")\`
352
-
353
- ## Step 6 — Record and show next steps
354
- \`record_trace(action="tasks", result_summary="Created <N> tasks for <change-name>", project_slug="${slug}")\`
355
- Show the full task list with names and goals.
356
- Tell the user: "Tasks saved. Run \`/opsr:apply <change-name>\` to start implementing."
357
- `,
82
+ ${pointerTail("opensddrag-tasks")}`,
358
83
  },
359
84
 
360
85
  // ── /opsr:apply ────────────────────────────────────────────────────────────
361
86
  {
362
87
  folder: "opsr",
363
88
  name: "apply",
364
- content: `${header("/opsr:apply")}## Purpose
89
+ content: `${fm("Implement the next pending task")}${openCodeHeader()}## Purpose
365
90
  Implement tasks one by one, validating each against the spec acceptance criteria before marking done.
366
91
  Read ALL planning artifacts (proposal, specs, design) as context before implementing any task.
367
92
 
368
93
  ## Input
369
94
  $ARGUMENTS = change name, or specific task name.
370
-
371
- ## Step 1 — Load full planning context from the database
372
- \`get_working_context(project_slug="${slug}")\`
373
- \`read_artifact(name="<change-name>-proposal", project_slug="${slug}")\`
374
- \`read_artifact(name="<change-name>-design", project_slug="${slug}")\`
375
- Get and read all specs linked to this change.
376
-
377
- ## Step 2 — List pending tasks in order
378
- \`list_artifacts(type="task", status="draft", project_slug="${slug}")\`
379
- AND
380
- \`list_artifacts(type="task", status="active", project_slug="${slug}")\`
381
- Combine both results. Prioritize tasks with status="active" (resuming interrupted session), then status="draft" in dependency order. Filter tasks for this change using metadata.change_name.
382
-
383
- ## Step 3 — Select next task
384
- If $ARGUMENTS specifies a task name, use it.
385
- Otherwise:
386
- 1. First, check for tasks with status="active" (resuming interrupted session)
387
- 2. If no active tasks, pick the first draft task whose dependencies are all archived (done)
388
-
389
- Read the task:
390
- \`read_artifact(name="<task-name>", project_slug="${slug}")\`
391
-
392
- ## Step 4 — Mark task as active in database
393
- \`update_artifact(name="<task-name>", status="active", project_slug="${slug}")\`
394
- Update working context:
395
- \`update_working_context(context={"current_task": "<task-name>"}, project_slug="${slug}")\`
396
-
397
- ## Step 5 — Implement the task
398
- Implement the code changes required by the task.
399
- The implementation MUST satisfy all acceptance criteria from the task's "## Acceptance Criteria" section.
400
- Pause and ask the user if any requirement is unclear — do not guess.
401
-
402
- ## Step 6 — Validate against spec requirements
403
- For each acceptance criterion (REQ-NNN) in the task:
404
- - Confirm the implementation satisfies the requirement
405
- - Verify no spec scenarios are broken
406
-
407
- ## Step 7 — Mark task as done in database
408
- \`update_artifact(name="<task-name>", status="archived", project_slug="${slug}")\`
409
-
410
- ## Step 8 — Record and check remaining tasks
411
- \`record_trace(action="apply_task", result_summary="Completed task: <task-name>", artifact_id="<artifact-id>", project_slug="${slug}")\`
412
- \`list_artifacts(type="task", status="draft", project_slug="${slug}")\`
413
- - If tasks remain: "Task complete. Run \`/opsr:apply <change-name>\` for the next task."
414
- - If all done: "All tasks complete. Run \`/opsr:verify <change-name>\` to validate, then \`/opsr:archive <change-name>\`."
415
- `,
95
+ ${pointerTail("opensddrag-apply")}`,
416
96
  },
417
97
 
418
98
  // ── /opsr:verify ────────────────────────────────────────────────────────────
419
99
  {
420
100
  folder: "opsr",
421
101
  name: "verify",
422
- content: `${header("/opsr:verify")}## Purpose
102
+ content: `${fm("Validate implementation against spec requirements")}${openCodeHeader()}## Purpose
423
103
  Validate the implementation against the spec requirements and design decisions.
424
104
  Produces a structured report with CRITICAL, WARNING, and SUGGESTION severity levels.
425
105
  Does NOT modify any artifacts — read-only operation.
426
106
 
427
107
  ## Input
428
108
  $ARGUMENTS = change name.
429
-
430
- ## Step 1 — Load all artifacts from the database
431
- \`read_artifact(name="<change-name>-proposal", project_slug="${slug}")\`
432
- \`read_artifact(name="<change-name>-design", project_slug="${slug}")\`
433
- Get all specs and tasks for this change:
434
- \`get_relationships(name="<change-name>-proposal", project_slug="${slug}")\`
435
- Read each linked spec and task artifact.
436
-
437
- ## Step 2 — Verify COMPLETENESS
438
- Check task completion:
439
- \`list_artifacts(type="task", status="draft", project_slug="${slug}")\`
440
- - If pending tasks exist → **CRITICAL: Tasks not complete**
441
-
442
- Extract all requirements (REQ-NNN) from specs.
443
- For each requirement, search the codebase for implementation evidence.
444
- - If requirement has no implementation evidence → **CRITICAL: Requirement not implemented**
445
-
446
- ## Step 3 — Verify CORRECTNESS
447
- For each spec scenario (WHEN/THEN blocks):
448
- - Search the codebase for test coverage or implementation of the scenario condition
449
- - If scenario has no coverage → **WARNING: Scenario not covered**
450
-
451
- ## Step 4 — Verify COHERENCE
452
- Extract decisions from the "## Decisions" section of the design.
453
- For each decision:
454
- - Check if the implementation follows the chosen approach
455
- - If implementation deviates from a decision → **SUGGESTION: Possible deviation from design**
456
-
457
- ## Step 5 — Generate report
458
- Output a structured report:
459
-
460
- \`\`\`
461
- ## Verification Report: <change-name>
462
-
463
- ### Summary
464
- | Dimension | Status |
465
- |--------------|--------|
466
- | Completeness | ✓/✗ |
467
- | Correctness | ✓/✗ |
468
- | Coherence | ✓/✗ |
469
-
470
- ### CRITICAL Issues
471
- - [Issue description]
472
-
473
- ### WARNING Issues
474
- - [Issue description]
475
-
476
- ### SUGGESTIONS
477
- - [Issue description]
478
-
479
- ### Assessment
480
- [READY TO ARCHIVE | ISSUES MUST BE FIXED BEFORE ARCHIVING]
481
- \`\`\`
482
-
483
- ## Step 6 — Record the verification
484
- \`record_trace(action="verify", result_summary="Verification: <PASS/FAIL> — <N> critical, <N> warnings", project_slug="${slug}")\`
485
- `,
109
+ ${pointerTail("opensddrag-verify")}`,
486
110
  },
487
111
 
488
112
  // ── /opsr:sync ──────────────────────────────────────────────────────────────
489
113
  {
490
114
  folder: "opsr",
491
115
  name: "sync",
492
- content: `${header("/opsr:sync")}## Purpose
116
+ content: `${fm("Merge delta specs into main specs")}${openCodeHeader()}## Purpose
493
117
  Merge delta specs (ADDED/MODIFIED/REMOVED/RENAMED sections) into the main specs stored in the database.
494
118
  Delta specs are created by /opsr:spec for MODIFIED capabilities.
495
119
  After sync, the main spec reflects all changes. This is called automatically during /opsr:archive.
496
120
 
497
121
  ## Input
498
122
  $ARGUMENTS = change name.
499
-
500
- ## Step 1 — Find delta specs for this change
501
- \`list_artifacts(type="spec", project_slug="${slug}")\`
502
- Filter specs where metadata.change_name = "<change-name>" AND metadata.is_delta = true.
503
-
504
- ## Step 2 — For each delta spec, find the main spec
505
- Search for the main (non-delta) spec for the same capability:
506
- \`search_semantic(query="<capability-name> spec", project_slug="${slug}", limit=5)\`
507
- Find the spec where metadata.is_delta = false (or not set) for the same capability.
508
-
509
- ## Step 3 — Apply delta operations to the main spec
510
- Read both delta and main spec:
511
- \`read_artifact(name="<delta-spec-name>", project_slug="${slug}")\`
512
- \`read_artifact(name="<main-spec-name>", project_slug="${slug}")\`
513
-
514
- Apply each section from the delta:
515
-
516
- **## ADDED Requirements:**
517
- - Find or confirm the requirement does NOT exist in main spec
518
- - Append the new requirement (with all scenarios) to the main spec
519
-
520
- **## MODIFIED Requirements:**
521
- - Find the requirement in main spec by name
522
- - Apply ONLY the changed parts (add new scenarios, update descriptions)
523
- - Do NOT wholesale replace — apply partial updates intelligently
524
-
525
- **## REMOVED Requirements:**
526
- - Find the requirement in main spec by name
527
- - Remove the entire requirement block
528
- - The Reason and Migration from delta should be noted in a comment
529
-
530
- **## RENAMED Requirements:**
531
- - Find FROM name in main spec
532
- - Change the heading to TO name
533
-
534
- ## Step 4 — Save the updated main spec to database
535
- \`update_artifact(name="<main-spec-name>", content="<merged spec content>", project_slug="${slug}")\`
536
-
537
- ## Step 5 — Mark delta spec as archived
538
- After merging the delta, mark the delta spec as archived:
539
- \`update_artifact(name="<delta-spec-name>", status="archived", metadata={"synced_at": "<ISO timestamp>", "merged_into": "<main-spec-name>"}, project_slug="${slug}")\`
540
-
541
- ## Step 6 — Record the sync
542
- \`record_trace(action="sync", result_summary="Synced delta for capability: <capability> into main spec", project_slug="${slug}")\`
543
- Tell the user which capabilities were updated.
544
- `,
123
+ ${pointerTail("opensddrag-sync")}`,
545
124
  },
546
125
 
547
126
  // ── /opsr:archive ───────────────────────────────────────────────────────────
548
127
  {
549
128
  folder: "opsr",
550
129
  name: "archive",
551
- content: `${header("/opsr:archive")}## Purpose
130
+ content: `${fm("Finalize and archive a completed change")}${openCodeHeader()}## Purpose
552
131
  Finalize a completed change by archiving all its artifacts.
553
132
  Runs verification checks, syncs delta specs to main specs, then archives everything.
554
133
 
555
134
  ## Input
556
135
  $ARGUMENTS = change name. If not provided, list active changes and ask.
557
-
558
- ## Step 1 — Get full status of the change
559
- \`list_artifacts(type="proposal", project_slug="${slug}")\`
560
- Select the change to archive (or use $ARGUMENTS).
561
- \`get_relationships(name="<change-name>-proposal", project_slug="${slug}")\`
562
- Get all linked artifacts (specs, design, tasks).
563
-
564
- ## Step 2 — Validate artifact completion
565
- Check each artifact status:
566
- \`list_artifacts(type="task", status="draft", project_slug="${slug}")\`
567
- If pending tasks exist → warn the user and ask for confirmation to archive anyway.
568
-
569
- ## Step 3 — Validate task completion
570
- Count draft vs archived tasks. If any draft tasks remain → warn and confirm.
571
-
572
- ## Step 4 — Check for delta specs that need syncing
573
- \`list_artifacts(type="spec", project_slug="${slug}")\`
574
- Filter for specs where metadata.change_name = "<change-name>" AND metadata.is_delta = true.
575
-
576
- If delta specs exist:
577
- - Show which capabilities have deltas
578
- - Ask: "Sync delta specs to main specs now? (recommended)"
579
- - If yes → execute /opsr:sync logic for each delta spec
580
- - If no → archive without syncing
581
-
582
- ## Step 5 — Archive all change artifacts
583
- For each artifact in this change (proposal, all specs, design, all tasks):
584
- \`update_artifact(name="<artifact-name>", status="archived", metadata={"archived_at": "<ISO timestamp>", "change_name": "<change-name>"}, project_slug="${slug}")\`
585
-
586
- ## Step 6 — Record and show summary
587
- \`record_trace(action="archive", result_summary="Archived change: <change-name> (<N> artifacts)", project_slug="${slug}")\`
588
- Show summary:
589
- - Artifacts archived: list
590
- - Specs synced: list (if any)
591
- - "Change <change-name> is complete."
592
- `,
136
+ ${pointerTail("opensddrag-archive")}`,
593
137
  },
594
138
 
595
139
  // ── /opsr:explore ───────────────────────────────────────────────────────────
596
140
  {
597
141
  folder: "opsr",
598
142
  name: "explore",
599
- content: `${header("/opsr:explore")}## Purpose
143
+ content: `${fm("Investigate a problem without implementing anything")}${openCodeHeader()}## Purpose
600
144
  Think through a problem, idea, or question WITHOUT implementing anything.
601
145
  Explore creates understanding before committing to a proposal.
602
146
  You may create OpenSddRag artifacts to capture insights, but NEVER write application code.
603
147
 
604
148
  ## Input
605
149
  $ARGUMENTS = topic, question, or idea to explore.
606
-
607
- ## Stance
608
- You are in THINKING MODE. Your role is to:
609
- - Ask clarifying questions
610
- - Surface multiple options with trade-offs
611
- - Investigate the codebase (read-only)
612
- - Create ASCII diagrams to illustrate ideas
613
- - Challenge assumptions
614
- - Reference existing specs for context
615
-
616
- You MUST NOT:
617
- - Write application code
618
- - Create implementation files
619
- - Make changes to the codebase
620
-
621
- ## Step 1 — Check for existing related work
622
- \`search_semantic(query="$ARGUMENTS", project_slug="${slug}", limit=5)\`
623
- \`recall_episodes(query="$ARGUMENTS", project_slug="${slug}", limit=3)\`
624
- Share any existing specs or past decisions that are relevant.
625
-
626
- ## Step 2 — Investigate and think
627
- - Read relevant codebase files (read-only)
628
- - Identify constraints and dependencies
629
- - Surface at least 2 different approaches
630
- - For each approach, list trade-offs
631
-
632
- ## Step 3 — Capture insights (if user asks)
633
- If the user wants to capture a finding or decision, create an artifact:
634
- \`create_artifact(name="explore-<topic>-<date>", type="proposal", content="<exploration notes, options, trade-offs>", metadata={"explore": true}, project_slug="${slug}")\`
635
-
636
- ## Step 4 — Transition when ready
637
- When the user has enough insight to decide:
638
- - Summarize key findings and recommendation
639
- - Ask: "Ready to create a formal proposal? Run \`/opsr:propose <name>\`"
640
- `,
150
+ ${pointerTail("opensddrag-explore")}`,
641
151
  },
642
152
 
643
153
  // ── /opsr:continue ─────────────────────────────────────────────────────────
644
154
  {
645
155
  folder: "opsr",
646
156
  name: "continue",
647
- content: `${header("/opsr:continue")}## Purpose
157
+ content: `${fm("Create the next artifact in the SDD dependency chain")}${openCodeHeader()}## Purpose
648
158
  Create the NEXT single artifact in the dependency chain for a change.
649
159
  Unlike /opsr:flow which creates all artifacts, this creates ONE artifact and stops.
650
160
  Dependency order: proposal → specs → design → tasks.
651
161
 
652
162
  ## Input
653
163
  $ARGUMENTS = change name.
654
-
655
- ## Step 1 — Get current status from database
656
- \`list_artifacts(type="proposal", project_slug="${slug}")\`
657
- Identify the change to continue.
658
- \`get_relationships(name="<change-name>-proposal", project_slug="${slug}")\`
659
- Get all existing artifacts for this change.
660
-
661
- ## Step 2 — Find the next artifact to create
662
- Check which artifacts exist and which are missing, in dependency order:
663
- 1. proposal → if missing, stop (must run /opsr:propose first)
664
- 2. specs → if any capability has no spec → create ONE spec and stop
665
- 3. design → if missing and all specs exist → create design and stop
666
- 4. tasks → if missing and design exists → create tasks and stop
667
-
668
- If all artifacts exist → tell the user "All planning artifacts complete. Run /opsr:apply."
669
-
670
- ## Step 3 — Create the NEXT artifact only
671
- Follow the logic from the corresponding command:
672
- - For spec: follow /opsr:spec steps for ONE capability
673
- - For design: follow /opsr:design steps
674
- - For tasks: follow /opsr:tasks steps
675
-
676
- ## Step 4 — Show progress
677
- After creating the artifact:
678
- - Show what was created
679
- - Show what is now unlocked (next in dependency chain)
680
- - Suggest: "Run \`/opsr:continue <change-name>\` to create the next artifact."
681
- `,
164
+ ${pointerTail("opensddrag-continue")}`,
682
165
  },
683
166
 
684
167
  // ── /opsr:status ────────────────────────────────────────────────────────────
685
168
  {
686
169
  folder: "opsr",
687
170
  name: "status",
688
- content: `${header("/opsr:status")}## Purpose
171
+ content: `${fm("Show state of all in-progress changes")}${openCodeHeader()}## Purpose
689
172
  Show the current state of all in-progress changes for this project.
690
173
  Reads from the MCP server — no local files involved.
691
174
 
692
175
  ## Input
693
176
  $ARGUMENTS = optional change name to show details for one change. If not provided, show all.
694
-
695
- ## Step 1 — Load working context
696
- \`get_working_context(project_slug="${slug}")\`
697
-
698
- ## Step 2 — List all artifacts by type and status
699
- \`list_artifacts(type="proposal", status="draft", project_slug="${slug}")\`
700
- \`list_artifacts(type="proposal", status="active", project_slug="${slug}")\`
701
- \`list_artifacts(type="spec", status="draft", project_slug="${slug}")\`
702
- \`list_artifacts(type="design", status="draft", project_slug="${slug}")\`
703
- \`list_artifacts(type="task", status="draft", project_slug="${slug}")\`
704
- \`list_artifacts(type="task", status="active", project_slug="${slug}")\`
705
-
706
- ## Step 3 — Recall recent activity
707
- \`recall_episodes(query="recent actions in this project", project_slug="${slug}", limit=5)\`
708
-
709
- ## Step 4 — Present structured status
710
-
711
- For each active change, show:
712
- \`\`\`
713
- ## Change: <change-name>
714
- | Artifact | Status |
715
- |----------|--------|
716
- | Proposal | ✓ done |
717
- | Specs | ✓ 2/2 |
718
- | Design | ✓ done |
719
- | Tasks | 3/5 done |
720
-
721
- Current task: <task-name>
722
- Next step: /opsr:apply <change-name>
723
- \`\`\`
724
-
725
- Then show:
726
- - Recent activity (last 5 actions from episodic memory)
727
- - Suggested next command based on current state
728
- `,
177
+ ${pointerTail("opensddrag-status")}`,
729
178
  },
730
179
 
731
180
  // ── /opsr:flow ──────────────────────────────────────────────────────────────
732
181
  {
733
182
  folder: "opsr",
734
183
  name: "flow",
735
- content: `${header("/opsr:flow")}## Purpose
184
+ content: `${fm("Run the complete SDD flow end-to-end")}${openCodeHeader()}## Purpose
736
185
  Run the complete SDD flow end-to-end in a single session.
737
- ALL artifacts are saved to the database via MCP tools no local files.
186
+ ALL planning artifacts are saved to the database via MCP tools; implementation code is written locally.
738
187
 
739
188
  ## Input
740
189
  $ARGUMENTS = feature description or change name.
741
-
742
- ## PHASE 1 — Propose
743
- Follow /opsr:propose steps:
744
- 1. \`search_semantic(query="$ARGUMENTS", project_slug="${slug}")\` — check for duplicates
745
- 2. Compose proposal content (Why / What Changes / Capabilities / Impact)
746
- 3. \`create_artifact(name="<change-name>-proposal", type="proposal", content="...", project_slug="${slug}")\`
747
-
748
- ## PHASE 2 — Spec
749
- Follow /opsr:spec steps for each capability in the proposal:
750
- 4. For each capability: compose spec (Purpose / Requirements with SHALL / Scenarios with WHEN-THEN)
751
- 5. \`create_artifact(name="<change-name>-<capability>-spec", type="spec", content="...", project_slug="${slug}")\`
752
- 6. \`link_artifacts(source_name="<spec>", target_name="<proposal>", relationship_type="implements", project_slug="${slug}")\`
753
- 7. \`validate_artifact(name="<spec>", project_slug="${slug}")\` — fix errors before continuing
754
-
755
- ## PHASE 3 — Design
756
- Follow /opsr:design steps:
757
- 8. Read all specs just created
758
- 9. Compose design (Context / Goals / Decisions / Architecture / Risks / Migration)
759
- 10. \`create_artifact(name="<change-name>-design", type="design", content="...", project_slug="${slug}")\`
760
- 11. \`link_artifacts(source_name="<design>", target_name="<proposal>", relationship_type="depends_on", project_slug="${slug}")\`
761
-
762
- ## PHASE 4 — Tasks
763
- Follow /opsr:tasks steps:
764
- 12. Read proposal, all specs, and design from database
765
- 13. For each task: \`create_artifact(name="<change-name>-task-<N>", type="task", content="...", project_slug="${slug}")\`
766
- 14. \`link_artifacts(source_name="<task>", target_name="<spec>", relationship_type="implements", project_slug="${slug}")\`
767
-
768
- ## PHASE 5 — Apply (repeat for each task in order)
769
- Follow /opsr:apply steps:
770
- 15. Read ALL planning artifacts as context (proposal + specs + design)
771
- 16. \`update_artifact(name="<task>", status="active", project_slug="${slug}")\`
772
- 17. Implement the task against its acceptance criteria
773
- 18. \`update_artifact(name="<task>", status="archived", project_slug="${slug}")\`
774
- 19. \`record_trace(action="apply_task", result_summary="Completed: <task>", project_slug="${slug}")\`
775
-
776
- ## PHASE 6 — Archive
777
- Follow /opsr:archive steps:
778
- 20. Sync delta specs if any
779
- 21. \`update_artifact(name="<all artifacts>", status="archived", project_slug="${slug}")\`
780
- 22. \`record_trace(action="complete_flow", result_summary="Completed: $ARGUMENTS", project_slug="${slug}")\`
781
- `,
190
+ ${pointerTail("opensddrag-flow")}`,
782
191
  },
783
192
 
784
193
  // ── /opsr:search ────────────────────────────────────────────────────────────
785
194
  {
786
195
  folder: "opsr",
787
196
  name: "search",
788
- content: `${header("/opsr:search")}## Purpose
197
+ content: `${fm("Semantic search over specs and past work")}${openCodeHeader()}## Purpose
789
198
  Search the SDD knowledge base using semantic similarity (pgvector).
790
199
  Use this BEFORE starting any new work to find existing specs, decisions, and past implementations.
791
200
 
792
201
  ## Input
793
202
  $ARGUMENTS = natural language search query.
203
+ ${pointerTail("opensddrag-search")}`,
204
+ },
794
205
 
795
- ## Step 1 — Search this project
796
- \`search_semantic(query="$ARGUMENTS", project_slug="${slug}", limit=5)\`
797
-
798
- ## Step 2 — If no relevant results, search all projects
799
- \`search_semantic(query="$ARGUMENTS", project_slug="*", limit=5)\`
800
-
801
- ## Step 3 Recall past actions related to the query
802
- \`recall_episodes(query="$ARGUMENTS", project_slug="${slug}", limit=3)\`
803
-
804
- ## Step 4 — Present results clearly
805
- For each result: name, type, status, and a content excerpt (first 200 chars).
806
- Group by: this project / other projects / past actions.
206
+ // ── /opsr:harness ───────────────────────────────────────────────────────────
207
+ {
208
+ folder: "opsr",
209
+ name: "harness",
210
+ content: `${fm("Manage persistent project rules (add, list, disable)")}${openCodeHeader()}## Purpose
211
+ Manage project harness rules: add new rules, list existing rules, and disable rules that are no longer needed.
212
+ Harness rules are persistent behavioral constraints injected into every agent session and surfaced as phase-gate checklists at spec/apply/verify/archive.
807
213
 
808
- ## Step 5 — Offer to read the full artifact
809
- \`read_artifact(name="<artifact-name>", project_slug="${slug}")\`
810
- `,
214
+ ## Input
215
+ $ARGUMENTS = one of: \`add\` (followed by rule fields or a natural-language description), \`list\` (show all rules), or \`disable <rule-name>\` (soft-delete by name). If empty, show the current rules list and ask.
216
+ ${pointerTail("opensddrag-harness")}`,
811
217
  },
812
218
  ];
813
- }
219
+ }