@devrik-tools/claude-gates 0.1.2 → 0.1.3

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 (104) hide show
  1. package/.claude-plugin/marketplace.json +23 -17
  2. package/cli/__tests__/config.test.mjs +113 -101
  3. package/cli/__tests__/install.test.mjs +102 -0
  4. package/cli/__tests__/materialize.test.mjs +95 -0
  5. package/cli/__tests__/registry-gates-consistency.test.mjs +52 -44
  6. package/cli/__tests__/task.test.mjs +124 -0
  7. package/cli/config.mjs +124 -113
  8. package/cli/index.mjs +100 -97
  9. package/cli/init.mjs +259 -256
  10. package/cli/install.mjs +150 -80
  11. package/cli/materialize.mjs +102 -51
  12. package/cli/registry.mjs +136 -127
  13. package/cli/task.mjs +140 -0
  14. package/package.json +74 -73
  15. package/plugins/gates/hooks/__tests__/ask-adoption.test.mjs +83 -0
  16. package/plugins/gates/hooks/__tests__/doctor.test.mjs +85 -0
  17. package/plugins/gates/hooks/__tests__/wiring-check.test.mjs +65 -0
  18. package/plugins/gates/hooks/ask-adoption.mjs +147 -0
  19. package/plugins/gates/hooks/doctor.mjs +207 -0
  20. package/plugins/gates/hooks/gates/audit-before-build/audit-before-build.edge.test.mjs +83 -0
  21. package/plugins/gates/hooks/gates/audit-before-build/index.mjs +88 -88
  22. package/plugins/gates/hooks/gates/audit-before-build/test.mjs +117 -92
  23. package/plugins/gates/hooks/gates/autonomous-mode/autonomous.edge.test.mjs +104 -0
  24. package/plugins/gates/hooks/gates/autonomous-mode/index.mjs +48 -45
  25. package/plugins/gates/hooks/gates/bash-commands/bash-commands.edge.test.mjs +165 -0
  26. package/plugins/gates/hooks/gates/bash-commands/index.mjs +285 -268
  27. package/plugins/gates/hooks/gates/brief-before-delegate/brief-before-delegate.edge.test.mjs +151 -0
  28. package/plugins/gates/hooks/gates/brief-before-delegate/index.mjs +265 -177
  29. package/plugins/gates/hooks/gates/circuit-breaker/circuit-breaker.edge.test.mjs +207 -0
  30. package/plugins/gates/hooks/gates/circuit-breaker/index.mjs +501 -456
  31. package/plugins/gates/hooks/gates/circuit-breaker/test.mjs +161 -143
  32. package/plugins/gates/hooks/gates/dependency-skills/dependency-skills.edge.test.mjs +69 -0
  33. package/plugins/gates/hooks/gates/dependency-skills/index.mjs +126 -118
  34. package/plugins/gates/hooks/gates/diagnosis-before-patch/diagnosis-before-patch.edge.test.mjs +68 -0
  35. package/plugins/gates/hooks/gates/diagnosis-before-patch/index.mjs +43 -49
  36. package/plugins/gates/hooks/gates/feature-catalog/edge.edge.test.mjs +83 -0
  37. package/plugins/gates/hooks/gates/feature-catalog/index.mjs +83 -100
  38. package/plugins/gates/hooks/gates/force-parallel/index.mjs +119 -0
  39. package/plugins/gates/hooks/gates/force-parallel/test.mjs +88 -0
  40. package/plugins/gates/hooks/gates/forge-flow/forge-flow.edge.test.mjs +155 -0
  41. package/plugins/gates/hooks/gates/forge-flow/index.mjs +134 -112
  42. package/plugins/gates/hooks/gates/implementation-pipeline/edge.edge.test.mjs +66 -0
  43. package/plugins/gates/hooks/gates/implementation-pipeline/index.mjs +187 -186
  44. package/plugins/gates/hooks/gates/intent-flow/index.mjs +260 -238
  45. package/plugins/gates/hooks/gates/intent-flow/intent-flow.edge.test.mjs +96 -0
  46. package/plugins/gates/hooks/gates/intent-flow/test.mjs +165 -136
  47. package/plugins/gates/hooks/gates/lint-commit/index.mjs +149 -0
  48. package/plugins/gates/hooks/gates/lint-commit/test.mjs +85 -0
  49. package/plugins/gates/hooks/gates/mandatory-flow/edge.edge.test.mjs +100 -0
  50. package/plugins/gates/hooks/gates/mandatory-flow/index.mjs +180 -166
  51. package/plugins/gates/hooks/gates/neutral-spanish/index.mjs +79 -85
  52. package/plugins/gates/hooks/gates/neutral-spanish/neutral-spanish.edge.test.mjs +80 -0
  53. package/plugins/gates/hooks/gates/never-assume/index.mjs +58 -55
  54. package/plugins/gates/hooks/gates/never-assume/never-assume.edge.test.mjs +71 -0
  55. package/plugins/gates/hooks/gates/never-assume/test.mjs +95 -78
  56. package/plugins/gates/hooks/gates/no-blocking/index.mjs +148 -142
  57. package/plugins/gates/hooks/gates/no-blocking/no-blocking.edge.test.mjs +109 -0
  58. package/plugins/gates/hooks/gates/no-memory-dependency/index.mjs +123 -120
  59. package/plugins/gates/hooks/gates/no-memory-dependency/no-memory-dependency.edge.test.mjs +83 -0
  60. package/plugins/gates/hooks/gates/no-reconfirm/no-reconfirm.edge.test.mjs +91 -0
  61. package/plugins/gates/hooks/gates/protected-paths/index.mjs +144 -147
  62. package/plugins/gates/hooks/gates/protected-paths/protected-paths.edge.test.mjs +126 -0
  63. package/plugins/gates/hooks/gates/recurrence-lock/index.mjs +89 -64
  64. package/plugins/gates/hooks/gates/recurrence-lock/recurrence-lock.edge.test.mjs +102 -0
  65. package/plugins/gates/hooks/gates/reuse-before-build/edge.edge.test.mjs +94 -0
  66. package/plugins/gates/hooks/gates/reuse-before-build/index.mjs +159 -150
  67. package/plugins/gates/hooks/gates/risk-level/index.mjs +263 -203
  68. package/plugins/gates/hooks/gates/risk-level/risk-level.edge.test.mjs +116 -0
  69. package/plugins/gates/hooks/gates/risk-level/test.mjs +153 -125
  70. package/plugins/gates/hooks/gates/root-cause-first/index.mjs +56 -50
  71. package/plugins/gates/hooks/gates/root-cause-first/root-cause-first.edge.test.mjs +58 -0
  72. package/plugins/gates/hooks/gates/root-whitelist/index.mjs +116 -111
  73. package/plugins/gates/hooks/gates/root-whitelist/root-whitelist.edge.test.mjs +97 -0
  74. package/plugins/gates/hooks/gates/rule-skill-autodiscovery/index.mjs +184 -99
  75. package/plugins/gates/hooks/gates/rule-skill-autodiscovery/rule-skill-autodiscovery.edge.test.mjs +126 -0
  76. package/plugins/gates/hooks/gates/sdd-specs/edge.edge.test.mjs +130 -0
  77. package/plugins/gates/hooks/gates/sdd-specs/index.mjs +256 -251
  78. package/plugins/gates/hooks/gates/stop-pending/index.mjs +159 -0
  79. package/plugins/gates/hooks/gates/stop-pending/test.mjs +114 -0
  80. package/plugins/gates/hooks/gates/test-after-implementation/index.mjs +101 -101
  81. package/plugins/gates/hooks/gates/test-after-implementation/test-after-implementation.edge.test.mjs +72 -0
  82. package/plugins/gates/hooks/gates/test-matrix/edge.edge.test.mjs +63 -0
  83. package/plugins/gates/hooks/gates/test-matrix/index.mjs +187 -181
  84. package/plugins/gates/hooks/gates/test-matrix/test.mjs +114 -87
  85. package/plugins/gates/hooks/gates/tool-map/edge.edge.test.mjs +62 -0
  86. package/plugins/gates/hooks/gates/tool-map/index.mjs +143 -140
  87. package/plugins/gates/hooks/hooks.json +346 -286
  88. package/plugins/gates/hooks/lib/__tests__/config.test.mjs +173 -154
  89. package/plugins/gates/hooks/lib/__tests__/hook-io.test.mjs +210 -154
  90. package/plugins/gates/hooks/lib/__tests__/signals.test.mjs +114 -0
  91. package/plugins/gates/hooks/lib/config.mjs +172 -165
  92. package/plugins/gates/hooks/lib/hook-io-config.edge.test.mjs +189 -0
  93. package/plugins/gates/hooks/lib/hook-io.mjs +318 -208
  94. package/plugins/gates/hooks/lib/signals.mjs +127 -0
  95. package/plugins/gates/hooks/wiring-check.mjs +227 -0
  96. package/plugins/tasks/.claude-plugin/plugin.json +9 -0
  97. package/plugins/tasks/hooks/__tests__/register-requests.test.mjs +100 -0
  98. package/plugins/tasks/hooks/__tests__/session-tasks.test.mjs +95 -0
  99. package/plugins/tasks/hooks/hooks.json +26 -0
  100. package/plugins/tasks/hooks/lib/__tests__/task-store.test.mjs +180 -132
  101. package/plugins/tasks/hooks/lib/task-store.mjs +197 -159
  102. package/plugins/tasks/hooks/register-requests.mjs +141 -108
  103. package/plugins/tasks/hooks/session-tasks.mjs +108 -0
  104. package/registry.json +793 -686
