Skip to content

Commit 604ed52

Browse files
authored
Merge pull request #66 from dmoliveira/my_opencode-e9-rules-ops
feat: add rules command operations and diagnostics
2 parents 3c18193 + 85e7930 commit 604ed52

File tree

10 files changed

+500
-7
lines changed

10 files changed

+500
-7
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ All notable changes to this project are documented in this file.
2929
- Added keyword mode controls for global enable/disable and per-keyword toggles (`disable-keyword` / `enable-keyword`) with persisted config state.
3030
- Added `instructions/conditional_rules_schema.md` defining rule frontmatter schema, discovery precedence, conflict resolution, and validation requirements for Epic 9 Task 9.1.
3131
- Added `scripts/rules_engine.py` implementing frontmatter parsing, layered rule discovery, path-based matching, deterministic precedence sorting, and duplicate-id conflict reporting.
32+
- Added `scripts/rules_command.py` with `/rules status`, `/rules explain`, per-rule disable/enable controls, and `/rules doctor` diagnostics.
3233

3334
### Changes
3435
- Documented extension evaluation outcomes and when each tool is the better fit.
@@ -58,6 +59,7 @@ All notable changes to this project are documented in this file.
5859
- Added `/keyword-mode doctor --json` diagnostics and integrated keyword subsystem health into unified `/doctor` checks.
5960
- Expanded keyword mode verification for false-positive resistance (partial words and code-literal contexts) and opt-out/toggle smoke scenarios.
6061
- Expanded selftest coverage for conditional rule discovery and effective-stack resolution behavior.
62+
- Added `/doctor` rules subsystem integration and expanded install/selftest coverage for rules command workflows.
6163

6264
## v0.2.0 - 2026-02-12
6365

