@devrik-tools/claude-gates 0.8.0 → 1.0.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.
Files changed (34) hide show
  1. package/.claude-plugin/marketplace.json +3 -3
  2. package/README.es.md +102 -9
  3. package/README.md +93 -9
  4. package/cli/artifacts.mjs +213 -0
  5. package/cli/constants.mjs +14 -0
  6. package/cli/doctor.mjs +2 -1
  7. package/cli/index.mjs +54 -2
  8. package/cli/init.mjs +95 -9
  9. package/cli/install.mjs +53 -1
  10. package/cli/registry.mjs +2 -0
  11. package/cli/selection.mjs +23 -1
  12. package/cli/smoke-fixtures.json +53 -3
  13. package/cli/task.mjs +69 -4
  14. package/package.json +5 -4
  15. package/plugins/gates/.claude-plugin/plugin.json +1 -1
  16. package/plugins/gates/hooks/gates/capability-map/index.mjs +37 -208
  17. package/plugins/gates/hooks/gates/circuit-breaker/index.mjs +4 -11
  18. package/plugins/gates/hooks/gates/circuit-breaker/track.mjs +285 -0
  19. package/plugins/gates/hooks/gates/force-parallel/index.mjs +11 -12
  20. package/plugins/gates/hooks/gates/library-docs/index.mjs +107 -31
  21. package/plugins/gates/hooks/gates/no-trivial-scripts/index.mjs +114 -0
  22. package/plugins/gates/hooks/gates/require-monitor/index.mjs +126 -0
  23. package/plugins/gates/hooks/gates/require-task-split/index.mjs +88 -0
  24. package/plugins/gates/hooks/gates/skill-first/index.mjs +138 -0
  25. package/plugins/gates/hooks/gates/skill-first/track.mjs +66 -0
  26. package/plugins/gates/hooks/hooks.json +61 -1
  27. package/plugins/gates/hooks/lib/capabilities.mjs +401 -0
  28. package/plugins/gates/hooks/lib/hook-io.mjs +9 -2
  29. package/plugins/gates/hooks/lib/signals.mjs +91 -0
  30. package/plugins/gates/hooks/lib/testing.mjs +15 -4
  31. package/plugins/tasks/.claude-plugin/plugin.json +1 -1
  32. package/plugins/tasks/hooks/lib/task-store.mjs +6 -0
  33. package/plugins/tasks/hooks/register-requests.mjs +37 -10
  34. package/registry.json +106 -5
package/registry.json CHANGED
@@ -110,6 +110,22 @@
110
110
  "description": "Comment marker that authorizes a justified wait as an escape hatch."
111
111
  }
112
112
  ]
113
+ },
114
+ {
115
+ "id": "require-monitor",
116
+ "configKey": "requireMonitorForBackground",
117
+ "default": true,
118
+ "event": "PreToolUse",
119
+ "tools": ["shell", "execution", "monitor"],
120
+ "description": "Enforces that every background command (run_in_background: true) has an associated Monitor. Phase 1: denies background without MONITOR-PLANNED: marker. Phase 2: denies any execution tool while unmonitored backgrounds exist.",
121
+ "script": "gates/require-monitor/index.mjs",
122
+ "params": [
123
+ {
124
+ "name": "monitorPlannedMarker",
125
+ "type": "string",
126
+ "description": "Marker the command must carry to declare its Monitor plan. Default MONITOR-PLANNED:."
127
+ }
128
+ ]
113
129
  }
114
130
  ]
115
131
  },
@@ -187,8 +203,15 @@
187
203
  "default": false,
188
204
  "event": "PreToolUse",
189
205
  "tools": ["delegation"],
190
- "description": "Cuts a delegation retried without substantial change: the attempt count is recomputed from stored signatures across the session (Dice >= similarityThreshold); retryThreshold below 2 is treated as 2.",
206
+ "description": "Cuts a delegation retried without substantial change: the attempt count is recomputed from stored signatures across the session (Dice >= similarityThreshold); retryThreshold below 2 is treated as 2. Only delegations that actually launched (allowed by all gates) count as attempts.",
191
207
  "script": "gates/circuit-breaker/index.mjs",
208
+ "extraScripts": [
209
+ {
210
+ "event": "PostToolUse",
211
+ "script": "gates/circuit-breaker/track.mjs",
212
+ "tools": ["delegation"]
213
+ }
214
+ ],
192
215
  "params": [
193
216
  {
194
217
  "name": "retryThreshold",
@@ -226,10 +249,10 @@
226
249
  {
227
250
  "id": "force-parallel",
228
251
  "configKey": "warnSequentialDelegations",
229
- "default": false,
252
+ "default": true,
230
253
  "event": "PreToolUse",
231
254
  "tools": ["delegation"],
232
- "description": "Warns after N consecutive sequential delegations within a time window, suggesting they be launched together instead.",
255
+ "description": "Denies the Nth consecutive sequential delegation within a time window, requiring independent delegations to be launched together in one message. Escape hatch: SEQUENTIAL-JUSTIFIED in the prompt declares a genuine dependency.",
233
256
  "script": "gates/force-parallel/index.mjs",
234
257
  "params": [
235
258
  {
@@ -736,6 +759,16 @@
736
759
  "description": "Substring inside a comment that allows it once (a documented exception). Default comment-ok:."
737
760
  }
738
761
  ]
762
+ },
763
+ {
764
+ "id": "no-trivial-scripts",
765
+ "configKey": "blockTrivialInlineScripts",
766
+ "default": true,
767
+ "event": "PreToolUse",
768
+ "tools": ["shell"],
769
+ "description": "Denies inline interpreter scripts (node -e, python -c, sed -i, perl -i, PowerShell Set-Content/Add-Content) when they perform file operations that the Edit or Write tool handles directly. Legitimate computation scripts are not caught.",
770
+ "script": "gates/no-trivial-scripts/index.mjs",
771
+ "params": []
739
772
  }
740
773
  ]
741
774
  },