@@ -0,0 +1,108 @@
1
+ // session-tasks — SessionStart hook. Runs once when a session opens. Lists this project's
2
+ // ACTIVE tasks (open/blocked/in_forge) so a fresh session (or one that just compacted) does
3
+ // not lose track of what was already registered. Silent when there is nothing active: this
4
+ // hook only speaks when it has something worth saying.
5
+ //
6
+ // Self-contained: Node built-ins + the task-store lib only, no npm at runtime.
7
+ //
8
+ // justification: no existing tool covers this. task-store.mjs (and its audit) already
9
+ // exists; this is the SessionStart wiring on top of it, mirroring register-requests.mjs's
10
+ // UserPromptSubmit wiring for the same store.
11
+
12
+ import { existsSync, readFileSync } from 'node:fs';
13
+ import { homedir } from 'node:os';
14
+ import { dirname, join } from 'node:path';
15
+ import { openTaskStore, STATUS } from './lib/task-store.mjs';
16
+
17
+ const STDIN_FILE_DESCRIPTOR = 0;
18
+ const SESSION_START_EVENT = 'SessionStart';
19
+ const CONFIG_KEY = 'listTasksOnSessionStart';
20
+ const MAX_TASKS_SHOWN = 20;
21
+
22
+ // Same config lookup as register-requests.mjs: project overrides global. Kept local so this
23
+ // plugin stays independent of the gates plugin.
24
+ const PROJECT_ROOT_MARKERS = ['.git', '.ai'];
25
+ const PROJECT_CONFIG = join('.ai', 'config.json');
26
+ const GLOBAL_CONFIG = join('.claude', 'claude-gates', 'config.json');
27
+
28
+ function readJson(path) {
29
+ try {
30
+ return JSON.parse(readFileSync(path, 'utf8'));
31
+ } catch {
32
+ return null;
33
+ }
34
+ }
35
+
36
+ function projectRootOf(startDirectory) {
37
+ let current = startDirectory;
38
+ while (true) {
39
+ if (
40
+ PROJECT_ROOT_MARKERS.some((marker) => existsSync(join(current, marker)))
41
+ ) {
42
+ return current;
43
+ }
44
+ const parent = dirname(current);
45
+ if (parent === current) return null;
46
+ current = parent;
47
+ }
48
+ }
49
+
50
+ /** The tasks gate config entry (project overrides global), or null. */
51
+ function sessionTasksConfig(startDirectory) {
52
+ const root = projectRootOf(startDirectory);
53
+ const projectData = root ? readJson(join(root, PROJECT_CONFIG)) : null;
54
+ const globalData = readJson(join(homedir(), GLOBAL_CONFIG));
55
+ const layer = projectData?.gates ?? globalData?.gates ?? {};
56
+ const entry = layer[CONFIG_KEY];
57
+ if (typeof entry === 'boolean') return { enabled: entry };
58
+ if (entry && typeof entry === 'object') return entry;
59
+ return null;
60
+ }
61
+
62
+ function readPayload() {
63
+ try {
64
+ return JSON.parse(readFileSync(STDIN_FILE_DESCRIPTOR, 'utf8'));
65
+ } catch {
66
+ return {};
67
+ }
68
+ }
69
+
70
+ function formatActiveTasks(tasks) {
71
+ const shown = tasks.slice(0, MAX_TASKS_SHOWN);
72
+ const lines = shown.map((task) => {
73
+ const marker = task.status === STATUS.IN_FORGE ? ' (in_forge)' : '';
74
+ return ` - ${task.id}: ${task.title} [${task.status}]${marker}`;
75
+ });
76
+ const extra = tasks.length - shown.length;
77
+ if (extra > 0) lines.push(` - …and ${extra} more`);
78
+ return `[tasks] Active tasks for this project:\n${lines.join('\n')}`;
79
+ }
80
+
81
+ function speak(context) {
82
+ process.stdout.write(
83
+ JSON.stringify({
84
+ hookSpecificOutput: {
85
+ hookEventName: SESSION_START_EVENT,
86
+ additionalContext: context,
87
+ },
88
+ }),
89
+ );
90
+ }
91
+
92
+ function main() {
93
+ const payload = readPayload();
94
+ const cwd = payload.cwd || process.cwd();
95
+
96
+ const config = sessionTasksConfig(cwd);
97
+ if (config && config.enabled === false) return; // gate turned off for this project
98
+
99
+ const store = openTaskStore(cwd);
100
+ if (!store) return; // no project: nowhere to track
101
+
102
+ const tasks = store.active();
103
+ if (tasks.length === 0) return; // nothing active: stay silent
104
+
105
+ speak(formatActiveTasks(tasks));
106
+ }
107
+
108
+ main();