IMPLEMENTATION_ROADMAP.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ Use this map to avoid overlapping implementations.
4545
| E6 | Session Intelligence and Resume Tooling | paused | Medium | E2 | TBD | Resume when core orchestration stabilizes |
4646
| E7 | Tmux Visual Multi-Agent Mode | postponed | Low | E2 | TBD | Optional power-user feature |
4747
| E8 | Keyword-Triggered Execution Modes | done | High | E1, E4 | bd-302, bd-2fb, bd-2zq, bd-3dp | Fast power-mode activation from prompt text |
48-
| E9 | Conditional Rules Injector | in_progress | High | E1 | bd-1q8, bd-3rj | Enforce project conventions with scoped rules |
48+
| E9 | Conditional Rules Injector | in_progress | High | E1 | bd-1q8, bd-3rj, bd-fo8 | Enforce project conventions with scoped rules |
4949
| E10 | Auto Slash Command Detector | paused | Medium | E1, E8 | TBD | Resume only if intent precision stays high in prototypes |
5050
| E11 | Context-Window Resilience Toolkit | planned | High | E4 | TBD | Improve long-session stability and recovery |
5151
| E12 | Provider/Model Fallback Visibility | planned | Medium | E5 | TBD | Explain why model routing decisions happen |
@@ -422,10 +422,11 @@ Every command-oriented epic must ship all of the following:
422422
- [x] Subtask 9.2.2: Match rules by file path and operation context
423423
- [x] Subtask 9.2.3: Inject effective rule set into execution context
424424
- [x] Notes: Added `scripts/rules_engine.py` with frontmatter parsing, layered discovery, deterministic precedence sorting, duplicate-id conflict reporting, and effective rule stack resolution helpers.
425-
- [ ] Task 9.3: Operations and diagnostics
426-
- [ ] Subtask 9.3.1: Add `/rules status` and `/rules explain <path>` commands
427-
- [ ] Subtask 9.3.2: Add per-rule disable list in config
428-
- [ ] Subtask 9.3.3: Add doctor output for rule source and conflicts
425+
- [x] Task 9.3: Operations and diagnostics
426+
- [x] Subtask 9.3.1: Add `/rules status` and `/rules explain <path>` commands
427+
- [x] Subtask 9.3.2: Add per-rule disable list in config
428+
- [x] Subtask 9.3.3: Add doctor output for rule source and conflicts
429+
- [x] Notes: Added `scripts/rules_command.py` with status/explain/disable-id/enable-id/doctor workflows, wired `/doctor` integration for rules diagnostics, and added command aliases/install smoke coverage.
429430
- [ ] Task 9.4: Verification and docs
430431
- [ ] Subtask 9.4.1: Add tests for glob matching and precedence
431432
- [ ] Subtask 9.4.2: Add docs with examples for team rule packs

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ install-test: ## Run installer smoke test in temp HOME
5656
if [ -f "$$TMP_HOME/.config/opencode/my_opencode/scripts/hooks_command.py" ]; then HOME="$$TMP_HOME" python3 "$$TMP_HOME/.config/opencode/my_opencode/scripts/hooks_command.py" status; HOME="$$TMP_HOME" python3 "$$TMP_HOME/.config/opencode/my_opencode/scripts/hooks_command.py" enable; HOME="$$TMP_HOME" python3 "$$TMP_HOME/.config/opencode/my_opencode/scripts/hooks_command.py" disable-hook error-hints; HOME="$$TMP_HOME" python3 "$$TMP_HOME/.config/opencode/my_opencode/scripts/hooks_command.py" run error-hints --json '{"command":"git status","exit_code":128,"stderr":"fatal: not a git repository"}'; HOME="$$TMP_HOME" python3 "$$TMP_HOME/.config/opencode/my_opencode/scripts/hooks_command.py" enable-hook error-hints; HOME="$$TMP_HOME" python3 "$$TMP_HOME/.config/opencode/my_opencode/scripts/hooks_command.py" doctor --json; fi; \
5757
if [ -f "$$TMP_HOME/.config/opencode/my_opencode/scripts/model_routing_command.py" ]; then HOME="$$TMP_HOME" python3 "$$TMP_HOME/.config/opencode/my_opencode/scripts/model_routing_command.py" status --json; HOME="$$TMP_HOME" python3 "$$TMP_HOME/.config/opencode/my_opencode/scripts/model_routing_command.py" resolve --category deep --override-model openai/nonexistent --available-models openai/gpt-5-mini,openai/gpt-5.3-codex --json; fi; \
5858
if [ -f "$$TMP_HOME/.config/opencode/my_opencode/scripts/keyword_mode_command.py" ]; then HOME="$$TMP_HOME" python3 "$$TMP_HOME/.config/opencode/my_opencode/scripts/keyword_mode_command.py" status --json; HOME="$$TMP_HOME" python3 "$$TMP_HOME/.config/opencode/my_opencode/scripts/keyword_mode_command.py" doctor --json; HOME="$$TMP_HOME" python3 "$$TMP_HOME/.config/opencode/my_opencode/scripts/keyword_mode_command.py" disable-keyword ulw; HOME="$$TMP_HOME" python3 "$$TMP_HOME/.config/opencode/my_opencode/scripts/keyword_mode_command.py" detect --prompt "ulw deep-analyze audit this change" --json; HOME="$$TMP_HOME" python3 "$$TMP_HOME/.config/opencode/my_opencode/scripts/keyword_mode_command.py" detect --prompt "no-keyword-mode safe-apply deep-analyze" --json; HOME="$$TMP_HOME" python3 "$$TMP_HOME/.config/opencode/my_opencode/scripts/keyword_mode_command.py" enable-keyword ulw; fi; \
59+
if [ -f "$$TMP_HOME/.config/opencode/my_opencode/scripts/rules_command.py" ]; then HOME="$$TMP_HOME" python3 "$$TMP_HOME/.config/opencode/my_opencode/scripts/rules_command.py" status --json; HOME="$$TMP_HOME" python3 "$$TMP_HOME/.config/opencode/my_opencode/scripts/rules_command.py" explain scripts/selftest.py --json; HOME="$$TMP_HOME" python3 "$$TMP_HOME/.config/opencode/my_opencode/scripts/rules_command.py" disable-id style-python; HOME="$$TMP_HOME" python3 "$$TMP_HOME/.config/opencode/my_opencode/scripts/rules_command.py" doctor --json; HOME="$$TMP_HOME" python3 "$$TMP_HOME/.config/opencode/my_opencode/scripts/rules_command.py" enable-id style-python; fi; \
5960
HOME="$$TMP_HOME" python3 "$$TMP_HOME/.config/opencode/my_opencode/scripts/install_wizard.py" --non-interactive --skip-extras --plugin-profile lean --mcp-profile research --policy-profile balanced --notify-profile skip --telemetry-profile local --post-session-profile manual-validate; \
6061
HOME="$$TMP_HOME" python3 "$$TMP_HOME/.config/opencode/my_opencode/scripts/doctor_command.py" run --json
6162

