@devrik-tools/claude-gates 0.2.0 → 0.3.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 (99) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/README.es.md +7 -6
  3. package/README.md +16 -7
  4. package/cli/index.mjs +4 -0
  5. package/cli/init.mjs +18 -1
  6. package/cli/install.mjs +26 -1
  7. package/package.json +5 -2
  8. package/plugins/gates/.claude-plugin/plugin.json +1 -1
  9. package/plugins/gates/hooks/gates/autonomous-mode/index.mjs +8 -6
  10. package/plugins/gates/hooks/gates/autonomous-mode/stop.mjs +78 -0
  11. package/plugins/gates/hooks/gates/bash-commands/index.mjs +11 -81
  12. package/plugins/gates/hooks/gates/block-remote-publish/index.mjs +140 -0
  13. package/plugins/gates/hooks/gates/dependency-skills/index.mjs +130 -126
  14. package/plugins/gates/hooks/gates/neutral-spanish/index.mjs +104 -79
  15. package/plugins/gates/hooks/gates/no-memory-dependency/index.mjs +138 -123
  16. package/plugins/gates/hooks/gates/root-whitelist/index.mjs +59 -44
  17. package/plugins/gates/hooks/gates/test-after-implementation/index.mjs +124 -101
  18. package/plugins/gates/hooks/hooks.json +365 -346
  19. package/plugins/gates/hooks/lib/hook-io.mjs +39 -0
  20. package/plugins/tasks/.claude-plugin/plugin.json +1 -1
  21. package/plugins/tasks/hooks/register-requests.mjs +7 -3
  22. package/registry.json +738 -793
  23. package/cli/__tests__/config.test.mjs +0 -113
  24. package/cli/__tests__/init-flags.test.mjs +0 -111
  25. package/cli/__tests__/install.test.mjs +0 -102
  26. package/cli/__tests__/materialize.test.mjs +0 -95
  27. package/cli/__tests__/registry-gates-consistency.test.mjs +0 -52
  28. package/cli/__tests__/selection.test.mjs +0 -200
  29. package/cli/__tests__/task.test.mjs +0 -124
  30. package/cli/__tests__/version-consistency.test.mjs +0 -44
  31. package/plugins/gates/hooks/__tests__/ask-adoption.test.mjs +0 -83
  32. package/plugins/gates/hooks/__tests__/doctor.test.mjs +0 -85
  33. package/plugins/gates/hooks/__tests__/wiring-check.test.mjs +0 -65
  34. package/plugins/gates/hooks/gates/audit-before-build/audit-before-build.edge.test.mjs +0 -83
  35. package/plugins/gates/hooks/gates/audit-before-build/test.mjs +0 -117
  36. package/plugins/gates/hooks/gates/autonomous-mode/autonomous.edge.test.mjs +0 -104
  37. package/plugins/gates/hooks/gates/autonomous-mode/test.mjs +0 -58
  38. package/plugins/gates/hooks/gates/bash-commands/bash-commands.edge.test.mjs +0 -165
  39. package/plugins/gates/hooks/gates/bash-commands/test.mjs +0 -126
  40. package/plugins/gates/hooks/gates/brief-before-delegate/brief-before-delegate.edge.test.mjs +0 -151
  41. package/plugins/gates/hooks/gates/brief-before-delegate/test.mjs +0 -111
  42. package/plugins/gates/hooks/gates/circuit-breaker/circuit-breaker.edge.test.mjs +0 -207
  43. package/plugins/gates/hooks/gates/circuit-breaker/test.mjs +0 -161
  44. package/plugins/gates/hooks/gates/dependency-skills/dependency-skills.edge.test.mjs +0 -69
  45. package/plugins/gates/hooks/gates/dependency-skills/test.mjs +0 -109
  46. package/plugins/gates/hooks/gates/diagnosis-before-patch/diagnosis-before-patch.edge.test.mjs +0 -68
  47. package/plugins/gates/hooks/gates/diagnosis-before-patch/test.mjs +0 -68
  48. package/plugins/gates/hooks/gates/feature-catalog/edge.edge.test.mjs +0 -83
  49. package/plugins/gates/hooks/gates/feature-catalog/test.mjs +0 -97
  50. package/plugins/gates/hooks/gates/force-parallel/test.mjs +0 -88
  51. package/plugins/gates/hooks/gates/forge-flow/forge-flow.edge.test.mjs +0 -155
  52. package/plugins/gates/hooks/gates/forge-flow/test.mjs +0 -135
  53. package/plugins/gates/hooks/gates/implementation-pipeline/edge.edge.test.mjs +0 -66
  54. package/plugins/gates/hooks/gates/implementation-pipeline/test.mjs +0 -86
  55. package/plugins/gates/hooks/gates/intent-flow/intent-flow.edge.test.mjs +0 -96
  56. package/plugins/gates/hooks/gates/intent-flow/test.mjs +0 -165
  57. package/plugins/gates/hooks/gates/lint-commit/test.mjs +0 -85
  58. package/plugins/gates/hooks/gates/mandatory-flow/edge.edge.test.mjs +0 -100
  59. package/plugins/gates/hooks/gates/mandatory-flow/test.mjs +0 -119
  60. package/plugins/gates/hooks/gates/neutral-spanish/neutral-spanish.edge.test.mjs +0 -80
  61. package/plugins/gates/hooks/gates/neutral-spanish/test.mjs +0 -65
  62. package/plugins/gates/hooks/gates/never-assume/never-assume.edge.test.mjs +0 -71
  63. package/plugins/gates/hooks/gates/never-assume/test.mjs +0 -95
  64. package/plugins/gates/hooks/gates/no-blocking/no-blocking.edge.test.mjs +0 -109
  65. package/plugins/gates/hooks/gates/no-blocking/test.mjs +0 -108
  66. package/plugins/gates/hooks/gates/no-memory-dependency/no-memory-dependency.edge.test.mjs +0 -83
  67. package/plugins/gates/hooks/gates/no-memory-dependency/test.mjs +0 -106
  68. package/plugins/gates/hooks/gates/no-reconfirm/no-reconfirm.edge.test.mjs +0 -91
  69. package/plugins/gates/hooks/gates/no-reconfirm/test.mjs +0 -131
  70. package/plugins/gates/hooks/gates/protected-paths/protected-paths.edge.test.mjs +0 -126
  71. package/plugins/gates/hooks/gates/protected-paths/test.mjs +0 -75
  72. package/plugins/gates/hooks/gates/recurrence-lock/recurrence-lock.edge.test.mjs +0 -102
  73. package/plugins/gates/hooks/gates/recurrence-lock/test.mjs +0 -99
  74. package/plugins/gates/hooks/gates/reuse-before-build/edge.edge.test.mjs +0 -94
  75. package/plugins/gates/hooks/gates/reuse-before-build/test.mjs +0 -101
  76. package/plugins/gates/hooks/gates/risk-level/risk-level.edge.test.mjs +0 -116
  77. package/plugins/gates/hooks/gates/risk-level/test.mjs +0 -153
  78. package/plugins/gates/hooks/gates/root-cause-first/root-cause-first.edge.test.mjs +0 -58
  79. package/plugins/gates/hooks/gates/root-cause-first/test.mjs +0 -73
  80. package/plugins/gates/hooks/gates/root-whitelist/root-whitelist.edge.test.mjs +0 -97
  81. package/plugins/gates/hooks/gates/root-whitelist/test.mjs +0 -80
  82. package/plugins/gates/hooks/gates/rule-skill-autodiscovery/rule-skill-autodiscovery.edge.test.mjs +0 -126
  83. package/plugins/gates/hooks/gates/rule-skill-autodiscovery/test.mjs +0 -78
  84. package/plugins/gates/hooks/gates/sdd-specs/edge.edge.test.mjs +0 -130
  85. package/plugins/gates/hooks/gates/sdd-specs/test.mjs +0 -163
  86. package/plugins/gates/hooks/gates/stop-pending/test.mjs +0 -114
  87. package/plugins/gates/hooks/gates/test-after-implementation/test-after-implementation.edge.test.mjs +0 -72
  88. package/plugins/gates/hooks/gates/test-after-implementation/test.mjs +0 -81
  89. package/plugins/gates/hooks/gates/test-matrix/edge.edge.test.mjs +0 -63
  90. package/plugins/gates/hooks/gates/test-matrix/test.mjs +0 -114
  91. package/plugins/gates/hooks/gates/tool-map/edge.edge.test.mjs +0 -62
  92. package/plugins/gates/hooks/gates/tool-map/test.mjs +0 -87
  93. package/plugins/gates/hooks/lib/__tests__/config.test.mjs +0 -173
  94. package/plugins/gates/hooks/lib/__tests__/hook-io.test.mjs +0 -210
  95. package/plugins/gates/hooks/lib/__tests__/signals.test.mjs +0 -114
  96. package/plugins/gates/hooks/lib/hook-io-config.edge.test.mjs +0 -189
  97. package/plugins/tasks/hooks/__tests__/register-requests.test.mjs +0 -100
  98. package/plugins/tasks/hooks/__tests__/session-tasks.test.mjs +0 -95
  99. package/plugins/tasks/hooks/lib/__tests__/task-store.test.mjs +0 -180
