opensddrag 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +87 -0
- package/package.json +1 -1
- package/src/commands/init.js +61 -46
- package/src/commands/status.js +7 -10
- package/src/config.js +53 -0
- package/src/templates/commands/index.js +190 -2
- package/src/templates/commands/opencode.js +139 -26
- package/src/templates/skill-md.js +180 -0
- package/src/templates/skills/index.js +208 -13
|
@@ -1,28 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* OpenCode command templates
|
|
3
|
-
*
|
|
4
|
-
*
|
|
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.
|
|
5
6
|
*/
|
|
6
7
|
|
|
7
|
-
export function getOpenCodeCommands(slug,
|
|
8
|
-
const
|
|
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}\`**
|
|
8
|
+
export function getOpenCodeCommands(slug, _serverUrl) {
|
|
9
|
+
const fm = (description) => `---\ndescription: ${description}\n---\n\n`;
|
|
14
10
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
`;
|
|
11
|
+
const openCodeHeader = () => `> **project_slug for every call:** \`${slug}\`\n\n---\n\n\n`;
|
|
19
12
|
|
|
20
13
|
return [
|
|
21
14
|
// ── /opsr:propose ──────────────────────────────────────────────────────────
|
|
22
15
|
{
|
|
23
16
|
folder: "opsr",
|
|
24
17
|
name: "propose",
|
|
25
|
-
content: `${
|
|
18
|
+
content: `${fm("Create a named change proposal")}${openCodeHeader()}## Purpose
|
|
26
19
|
Create a named change with a proposal artifact. This is the entry point for every new feature or change.
|
|
27
20
|
The proposal defines WHY, WHAT changes, WHICH capabilities are affected, and the IMPACT.
|
|
28
21
|
After this command, /opsr:spec and /opsr:design become available.
|
|
@@ -144,7 +137,7 @@ Tell the user:
|
|
|
144
137
|
{
|
|
145
138
|
folder: "opsr",
|
|
146
139
|
name: "spec",
|
|
147
|
-
content: `${
|
|
140
|
+
content: `${fm("Write capability specs with requirements and scenarios")}${openCodeHeader()}## Purpose
|
|
148
141
|
Create one or more spec artifacts for the capabilities listed in a proposal.
|
|
149
142
|
Each capability in "New Capabilities" or "Modified Capabilities" gets its own spec artifact.
|
|
150
143
|
Specs use SHALL/MUST language and must have Scenarios with WHEN/THEN format.
|
|
@@ -245,7 +238,7 @@ Fix any validation errors before continuing.
|
|
|
245
238
|
{
|
|
246
239
|
folder: "opsr",
|
|
247
240
|
name: "design",
|
|
248
|
-
content: `${
|
|
241
|
+
content: `${fm("Document technical decisions and architecture")}${openCodeHeader()}## Purpose
|
|
249
242
|
Create a design document that captures technical decisions, architecture, trade-offs, and open questions.
|
|
250
243
|
The design must be based on the proposal and spec artifacts already in the database.
|
|
251
244
|
|
|
@@ -318,7 +311,7 @@ Tell the user: "Design saved. Run \`/opsr:tasks <change-name>\` to decompose int
|
|
|
318
311
|
{
|
|
319
312
|
folder: "opsr",
|
|
320
313
|
name: "tasks",
|
|
321
|
-
content: `${
|
|
314
|
+
content: `${fm("Break a design into atomic implementation tasks")}${openCodeHeader()}## Purpose
|
|
322
315
|
Decompose the specs and design into atomic, verifiable task artifacts.
|
|
323
316
|
Each task must map to one or more spec requirements (REQ-NNN) and be completable in under 4 hours.
|
|
324
317
|
Tasks depend on BOTH specs AND design being in the database.
|
|
@@ -361,7 +354,7 @@ Tell the user: "Tasks saved. Run \`/opsr:apply <change-name>\` to start implemen
|
|
|
361
354
|
{
|
|
362
355
|
folder: "opsr",
|
|
363
356
|
name: "apply",
|
|
364
|
-
content: `${
|
|
357
|
+
content: `${fm("Implement the next pending task")}${openCodeHeader()}## Purpose
|
|
365
358
|
Implement tasks one by one, validating each against the spec acceptance criteria before marking done.
|
|
366
359
|
Read ALL planning artifacts (proposal, specs, design) as context before implementing any task.
|
|
367
360
|
|
|
@@ -419,7 +412,7 @@ For each acceptance criterion (REQ-NNN) in the task:
|
|
|
419
412
|
{
|
|
420
413
|
folder: "opsr",
|
|
421
414
|
name: "verify",
|
|
422
|
-
content: `${
|
|
415
|
+
content: `${fm("Validate implementation against spec requirements")}${openCodeHeader()}## Purpose
|
|
423
416
|
Validate the implementation against the spec requirements and design decisions.
|
|
424
417
|
Produces a structured report with CRITICAL, WARNING, and SUGGESTION severity levels.
|
|
425
418
|
Does NOT modify any artifacts — read-only operation.
|
|
@@ -489,7 +482,7 @@ Output a structured report:
|
|
|
489
482
|
{
|
|
490
483
|
folder: "opsr",
|
|
491
484
|
name: "sync",
|
|
492
|
-
content: `${
|
|
485
|
+
content: `${fm("Merge delta specs into main specs")}${openCodeHeader()}## Purpose
|
|
493
486
|
Merge delta specs (ADDED/MODIFIED/REMOVED/RENAMED sections) into the main specs stored in the database.
|
|
494
487
|
Delta specs are created by /opsr:spec for MODIFIED capabilities.
|
|
495
488
|
After sync, the main spec reflects all changes. This is called automatically during /opsr:archive.
|
|
@@ -548,7 +541,7 @@ Tell the user which capabilities were updated.
|
|
|
548
541
|
{
|
|
549
542
|
folder: "opsr",
|
|
550
543
|
name: "archive",
|
|
551
|
-
content: `${
|
|
544
|
+
content: `${fm("Finalize and archive a completed change")}${openCodeHeader()}## Purpose
|
|
552
545
|
Finalize a completed change by archiving all its artifacts.
|
|
553
546
|
Runs verification checks, syncs delta specs to main specs, then archives everything.
|
|
554
547
|
|
|
@@ -596,7 +589,7 @@ Show summary:
|
|
|
596
589
|
{
|
|
597
590
|
folder: "opsr",
|
|
598
591
|
name: "explore",
|
|
599
|
-
content: `${
|
|
592
|
+
content: `${fm("Investigate a problem without implementing anything")}${openCodeHeader()}## Purpose
|
|
600
593
|
Think through a problem, idea, or question WITHOUT implementing anything.
|
|
601
594
|
Explore creates understanding before committing to a proposal.
|
|
602
595
|
You may create OpenSddRag artifacts to capture insights, but NEVER write application code.
|
|
@@ -644,7 +637,7 @@ When the user has enough insight to decide:
|
|
|
644
637
|
{
|
|
645
638
|
folder: "opsr",
|
|
646
639
|
name: "continue",
|
|
647
|
-
content: `${
|
|
640
|
+
content: `${fm("Create the next artifact in the SDD dependency chain")}${openCodeHeader()}## Purpose
|
|
648
641
|
Create the NEXT single artifact in the dependency chain for a change.
|
|
649
642
|
Unlike /opsr:flow which creates all artifacts, this creates ONE artifact and stops.
|
|
650
643
|
Dependency order: proposal → specs → design → tasks.
|
|
@@ -685,7 +678,7 @@ After creating the artifact:
|
|
|
685
678
|
{
|
|
686
679
|
folder: "opsr",
|
|
687
680
|
name: "status",
|
|
688
|
-
content: `${
|
|
681
|
+
content: `${fm("Show state of all in-progress changes")}${openCodeHeader()}## Purpose
|
|
689
682
|
Show the current state of all in-progress changes for this project.
|
|
690
683
|
Reads from the MCP server — no local files involved.
|
|
691
684
|
|
|
@@ -732,7 +725,7 @@ Then show:
|
|
|
732
725
|
{
|
|
733
726
|
folder: "opsr",
|
|
734
727
|
name: "flow",
|
|
735
|
-
content: `${
|
|
728
|
+
content: `${fm("Run the complete SDD flow end-to-end")}${openCodeHeader()}## Purpose
|
|
736
729
|
Run the complete SDD flow end-to-end in a single session.
|
|
737
730
|
ALL artifacts are saved to the database via MCP tools — no local files.
|
|
738
731
|
|
|
@@ -785,7 +778,7 @@ Follow /opsr:archive steps:
|
|
|
785
778
|
{
|
|
786
779
|
folder: "opsr",
|
|
787
780
|
name: "search",
|
|
788
|
-
content: `${
|
|
781
|
+
content: `${fm("Semantic search over specs and past work")}${openCodeHeader()}## Purpose
|
|
789
782
|
Search the SDD knowledge base using semantic similarity (pgvector).
|
|
790
783
|
Use this BEFORE starting any new work to find existing specs, decisions, and past implementations.
|
|
791
784
|
|
|
@@ -807,6 +800,126 @@ Group by: this project / other projects / past actions.
|
|
|
807
800
|
|
|
808
801
|
## Step 5 — Offer to read the full artifact
|
|
809
802
|
\`read_artifact(name="<artifact-name>", project_slug="${slug}")\`
|
|
803
|
+
`,
|
|
804
|
+
},
|
|
805
|
+
|
|
806
|
+
// ── /opsr:harness ───────────────────────────────────────────────────────────
|
|
807
|
+
{
|
|
808
|
+
folder: "opsr",
|
|
809
|
+
name: "harness",
|
|
810
|
+
content: `${fm("Manage persistent project rules (add, list, disable)")}${openCodeHeader()}## Purpose
|
|
811
|
+
Manage project harness rules: add new rules, list existing rules, and disable rules that are no longer needed.
|
|
812
|
+
Harness rules are persistent behavioral constraints injected into every agent session via \`get_working_context\` (for \`trigger="always"\` rules) and surfaced as phase-gate checklists via \`get_harness_checklist\`.
|
|
813
|
+
|
|
814
|
+
## Input
|
|
815
|
+
$ARGUMENTS = one of:
|
|
816
|
+
- \`add\` — followed by rule fields or a natural-language description
|
|
817
|
+
- \`list\` — show all rules for this project
|
|
818
|
+
- \`disable <rule-name>\` — soft-delete a rule by name
|
|
819
|
+
|
|
820
|
+
If $ARGUMENTS is empty, show the current rules list and ask what the user wants to do.
|
|
821
|
+
|
|
822
|
+
## Supported rule fields
|
|
823
|
+
|
|
824
|
+
| Field | Values |
|
|
825
|
+
|-------|--------|
|
|
826
|
+
| \`name\` | kebab-case slug, unique per project |
|
|
827
|
+
| \`trigger\` | \`always\` (every session) / \`on_apply\` / \`on_verify\` / \`on_archive\` / \`on_spec\` |
|
|
828
|
+
| \`category\` | \`architecture\` / \`naming\` / \`forbidden\` / \`doc-sync\` / \`verification\` |
|
|
829
|
+
| \`severity\` | \`error\` (MUST satisfy) / \`warning\` (SHOULD satisfy) / \`info\` (advisory) |
|
|
830
|
+
| \`instruction\` | free-text rule the agent must follow |
|
|
831
|
+
| \`metadata\` | optional JSON |
|
|
832
|
+
| \`enabled\` | \`true\` (default) / \`false\` (soft-delete) |
|
|
833
|
+
|
|
834
|
+
## Step 1 — Parse the operation
|
|
835
|
+
|
|
836
|
+
If $ARGUMENTS starts with \`add\`:
|
|
837
|
+
→ Go to **Step 2A — Add**
|
|
838
|
+
|
|
839
|
+
If $ARGUMENTS starts with \`list\`:
|
|
840
|
+
→ Go to **Step 2B — List**
|
|
841
|
+
|
|
842
|
+
If $ARGUMENTS starts with \`disable <name>\`:
|
|
843
|
+
→ Go to **Step 2C — Disable**
|
|
844
|
+
|
|
845
|
+
If $ARGUMENTS is empty:
|
|
846
|
+
→ Call \`list_rules(project_slug="${slug}")\` and show the current state. Ask the user what they want to do.
|
|
847
|
+
|
|
848
|
+
## Step 2A — Add a rule
|
|
849
|
+
|
|
850
|
+
If the user provided explicit fields after \`add\`, use them as-is.
|
|
851
|
+
|
|
852
|
+
Otherwise, ask the user for each field. **You can infer sensible defaults from natural language:**
|
|
853
|
+
- "always update CHANGELOG when applying" → trigger=\`on_apply\`, category=\`doc-sync\`, severity=\`warning\`
|
|
854
|
+
- "never do X" → trigger=\`always\`, category=\`forbidden\`, severity=\`error\`
|
|
855
|
+
- "use Y pattern" → trigger=\`always\`, category=\`architecture\`, severity=\`warning\`
|
|
856
|
+
|
|
857
|
+
**Show the inferred values and ask for confirmation** before calling \`add_rule\`.
|
|
858
|
+
|
|
859
|
+
Then call:
|
|
860
|
+
\`\`\`
|
|
861
|
+
add_rule(
|
|
862
|
+
name: "<kebab-case>",
|
|
863
|
+
trigger: "<always|on_apply|on_verify|on_archive|on_spec>",
|
|
864
|
+
category: "<architecture|naming|forbidden|doc-sync|verification>",
|
|
865
|
+
severity: "<error|warning|info>",
|
|
866
|
+
instruction: "<text>",
|
|
867
|
+
project_slug:"${slug}",
|
|
868
|
+
enabled: true
|
|
869
|
+
)
|
|
870
|
+
\`\`\`
|
|
871
|
+
|
|
872
|
+
Confirm to the user:
|
|
873
|
+
"Rule '<name>' added. It will [be injected into every working context | be checked during /opsr:<trigger> when the phase completes]."
|
|
874
|
+
|
|
875
|
+
Then record:
|
|
876
|
+
\`record_trace(action="add_rule", result_summary="Added harness rule: <name>", project_slug="${slug}")\`
|
|
877
|
+
|
|
878
|
+
## Step 2B — List rules
|
|
879
|
+
|
|
880
|
+
Call:
|
|
881
|
+
\`list_rules(project_slug="${slug}", enabled_only=true)\`
|
|
882
|
+
|
|
883
|
+
Present the results **grouped by trigger**, in this order:
|
|
884
|
+
|
|
885
|
+
\`\`\`
|
|
886
|
+
### Always (loaded at session start)
|
|
887
|
+
- [<category>:<severity>] <name> — <instruction (max 80 chars)>
|
|
888
|
+
|
|
889
|
+
### On Apply (checked during /opsr:apply)
|
|
890
|
+
- ...
|
|
891
|
+
|
|
892
|
+
### On Verify (checked during /opsr:verify)
|
|
893
|
+
- ...
|
|
894
|
+
|
|
895
|
+
### On Archive (checked during /opsr:archive)
|
|
896
|
+
- ...
|
|
897
|
+
|
|
898
|
+
### On Spec (checked during /opsr:spec)
|
|
899
|
+
- ...
|
|
900
|
+
\`\`\`
|
|
901
|
+
|
|
902
|
+
If the result list is empty, respond:
|
|
903
|
+
"No harness rules defined for this project. Run \`/opsr:harness add\` to create the first rule."
|
|
904
|
+
|
|
905
|
+
## Step 2C — Disable a rule
|
|
906
|
+
|
|
907
|
+
Extract the rule name from $ARGUMENTS (the token after \`disable\`).
|
|
908
|
+
|
|
909
|
+
Call:
|
|
910
|
+
\`add_rule(name: "<name>", enabled: false, project_slug: "${slug}")\`
|
|
911
|
+
|
|
912
|
+
Confirm:
|
|
913
|
+
"Rule '<name>' disabled. It will no longer appear in checklists or session context. Re-add with the same name to re-enable."
|
|
914
|
+
|
|
915
|
+
Then record:
|
|
916
|
+
\`record_trace(action="disable_rule", result_summary="Disabled harness rule: <name>", project_slug="${slug}")\`
|
|
917
|
+
|
|
918
|
+
## Notes
|
|
919
|
+
|
|
920
|
+
- The same \`add_rule\` MCP call is used for create, update, and soft-delete — it is idempotent on \`(project_id, name)\`.
|
|
921
|
+
- Disabled rules are preserved in the database and can be re-enabled by calling \`add_rule\` with the same \`name\` and \`enabled=true\`.
|
|
922
|
+
- Rules are project-scoped — they never leak across projects.
|
|
810
923
|
`,
|
|
811
924
|
},
|
|
812
925
|
];
|
|
@@ -1,3 +1,183 @@
|
|
|
1
|
+
export function getHarnessSkill({ slug, serverUrl }) {
|
|
2
|
+
// SKILL.md for the `opensddrag-harness` skill — installed into
|
|
3
|
+
// .claude/skills/opensddrag-harness/ and .agents/skills/opensddrag-harness/
|
|
4
|
+
// by `opensddrag init`. Drives the /opsr:harness slash command behaviorally
|
|
5
|
+
// for both Claude Code and OpenCode, using only the standard MCP tools
|
|
6
|
+
// (add_rule, list_rules, get_harness_checklist). No direct DB access, no
|
|
7
|
+
// local file writes for rule storage — rules are persisted via the MCP
|
|
8
|
+
// server's `project_rules` table.
|
|
9
|
+
return `---
|
|
10
|
+
name: opensddrag-harness
|
|
11
|
+
description: Manage persistent project rules — add, list, and disable behavioral constraints
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# OpenSddRag — Harness
|
|
15
|
+
|
|
16
|
+
This project is connected to the OpenSddRag Harness (${serverUrl}).
|
|
17
|
+
The Harness layer manages **project rules**: persistent, per-project behavioral
|
|
18
|
+
constraints that are automatically injected into every agent session.
|
|
19
|
+
|
|
20
|
+
## Project slug: \`${slug}\`
|
|
21
|
+
|
|
22
|
+
Always pass \`project_slug: "${slug}"\` to scope rule operations to this project.
|
|
23
|
+
|
|
24
|
+
## When to use
|
|
25
|
+
|
|
26
|
+
- Before starting any new feature, ask: "Are there harness rules I should be aware of?"
|
|
27
|
+
\`get_working_context(project_slug="${slug}")\` will return any \`trigger="always"\` rules
|
|
28
|
+
automatically — read them first.
|
|
29
|
+
- Use \`/opsr:harness\` (Claude Code) or invoke this skill (OpenCode) to:
|
|
30
|
+
- **add** a new rule (architecture, naming, forbidden, doc-sync, verification)
|
|
31
|
+
- **list** all rules for the project, grouped by trigger
|
|
32
|
+
- **disable** a rule (soft-delete — re-enable by re-adding with the same name)
|
|
33
|
+
|
|
34
|
+
## Available operations
|
|
35
|
+
|
|
36
|
+
### add — create or update a project rule
|
|
37
|
+
|
|
38
|
+
Call the \`add_rule\` MCP tool. Required arguments:
|
|
39
|
+
|
|
40
|
+
\`\`\`
|
|
41
|
+
add_rule(
|
|
42
|
+
name: "<kebab-case-name>",
|
|
43
|
+
trigger: "always" | "on_apply" | "on_verify" | "on_archive" | "on_spec",
|
|
44
|
+
category: "architecture" | "naming" | "forbidden" | "doc-sync" | "verification",
|
|
45
|
+
severity: "error" | "warning" | "info", // default: "warning"
|
|
46
|
+
instruction: "<free-text rule the agent must follow>",
|
|
47
|
+
project_slug:"${slug}",
|
|
48
|
+
enabled: true, // default: true (set false to soft-delete)
|
|
49
|
+
metadata: { ... } // optional, free-form JSON
|
|
50
|
+
)
|
|
51
|
+
\`\`\`
|
|
52
|
+
|
|
53
|
+
When the user provides a rule in natural language, infer the fields:
|
|
54
|
+
- "always update X when applying" → trigger=\`on_apply\`, category=\`doc-sync\`, severity=\`warning\`
|
|
55
|
+
- "never do Y" → trigger=\`always\`, category=\`forbidden\`, severity=\`error\`
|
|
56
|
+
- "use Z pattern in this project" → trigger=\`always\`, category=\`architecture\`, severity=\`warning\`
|
|
57
|
+
|
|
58
|
+
**Example 1 — architecture rule (always):**
|
|
59
|
+
\`\`\`
|
|
60
|
+
add_rule(
|
|
61
|
+
name: "repo-pattern-required",
|
|
62
|
+
trigger: "always",
|
|
63
|
+
category: "architecture",
|
|
64
|
+
severity: "error",
|
|
65
|
+
instruction: "All data access must go through a repository class. Do not call the ORM or DB driver directly from route handlers or service classes.",
|
|
66
|
+
project_slug:"${slug}"
|
|
67
|
+
)
|
|
68
|
+
\`\`\`
|
|
69
|
+
|
|
70
|
+
**Example 2 — doc-sync rule (on_apply):**
|
|
71
|
+
\`\`\`
|
|
72
|
+
add_rule(
|
|
73
|
+
name: "update-changelog-on-apply",
|
|
74
|
+
trigger: "on_apply",
|
|
75
|
+
category: "doc-sync",
|
|
76
|
+
severity: "warning",
|
|
77
|
+
instruction: "When applying a task that ships a user-visible change, add a one-line entry to CHANGELOG.md under the unreleased section before marking the task complete.",
|
|
78
|
+
project_slug:"${slug}"
|
|
79
|
+
)
|
|
80
|
+
\`\`\`
|
|
81
|
+
|
|
82
|
+
Confirm with the user after adding:
|
|
83
|
+
"Rule '<name>' added. It will be [injected at every session start | checked during /opsr:apply | ...]."
|
|
84
|
+
|
|
85
|
+
### list — show all rules for this project
|
|
86
|
+
|
|
87
|
+
Call the \`list_rules\` MCP tool:
|
|
88
|
+
|
|
89
|
+
\`\`\`
|
|
90
|
+
list_rules(project_slug="${slug}", enabled_only=true)
|
|
91
|
+
\`\`\`
|
|
92
|
+
|
|
93
|
+
Group the results by \`trigger\` in the output:
|
|
94
|
+
|
|
95
|
+
\`\`\`
|
|
96
|
+
### Always (loaded at session start)
|
|
97
|
+
- [architecture:error] repo-pattern-required — All data access must go through...
|
|
98
|
+
|
|
99
|
+
### On Apply (checked during /opsr:apply)
|
|
100
|
+
- [doc-sync:warning] update-changelog-on-apply — When applying a task...
|
|
101
|
+
|
|
102
|
+
### On Verify (checked during /opsr:verify)
|
|
103
|
+
- (none)
|
|
104
|
+
|
|
105
|
+
### On Archive (checked during /opsr:archive)
|
|
106
|
+
- (none)
|
|
107
|
+
|
|
108
|
+
### On Spec (checked during /opsr:spec)
|
|
109
|
+
- (none)
|
|
110
|
+
\`\`\`
|
|
111
|
+
|
|
112
|
+
If the result list is empty, respond:
|
|
113
|
+
"No harness rules defined for this project. Run \`/opsr:harness add\` to create the first rule."
|
|
114
|
+
|
|
115
|
+
### disable — soft-delete a rule
|
|
116
|
+
|
|
117
|
+
Call the \`add_rule\` MCP tool with the same \`name\` and \`enabled=false\`:
|
|
118
|
+
|
|
119
|
+
\`\`\`
|
|
120
|
+
add_rule(name: "<rule-name>", enabled: false, project_slug: "${slug}")
|
|
121
|
+
\`\`\`
|
|
122
|
+
|
|
123
|
+
This is a soft-delete: the rule is preserved in the database with \`enabled=false\`
|
|
124
|
+
and will no longer appear in \`list_rules\` (default \`enabled_only=true\`) or in
|
|
125
|
+
\`get_working_context\` injection. To re-enable, call \`add_rule\` with the same
|
|
126
|
+
name and \`enabled=true\`.
|
|
127
|
+
|
|
128
|
+
Confirm with the user:
|
|
129
|
+
"Rule '<name>' disabled. It will no longer appear in checklists or session context."
|
|
130
|
+
|
|
131
|
+
## Phase-gate checklist — get_harness_checklist
|
|
132
|
+
|
|
133
|
+
When the user runs \`/opsr:apply\`, \`/opsr:verify\`, \`/opsr:archive\`, or
|
|
134
|
+
\`/opsr:spec\`, the corresponding slash command will call:
|
|
135
|
+
|
|
136
|
+
\`\`\`
|
|
137
|
+
get_harness_checklist(trigger="on_apply"|"on_verify"|"on_archive"|"on_spec", project_slug="${slug}")
|
|
138
|
+
\`\`\`
|
|
139
|
+
|
|
140
|
+
…to fetch rules that must be satisfied at that phase gate. The response is an
|
|
141
|
+
array of {name, category, severity, instruction} objects ordered by severity
|
|
142
|
+
(error first) then name. Rules with \`severity="error"\` MUST be completed before
|
|
143
|
+
the phase is declared done; \`severity="warning"\` rules SHOULD be addressed.
|
|
144
|
+
|
|
145
|
+
You do not need to call this directly — the slash commands invoke it. But you
|
|
146
|
+
can use it from this skill if the user asks "what rules apply to apply?".
|
|
147
|
+
|
|
148
|
+
## Memory of rule operations
|
|
149
|
+
|
|
150
|
+
Every add / disable operation should be recorded in episodic memory:
|
|
151
|
+
|
|
152
|
+
\`\`\`
|
|
153
|
+
record_trace(action="add_rule"|"disable_rule", result_summary="Added/disabled rule: <name>", project_slug="${slug}")
|
|
154
|
+
\`\`\`
|
|
155
|
+
|
|
156
|
+
## MCP tools used
|
|
157
|
+
|
|
158
|
+
| Tool | Purpose |
|
|
159
|
+
|------|---------|
|
|
160
|
+
| \`add_rule\` | Upsert a rule (create, update, or soft-delete) |
|
|
161
|
+
| \`list_rules\` | List rules with optional filters |
|
|
162
|
+
| \`get_harness_checklist\` | Fetch phase-gate rules for apply/verify/archive/spec |
|
|
163
|
+
| \`get_working_context\` | Already returns trigger="always" rules automatically |
|
|
164
|
+
| \`record_trace\` | Log harness operations to episodic memory |
|
|
165
|
+
|
|
166
|
+
## Important rules for this skill
|
|
167
|
+
|
|
168
|
+
- **Never write rule data to local files** — all rules live in the \`project_rules\` table.
|
|
169
|
+
- **Never translate or modify the user's rule instruction** — store it verbatim.
|
|
170
|
+
- **Always confirm with the user before calling \`add_rule\`** for new rules, especially when inferring fields from natural language.
|
|
171
|
+
- **Soft-delete is the only way to "remove" a rule** — re-adding with the same name restores it.
|
|
172
|
+
`;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export function getOpenCodeHarnessSkill({ slug, serverUrl }) {
|
|
176
|
+
const full = getHarnessSkill({ slug, serverUrl });
|
|
177
|
+
// OpenCode auto-discovers tools from opencode.json — the table is noise.
|
|
178
|
+
return full.replace(/\n## MCP tools used\n[\s\S]*?(?=\n## |\n$)/, '\n');
|
|
179
|
+
}
|
|
180
|
+
|
|
1
181
|
export function renderSkillMd({ slug, serverUrl }) {
|
|
2
182
|
return `# OpenSddRag — SDD + Harness
|
|
3
183
|
|