opensddrag 0.1.0 → 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.
@@ -6,7 +6,8 @@ export function getCommands(slug, serverUrl) {
6
6
  */
7
7
  const artifactHeader = (name) => `> **IMPORTANT — ${name}**
8
8
  > This command requires the **\`opensddrag\`** MCP server (${serverUrl}), configured in \`.mcp.json\`.
9
- > 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\`
9
+ > 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\`, \`get_harness_checklist\`
10
+
10
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."
11
12
  > All artifact reads/writes go through these MCP tools. DO NOT create local files. DO NOT write markdown to disk.
12
13
  > **project_slug for every call: \`${slug}\`**
@@ -22,12 +23,67 @@ export function getCommands(slug, serverUrl) {
22
23
  */
23
24
  const implementHeader = (name) => `> **IMPORTANT — ${name}**
24
25
  > This command requires the **\`opensddrag\`** MCP server (${serverUrl}), configured in \`.mcp.json\`.
25
- > MCP tools provided by this server: \`read_artifact\`, \`list_artifacts\`, \`update_artifact\`, \`get_relationships\`, \`search_semantic\`, \`recall_episodes\`, \`get_working_context\`, \`update_working_context\`, \`record_trace\`
26
+ > MCP tools provided by this server: \`read_artifact\`, \`list_artifacts\`, \`update_artifact\`, \`get_relationships\`, \`search_semantic\`, \`recall_episodes\`, \`get_working_context\`, \`update_working_context\`, \`record_trace\`, \`get_harness_checklist\`
26
27
  > **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."
27
28
  > SDD planning artifacts are read/traced via these MCP tools. Code implementation writes local files using Edit, Write, Bash — this is expected and required.
28
29
  > **project_slug for every MCP call: \`${slug}\`**
29
30
 
30
31
  ---
32
+ `;
33
+
34
+ /**
35
+ * Header for harness-management commands (harness).
36
+ * Project rules are stored in the MCP server's project_rules table.
37
+ * No local file writes — all persistence is via the harness MCP tools.
38
+ */
39
+ const harnessHeader = (name) => `> **IMPORTANT — ${name}**
40
+ > This command requires the **\`opensddrag\`** MCP server (${serverUrl}), configured in \`.mcp.json\`.
41
+ > MCP tools provided by this server: \`add_rule\`, \`list_rules\`, \`get_harness_checklist\`, \`get_working_context\`, \`record_trace\`
42
+ > **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."
43
+ > Harness rules are persisted in the MCP server's database. Do NOT write rule definitions to local files.
44
+ > **project_slug for every call: \`${slug}\`**
45
+
46
+ ---
47
+ `;
48
+
49
+ /**
50
+ * Reusable step block that calls `get_harness_checklist(trigger=...)` and
51
+ * presents the results as a phase-gate checklist. Injected into `/opsr:apply`,
52
+ * `/opsr:verify`, `/opsr:archive`, and `/opsr:spec` per spec
53
+ * `harness-engineering-harness-checklist-spec` (REQ-002, REQ-003).
54
+ *
55
+ * Behavior:
56
+ * - If the checklist is empty, print "No harness rules for this trigger." and
57
+ * continue normally.
58
+ * - If the checklist has error-severity rules, the agent MUST confirm each
59
+ * one is satisfied before proceeding to the next step.
60
+ * - Warning-severity rules are presented as advisory (SHOULD complete).
61
+ *
62
+ * @param {string} trigger - One of: "on_apply", "on_verify", "on_archive", "on_spec"
63
+ * @param {string} gateLabel - Short human-readable label for the gate, e.g. "Marking task archived"
64
+ * @returns {string} Markdown step content
65
+ */
66
+ const harnessChecklistStep = (trigger, gateLabel) => `## Step — Harness checklist (${trigger})
67
+ Call MCP tool to load all enabled harness rules for the \`${trigger}\` trigger:
68
+ \`get_harness_checklist(trigger="${trigger}", project_slug="${slug}")\`
69
+
70
+ Process the response as follows:
71
+ - **If the result is an empty array \`[]\`** → output "No harness rules for this trigger." and continue to the next step.
72
+ - **If any rule has \`severity="error"\`** → present it as:
73
+ \`\`\`
74
+ MUST complete before proceeding (${gateLabel}):
75
+ - [<name>] <instruction>
76
+ \`\`\`
77
+ Then \`STOP\` and wait for the agent/user to confirm each error-severity rule has been satisfied before continuing.
78
+ - **If any rule has \`severity="warning"\`** → present it as:
79
+ \`\`\`
80
+ SHOULD complete:
81
+ - [<name>] <instruction>
82
+ \`\`\`
83
+ These are advisory; proceed if the agent judges them satisfied, otherwise complete them first.
84
+ - **If any rule has \`severity="info"\`** → present it inline as "Info: [<name>] <instruction>"; proceed normally.
85
+ - Rules are returned sorted error-first then by name; preserve that order when displaying.
86
+ - This step must run BEFORE the next phase-gate step (archiving the task, finalizing verification, archiving change artifacts, or saving the spec to the database).
31
87
 
32
88
  `;
33
89
 
@@ -242,6 +298,7 @@ If no main spec → create BOTH:
242
298
  - TO: \`### Requirement: New Name\`
243
299
  \`\`\`
244
300
 
301
+ ${harnessChecklistStep("on_spec", "Saving specs to the database")}
245
302
  ## Step 4 — Save each spec to the database
246
303
  For each capability spec:
247
304
  \`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}")\`
@@ -425,6 +482,7 @@ For each acceptance criterion (REQ-NNN) in the task:
425
482
  - Confirm the implementation satisfies the requirement
426
483
  - Verify no spec scenarios are broken
427
484
 
485
+ ${harnessChecklistStep("on_apply", "Marking task archived")}
428
486
  ## Step 7 — Mark task as done in database
429
487
  \`update_artifact(name="<task-name>", status="archived", project_slug="${slug}")\`
430
488
 
@@ -475,6 +533,7 @@ For each decision:
475
533
  - Check if the implementation follows the chosen approach
476
534
  - If implementation deviates from a decision → **SUGGESTION: Possible deviation from design**
477
535
 
536
+ ${harnessChecklistStep("on_verify", "Declaring verification complete")}
478
537
  ## Step 5 — Generate report
479
538
  Output a structured report:
480
539
 
@@ -600,6 +659,7 @@ If delta specs exist:
600
659
  - If yes → execute <opsr:sync logic for each delta spec
601
660
  - If no → archive without syncing
602
661
 
662
+ ${harnessChecklistStep("on_archive", "Archiving change artifacts")}
603
663
  ## Step 5 — Archive all change artifacts
604
664
  For each artifact in this change (proposal, all specs, design, all tasks):
605
665
  \`update_artifact(name="<artifact-name>", status="archived", metadata={"archived_at": "<ISO timestamp>", "change_name": "<change-name>"}, project_slug="${slug}")\`
@@ -831,6 +891,134 @@ Group by: this project / other projects / past actions.
831
891
 
832
892
  ## Step 5 — Offer to read the full artifact
833
893
  \`read_artifact(name="<artifact-name>", project_slug="${slug}")\`
894
+ `,
895
+ },
896
+
897
+ // ── <opsr:harness ───────────────────────────────────────────────────────────
898
+ {
899
+ folder: "opsr",
900
+ name: "harness",
901
+ content: `${harnessHeader("/opsr:harness")}## Purpose
902
+ Manage project harness rules: add new rules, list existing rules, and disable rules that are no longer needed.
903
+ 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\`.
904
+
905
+ ## Input
906
+ $ARGUMENTS = one of:
907
+ - \`add\` — followed by rule fields or a natural-language description
908
+ - \`list\` — show all rules for this project
909
+ - \`disable <rule-name>\` — soft-delete a rule by name
910
+
911
+ If $ARGUMENTS is empty, show the current rules list and ask what the user wants to do.
912
+
913
+ ## Supported rule fields
914
+
915
+ | Field | Values |
916
+ |-------|--------|
917
+ | \`name\` | kebab-case slug, unique per project |
918
+ | \`trigger\` | \`always\` (every session) / \`on_apply\` / \`on_verify\` / \`on_archive\` / \`on_spec\` |
919
+ | \`category\` | \`architecture\` / \`naming\` / \`forbidden\` / \`doc-sync\` / \`verification\` |
920
+ | \`severity\` | \`error\` (MUST satisfy) / \`warning\` (SHOULD satisfy) / \`info\` (advisory) |
921
+ | \`instruction\` | free-text rule the agent must follow |
922
+ | \`metadata\` | optional JSON |
923
+ | \`enabled\` | \`true\` (default) / \`false\` (soft-delete) |
924
+
925
+ ## Step 1 — Parse the operation
926
+
927
+ If $ARGUMENTS starts with \`add\`:
928
+ → Go to **Step 2A — Add**
929
+
930
+ If $ARGUMENTS starts with \`list\`:
931
+ → Go to **Step 2B — List**
932
+
933
+ If $ARGUMENTS starts with \`disable <name>\`:
934
+ → Go to **Step 2C — Disable**
935
+
936
+ If $ARGUMENTS is empty:
937
+ → Call \`list_rules(project_slug="${slug}")\` and show the current state. Ask the user what they want to do.
938
+
939
+ ## Step 2A — Add a rule
940
+
941
+ If the user provided explicit fields after \`add\` (e.g. \`add name=repo-pattern trigger=always category=architecture severity=error instruction="..."\`), use them as-is.
942
+
943
+ Otherwise, ask the user for each field. **You can infer sensible defaults from natural language:**
944
+ - "always update CHANGELOG when applying" → trigger=\`on_apply\`, category=\`doc-sync\`, severity=\`warning\`
945
+ - "never do X" → trigger=\`always\`, category=\`forbidden\`, severity=\`error\`
946
+ - "use Y pattern" → trigger=\`always\`, category=\`architecture\`, severity=\`warning\`
947
+
948
+ **Show the inferred values and ask for confirmation** before calling \`add_rule\`.
949
+
950
+ Then call:
951
+
952
+ \`\`\`
953
+ add_rule(
954
+ name: "<kebab-case>",
955
+ trigger: "<always|on_apply|on_verify|on_archive|on_spec>",
956
+ category: "<architecture|naming|forbidden|doc-sync|verification>",
957
+ severity: "<error|warning|info>",
958
+ instruction: "<text>",
959
+ project_slug:"${slug}",
960
+ enabled: true
961
+ )
962
+ \`\`\`
963
+
964
+ Confirm to the user:
965
+ "Rule '<name>' added. It will [be injected into every working context | be checked during /opsr:<trigger> when the phase completes]."
966
+
967
+ Then record the operation:
968
+ \`record_trace(action="add_rule", result_summary="Added harness rule: <name>", project_slug="${slug}")\`
969
+
970
+ ## Step 2B — List rules
971
+
972
+ Call:
973
+
974
+ \`list_rules(project_slug="${slug}", enabled_only=true)\`
975
+
976
+ Present the results **grouped by trigger**, in this order:
977
+
978
+ \`\`\`
979
+ ### Always (loaded at session start)
980
+ - [<category>:<severity>] <name> — <truncated instruction (max 80 chars)>
981
+
982
+ ### On Apply (checked during /opsr:apply)
983
+ - ...
984
+
985
+ ### On Verify (checked during /opsr:verify)
986
+ - ...
987
+
988
+ ### On Archive (checked during /opsr:archive)
989
+ - ...
990
+
991
+ ### On Spec (checked during /opsr:spec)
992
+ - ...
993
+ \`\`\`
994
+
995
+ If the result list is empty, respond:
996
+ "No harness rules defined for this project. Run \`/opsr:harness add\` to create the first rule."
997
+
998
+ If rules exist in only some sections, show "(none)" for empty sections.
999
+
1000
+ ## Step 2C — Disable a rule
1001
+
1002
+ Extract the rule name from $ARGUMENTS (the token after \`disable\`).
1003
+
1004
+ Call:
1005
+
1006
+ \`add_rule(name: "<name>", enabled: false, project_slug: "${slug}")\`
1007
+
1008
+ (You don't need to pass the other fields — \`add_rule\` is an upsert keyed on \`(project_id, name)\` and will set the existing rule's \`enabled\` flag to \`false\`.)
1009
+
1010
+ Confirm:
1011
+ "Rule '<name>' disabled. It will no longer appear in checklists or session context. Re-add with the same name to re-enable."
1012
+
1013
+ Then record:
1014
+ \`record_trace(action="disable_rule", result_summary="Disabled harness rule: <name>", project_slug="${slug}")\`
1015
+
1016
+ ## Notes
1017
+
1018
+ - The same \`add_rule\` MCP call is used for create, update, and soft-delete — it is idempotent on \`(project_id, name)\`.
1019
+ - Disabled rules are preserved in the database and can be re-enabled by calling \`add_rule\` with the same \`name\` and \`enabled=true\`.
1020
+ - Rules are project-scoped — they never leak across projects.
1021
+ - The OpenCode equivalent of this command is the \`opensddrag-harness\` skill, which calls the same MCP tools.
834
1022
  `,
835
1023
  },
836
1024
  ];
@@ -1,28 +1,21 @@
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.
5
6
  */
6
7
 
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}\`**
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: `${header("/opsr:propose")}## Purpose
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: `${header("/opsr:spec")}## Purpose
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: `${header("/opsr:design")}## Purpose
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: `${header("/opsr:tasks")}## Purpose
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: `${header("/opsr:apply")}## Purpose
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: `${header("/opsr:verify")}## Purpose
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: `${header("/opsr:sync")}## Purpose
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: `${header("/opsr:archive")}## Purpose
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: `${header("/opsr:explore")}## Purpose
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: `${header("/opsr:continue")}## Purpose
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: `${header("/opsr:status")}## Purpose
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: `${header("/opsr:flow")}## Purpose
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: `${header("/opsr:search")}## Purpose
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
  ];