README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,29 @@ Anti-patterns:
504504
- avoid relying on partial words (`deep` or `safe`) because matching is exact-token only.
505505
- avoid forgetting local opt-outs in copied prompts; `no-keyword-mode` intentionally disables all activation for that request.
506506

507+
## Conditional rules injector
508+
509+
Epic 9 introduces a rules engine for conditional instruction injection:
510+
511+
- schema contract: `instructions/conditional_rules_schema.md`
512+
- engine implementation: `scripts/rules_engine.py`
513+
- command wrapper: `scripts/rules_command.py`
514+
515+
Use:
516+
```text
517+
/rules status
518+
/rules explain scripts/selftest.py --json
519+
/rules disable-id style-python
520+
/rules enable-id style-python
521+
/rules doctor --json
522+
```
523+
524+
Rules are discovered from:
525+
- user scope: `~/.config/opencode/rules/**/*.md`
526+
- project scope: `.opencode/rules/**/*.md`
527+
528+
Precedence is deterministic: priority desc, then scope (`project` before `user`), then lexical rule id.
529+
507530
## Background jobs inside OpenCode 🧵
508531

509532
Use these directly in OpenCode:

install.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ printf " /keyword-mode status\n"
152152
printf " /keyword-mode detect --prompt 'safe-apply deep-analyze investigate this refactor'\n"
153153
printf " /keyword-mode disable-keyword ulw\n"
154154
printf " /keyword-mode doctor --json\n"
155+
printf " /rules status\n"
156+
printf " /rules explain scripts/selftest.py --json\n"
155157
printf " /stack apply focus\n"
156158
printf " /nvim status\n"
157159
printf " /devtools status\n"

opencode.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,22 @@
190190
"description": "Run keyword mode diagnostics in JSON",
191191
"template": "!`python3 \"$HOME/.config/opencode/my_opencode/scripts/keyword_mode_command.py\" doctor --json`\nShow only the command output."
192192
},
193+
"rules": {
194+
"description": "Inspect conditional rules (status|explain|disable-id|enable-id|doctor)",
195+
"template": "!`python3 \"$HOME/.config/opencode/my_opencode/scripts/rules_command.py\" $ARGUMENTS`\nShow only the command output."
196+
},
197+
"rules-status": {
198+
"description": "Show rules discovery and config status",
199+
"template": "!`python3 \"$HOME/.config/opencode/my_opencode/scripts/rules_command.py\" status`\nShow only the command output."
200+
},
201+
"rules-explain": {
202+
"description": "Explain effective rules for a target path",
203+
"template": "!`python3 \"$HOME/.config/opencode/my_opencode/scripts/rules_command.py\" explain $ARGUMENTS --json`\nShow only the command output."
204+
},
205+
"rules-doctor": {
206+
"description": "Run rules diagnostics in JSON",
207+
"template": "!`python3 \"$HOME/.config/opencode/my_opencode/scripts/rules_command.py\" doctor --json`\nShow only the command output."
208+
},
193209
"stack": {
194210
"description": "Apply cross-command profile bundles",
195211
"template": "!`python3 \"$HOME/.config/opencode/my_opencode/scripts/stack_profile_command.py\" $ARGUMENTS`\nShow only the command output."

scripts/doctor_command.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,18 @@ def script_path(name: str) -> Path:
144144
"--json",
145145
],
146146
},
147+
{
148+
"name": "rules",
149+
"kind": "doctor-json",
150+
"optional": True,
151+
"required_path": str(script_path("rules_command.py")),
152+
"command": [
153+
sys.executable,
154+
str(script_path("rules_command.py")),
155+
"doctor",
156+
"--json",
157+
],
158+
},
147159
]
148160

149161

0 commit comments

Comments
 (0)