@@ -155,6 +155,45 @@ export function writtenPathOf(toolInput) {
155
155
  return String(path);
156
156
  }
157
157
 
158
+ // Shell forms that CREATE or write a file at a named path, so a gate protecting a path can
159
+ // see a `printf ... > basura.txt` the same way it sees a Write. Each pattern captures the
160
+ // target path. Conservative by design: it over-detects (a gate then finds the path benign)
161
+ // rather than under-detects (a silent hole). It does NOT resolve variables, command
162
+ // substitution, or subshells — a path built dynamically (`> "$f"`) is not extracted; that
163
+ // limitation is documented on the gates that use this, the honest boundary of a regex.
164
+ const SHELL_WRITE_PATTERNS = [
165
+ // redirection: `> file`, `>> file`, `1> file`, `&> file` (not `2>` alone — stderr)
166
+ /(?:^|\s|;|&&|\|\|)(?:[0-9]*|&)>>?\s*(['"]?)([^\s'"|;&<>]+)\1/g,
167
+ // touch / tee target(s)
168
+ /\b(?:touch|tee)\s+(?:-\S+\s+)*(['"]?)([^\s'"|;&<>]+)\1/g,
169
+ // cp / mv / install destination is the LAST path; capture the first arg after the command
170
+ // as a cheap proxy (over-detects the source too, which is acceptable — a gate re-checks).
171
+ /\b(?:cp|mv|install)\s+(?:-\S+\s+)*(['"]?)([^\s'"|;&<>]+)\1/g,
172
+ ];
173
+
174
+ /**
175
+ * Every filesystem path a shell command appears to create or write to (redirections, touch,
176
+ * tee, cp/mv destinations). Returns a de-duplicated list, empty when none is found. A gate
177
+ * that protects paths should check these IN ADDITION to writtenPathOf, or a shell redirection
178
+ * slips past it (the exact hole that let `printf x > basura.txt` evade root-whitelist while a
179
+ * Write to the same path was blocked).
180
+ */
181
+ export function shellWrittenPaths(command) {
182
+ const text = String(command ?? '');
183
+ const found = new Set();
184
+ for (const pattern of SHELL_WRITE_PATTERNS) {
185
+ for (const match of text.matchAll(pattern)) {
186
+ const path = match[2];
187
+ // Skip a dynamically built target (a variable/substitution): we cannot resolve `$f`,
188
+ // `${x}` or `$(…)` to a real path, and guessing would only add false positives. This is
189
+ // the documented limitation — the write-tool surface, which carries a concrete path,
190
+ // stays the reliable one.
191
+ if (path && !/[$`]/.test(path)) found.add(path);
192
+ }
193
+ }
194
+ return [...found];
195
+ }
196
+
158
197
  /** The brief/prompt a delegation carries, across native and MCP field shapes. */
159
198
  export function delegationPromptOf(toolInput) {
160
199
  if (!toolInput || typeof toolInput !== 'object') return '';
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tasks",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Deterministic task tracking for Claude Code: persists tasks the model registers via the CLI, reminds of open tasks on a message counter, and lists active tasks on session start.",
5
5
  "author": {
6
6
  "name": "Devrik"
@@ -81,9 +81,13 @@ function readPayload() {
81
81
  // make something OCCUR deterministically; it is depending on the model's judgment for a
82
82
  // judgment call (whether this message describes a new task), same shape as ask-adoption.
83
83
  const CLASSIFY_PROMPT =
84
- '[tasks] If the user just described a new actionable task (not a question, not small talk), ' +
85
- 'register it now: run `claude-gates task add "<title>" [--description <text>] [--size <size>]` ' +
86
- 'from the project root. Skip this for messages that are not a new task.';
84
+ '[tasks] MANDATORY before you respond: judge whether the message you just received describes ' +
85
+ 'a new actionable task (not a question, not small talk, not a follow-up on an already-registered ' +
86
+ 'task). If it does, you MUST register it now, before writing your reply — run ' +
87
+ '`claude-gates task add "<title>" [--description <text>] [--size <size>]` from the project root ' +
88
+ '(or the CLI\'s absolute path if `claude-gates` is not on PATH). Do not defer this, do not decide ' +
89
+ 'to register it "later", do not silently skip it because the answer seems obvious. If it is not a ' +
90
+ 'new task, skip registration — do not fabricate one.';
87
91
 
88
92
  function formatReminder(tasks) {
89
93
  const shown = tasks.slice(0, MAX_TASKS_SHOWN);