@@ -805,6 +838,59 @@
805
838
  "description": "Regex sources; a file whose basename matches any is a helper regardless of folder."
806
839
  }
807
840
  ]
841
+ },
842
+ {
843
+ "id": "skill-first",
844
+ "configKey": "requireSkillCheckBeforeActing",
845
+ "default": false,
846
+ "event": "PreToolUse",
847
+ "tools": ["execution", "delegation"],
848
+ "script": "gates/skill-first/index.mjs",
849
+ "extraScripts": [
850
+ {
851
+ "event": "PostToolUse",
852
+ "script": "gates/skill-first/track.mjs",
853
+ "tools": ["skill"]
854
+ }
855
+ ],
856
+ "description": "Denies a write, command or delegation that an available skill plausibly covers until the question was asked: load the skill (the Skill tool, recorded by its tracker), or state the decision in the content/prompt (\"using the <name> skill\", \"no skill covers this\"). Relevance is lexical over the same catalog capability-map injects: the action names the skill, or shares minTokenOverlap distinctive tokens with its description. Silent when nothing matches.",
857
+ "params": [
858
+ {
859
+ "name": "kinds",
860
+ "type": "string[]",
861
+ "description": "Which capability kinds are judged for relevance: skills, agents, commands. Default skills only."
862
+ },
863
+ {
864
+ "name": "minTokenOverlap",
865
+ "type": "number",
866
+ "description": "How many distinctive tokens an action must share with a capability's description to count as relevant. Raise it to make the gate quieter. Default 3."
867
+ },
868
+ {
869
+ "name": "maxMatches",
870
+ "type": "number",
871
+ "description": "How many relevant capabilities the deny message lists. Default 3."
872
+ },
873
+ {
874
+ "name": "minTextChars",
875
+ "type": "number",
876
+ "description": "Actions with less text than this are never judged (a bare command has nothing to match). Default 40."
877
+ },
878
+ {
879
+ "name": "extraSkillsDirs",
880
+ "type": "string[]",
881
+ "description": "Extra skill roots scanned in addition to the default project and home roots."
882
+ },
883
+ {
884
+ "name": "extraAgentsDirs",
885
+ "type": "string[]",
886
+ "description": "Extra agent roots, used only when 'agents' is in kinds."
887
+ },
888
+ {
889
+ "name": "extraCommandsDirs",
890
+ "type": "string[]",
891
+ "description": "Extra command roots, used only when 'commands' is in kinds."
892
+ }
893
+ ]
808
894
  }
809
895
  ]
810
896
  },
@@ -869,7 +955,7 @@
869
955
  "configKey": "requireDocsBeforeUsingNewLibrary",
870
956
  "default": true,
871
957
  "event": "PreToolUse",
872
- "tools": ["write"],
958
+ "tools": ["write", "shell"],
873
959
  "script": "gates/library-docs/index.mjs",
874
960
  "extraScripts": [
875
961
  {
@@ -878,7 +964,7 @@
878
964
  "tools": ["research"]
879
965
  }
880
966
  ],
881
- "description": "Denies a write that imports a package the project does not use anywhere yet unless this session looked it up: an engram hit about it, or context7 docs followed by a mem_save. Never guess a library API.",
967
+ "description": "Denies a write or shell command that imports a package the project does not use anywhere yet unless this session looked it up: an engram hit about it, or context7 docs followed by a mem_save. Shell heredocs are inspected; opaque redirections to code files are denied outright. Never guess a library API.",
882
968
  "params": [
883
969
  {
884
970
  "name": "codeExtensions",
@@ -964,6 +1050,16 @@
964
1050
  "description": "When true (default), a task with status 'blocked' does not prevent stop; only open/in_forge do."
965
1051
  }
966
1052
  ]
1053
+ },
1054
+ {
1055
+ "id": "require-task-split",
1056
+ "configKey": "requireTaskSplitBeforeImplementing",
1057
+ "default": true,
1058
+ "event": "PreToolUse",
1059
+ "tools": ["write", "execution"],
1060
+ "description": "Denies writes and execution when an active task has size > small/trivial and no sub-tasks registered. Forces splitting into smaller, independently verifiable sub-tasks before implementation begins.",
1061
+ "script": "gates/require-task-split/index.mjs",
1062
+ "params": []
967
1063
  }
968
1064
  ]
969
1065
  },
@@ -1052,6 +1148,11 @@
1052
1148
  "name": "blurbOverridesFile",
1053
1149
  "type": "string",
1054
1150
  "description": "Path, relative to the project root, of a JSON map name -> hand-written blurb (default .ai/blurb-overrides.json)."
1151
+ },
1152
+ {
1153
+ "name": "reinjectOnWorkNatureChange",
1154
+ "type": "boolean",
1155
+ "description": "Re-inject the catalog when the prompt's kind of work changes (debug -> design -> release), not only when the catalog itself changed. Default true; set false to fall back to the throttle alone."
1055
1156
  }
1056
1157
  ],
1057
1158
  "timeoutSeconds": 10