comp-gate 0.1.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 (130) hide show
  1. package/README.md +353 -0
  2. package/dist/agents/agents-md.d.ts +2 -0
  3. package/dist/agents/agents-md.d.ts.map +1 -0
  4. package/dist/agents/agents-md.js +25 -0
  5. package/dist/agents/agents-md.js.map +1 -0
  6. package/dist/agents/claude.d.ts +2 -0
  7. package/dist/agents/claude.d.ts.map +1 -0
  8. package/dist/agents/claude.js +45 -0
  9. package/dist/agents/claude.js.map +1 -0
  10. package/dist/agents/cursor.d.ts +2 -0
  11. package/dist/agents/cursor.d.ts.map +1 -0
  12. package/dist/agents/cursor.js +28 -0
  13. package/dist/agents/cursor.js.map +1 -0
  14. package/dist/agents/detect.d.ts +4 -0
  15. package/dist/agents/detect.d.ts.map +1 -0
  16. package/dist/agents/detect.js +96 -0
  17. package/dist/agents/detect.js.map +1 -0
  18. package/dist/agents/shared.d.ts +9 -0
  19. package/dist/agents/shared.d.ts.map +1 -0
  20. package/dist/agents/shared.js +83 -0
  21. package/dist/agents/shared.js.map +1 -0
  22. package/dist/agents/types.d.ts +14 -0
  23. package/dist/agents/types.d.ts.map +1 -0
  24. package/dist/agents/types.js +8 -0
  25. package/dist/agents/types.js.map +1 -0
  26. package/dist/agents/windsurf.d.ts +2 -0
  27. package/dist/agents/windsurf.d.ts.map +1 -0
  28. package/dist/agents/windsurf.js +27 -0
  29. package/dist/agents/windsurf.js.map +1 -0
  30. package/dist/bootstrap-summary.d.ts +2 -0
  31. package/dist/bootstrap-summary.d.ts.map +1 -0
  32. package/dist/bootstrap-summary.js +262 -0
  33. package/dist/bootstrap-summary.js.map +1 -0
  34. package/dist/categories.d.ts +13 -0
  35. package/dist/categories.d.ts.map +1 -0
  36. package/dist/categories.js +382 -0
  37. package/dist/categories.js.map +1 -0
  38. package/dist/cli.d.ts +3 -0
  39. package/dist/cli.d.ts.map +1 -0
  40. package/dist/cli.js +361 -0
  41. package/dist/cli.js.map +1 -0
  42. package/dist/config-init.d.ts +16 -0
  43. package/dist/config-init.d.ts.map +1 -0
  44. package/dist/config-init.js +53 -0
  45. package/dist/config-init.js.map +1 -0
  46. package/dist/config.d.ts +11 -0
  47. package/dist/config.d.ts.map +1 -0
  48. package/dist/config.js +127 -0
  49. package/dist/config.js.map +1 -0
  50. package/dist/constants.d.ts +2 -0
  51. package/dist/constants.d.ts.map +1 -0
  52. package/dist/constants.js +2 -0
  53. package/dist/constants.js.map +1 -0
  54. package/dist/detect.d.ts +4 -0
  55. package/dist/detect.d.ts.map +1 -0
  56. package/dist/detect.js +244 -0
  57. package/dist/detect.js.map +1 -0
  58. package/dist/diff.d.ts +11 -0
  59. package/dist/diff.d.ts.map +1 -0
  60. package/dist/diff.js +198 -0
  61. package/dist/diff.js.map +1 -0
  62. package/dist/generate.d.ts +7 -0
  63. package/dist/generate.d.ts.map +1 -0
  64. package/dist/generate.js +71 -0
  65. package/dist/generate.js.map +1 -0
  66. package/dist/gitignore.d.ts +12 -0
  67. package/dist/gitignore.d.ts.map +1 -0
  68. package/dist/gitignore.js +106 -0
  69. package/dist/gitignore.js.map +1 -0
  70. package/dist/hooks.d.ts +22 -0
  71. package/dist/hooks.d.ts.map +1 -0
  72. package/dist/hooks.js +199 -0
  73. package/dist/hooks.js.map +1 -0
  74. package/dist/init.d.ts +24 -0
  75. package/dist/init.d.ts.map +1 -0
  76. package/dist/init.js +218 -0
  77. package/dist/init.js.map +1 -0
  78. package/dist/paths.d.ts +13 -0
  79. package/dist/paths.d.ts.map +1 -0
  80. package/dist/paths.js +18 -0
  81. package/dist/paths.js.map +1 -0
  82. package/dist/prompts.d.ts +9 -0
  83. package/dist/prompts.d.ts.map +1 -0
  84. package/dist/prompts.js +88 -0
  85. package/dist/prompts.js.map +1 -0
  86. package/dist/repo-stats.d.ts +10 -0
  87. package/dist/repo-stats.d.ts.map +1 -0
  88. package/dist/repo-stats.js +117 -0
  89. package/dist/repo-stats.js.map +1 -0
  90. package/dist/setup-wizard.d.ts +34 -0
  91. package/dist/setup-wizard.d.ts.map +1 -0
  92. package/dist/setup-wizard.js +251 -0
  93. package/dist/setup-wizard.js.map +1 -0
  94. package/dist/testing.d.ts +6 -0
  95. package/dist/testing.d.ts.map +1 -0
  96. package/dist/testing.js +24 -0
  97. package/dist/testing.js.map +1 -0
  98. package/dist/types.d.ts +156 -0
  99. package/dist/types.d.ts.map +1 -0
  100. package/dist/types.js +31 -0
  101. package/dist/types.js.map +1 -0
  102. package/dist/verify.d.ts +38 -0
  103. package/dist/verify.d.ts.map +1 -0
  104. package/dist/verify.js +254 -0
  105. package/dist/verify.js.map +1 -0
  106. package/package.json +52 -0
  107. package/src/templates/PROMPTS.md +6 -0
  108. package/src/templates/SKILL.md +253 -0
  109. package/src/templates/SUMMARY.md +29 -0
  110. package/src/templates/agents/agents-md/section.md +11 -0
  111. package/src/templates/agents/claude/SKILL.md +8 -0
  112. package/src/templates/agents/claude/settings.fragment.json +16 -0
  113. package/src/templates/agents/claude/testing-SKILL.md +9 -0
  114. package/src/templates/agents/cursor/SKILL.md +9 -0
  115. package/src/templates/agents/cursor/hooks.json +23 -0
  116. package/src/templates/agents/cursor/testing-SKILL.md +9 -0
  117. package/src/templates/agents/windsurf/SKILL.md +8 -0
  118. package/src/templates/agents/windsurf/hooks.json +10 -0
  119. package/src/templates/agents/windsurf/testing-SKILL.md +9 -0
  120. package/src/templates/hooks/after-push.sh +17 -0
  121. package/src/templates/hooks/block-commit.sh +29 -0
  122. package/src/templates/hooks/block-push.sh +29 -0
  123. package/src/templates/hooks/claude-pre-tool.sh +59 -0
  124. package/src/templates/hooks/git-pre-commit.sh +35 -0
  125. package/src/templates/hooks/git-pre-push.sh +53 -0
  126. package/src/templates/hooks/statusline.sh +3 -0
  127. package/src/templates/hooks/windsurf-pre-run.sh +39 -0
  128. package/src/templates/hooks.json +23 -0
  129. package/src/templates/testing-SKILL.md +33 -0
  130. package/src/templates/testme.config.json +32 -0
@@ -0,0 +1,253 @@
1
+ ---
2
+ name: testme
3
+ description: Generate and verify codebase comprehension tests before committing or pushing. Use when the user runs /testme, asks to commit or push, or when a hook blocks git commit/push.
4
+ disable-model-invocation: true
5
+ ---
6
+
7
+ # testme
8
+
9
+ > **Gate off?** Run `npx comp-gate testing status`. If the gate is disabled, do not run this workflow — tell the user to run `/testing` to re-enable.
10
+
11
+ Gate `git commit` (when `gateCommits` is enabled) and `git push` to protected branches behind a comprehension check. The agent generates reference answers, quizzes you in chat, then grades your replies by **conceptual alignment** — not keyword matching.
12
+
13
+ ## When to use
14
+
15
+ - User runs `/testme`
16
+ - User asks to commit or push to a protected branch
17
+ - Hook blocks a commit or push and asks for verification
18
+
19
+ ## Workflow
20
+
21
+ **Use conversational Q&A in chat.** Do not ask the user to manually edit `.testme/` JSON files.
22
+
23
+ ```
24
+ Task Progress:
25
+ - [ ] Step 1: Update PROMPTS.md with session changes
26
+ - [ ] Step 2: Run npx comp-gate generate
27
+ - [ ] Step 3: Read referenced files; write .testme/references.json
28
+ - [ ] Step 4: Ask each question in chat; collect answers from user replies
29
+ - [ ] Step 5: Grade semantically; write .testme/judgments.json; run npx comp-gate verify
30
+ - [ ] Step 6: Commit and push only after PASS
31
+ ```
32
+
33
+ ### Step 1: Update PROMPTS.md
34
+
35
+ Before generating questions, ensure `PROMPTS.md` documents what changed:
36
+
37
+ ```markdown
38
+ # Session Changes
39
+
40
+ ## src/auth.ts
41
+ - Added validateToken middleware; checks JWT expiry before route handlers
42
+ ```
43
+
44
+ Write bullets as you work. If empty, update from `git diff --stat` first.
45
+
46
+ ### Step 2: Generate questions
47
+
48
+ ```bash
49
+ npx comp-gate generate
50
+ ```
51
+
52
+ Reads `SUMMARY.md`, `PROMPTS.md`, and git diff. Writes `.testme/session.json`.
53
+
54
+ Announce how many questions were generated and list their ids/categories.
55
+
56
+ ### Step 3: Generate reference answers
57
+
58
+ Read `.testme/session.json`. For each question, read **only** files in `files[]`.
59
+
60
+ Write `.testme/references.json`:
61
+
62
+ ```json
63
+ {
64
+ "diffHash": "<same as session.json>",
65
+ "generatedAt": "<ISO timestamp>",
66
+ "references": {
67
+ "q1": "A complete reference answer explaining what changed and why, based on the code and PROMPTS.md.",
68
+ "q2": "A reference answer describing how the change fits the project architecture."
69
+ }
70
+ }
71
+ ```
72
+
73
+ Reference answers are the **gold standard** you will compare user replies against. Write them from your understanding of the code — not by copying PROMPTS.md bullets verbatim.
74
+
75
+ ### Step 4: Conversational Q&A (in chat)
76
+
77
+ Ask questions **one at a time**. Wait for the user's reply before asking the next.
78
+
79
+ **Format each question:**
80
+
81
+ ```
82
+ **Question 1 of N** · `q1` · changeRationale
83
+
84
+ What changed in src/auth.ts and why?
85
+
86
+ _Files: src/auth.ts_
87
+ ```
88
+
89
+ Rules:
90
+ - Show progress, question id, category, prompt verbatim, and referenced files
91
+ - Do **not** show reference answers or rubric terms to the user
92
+ - Nudge once if an answer is too vague: "Can you explain what changed and why?"
93
+ - Store each answer keyed by question id (`q1`, `q2`, …)
94
+
95
+ ### Step 5: Semantic grading and verify
96
+
97
+ For each question, compare the user's answer to the reference in `.testme/references.json`:
98
+
99
+ 1. **Summarize** the user's answer in 1–2 sentences (`userSummary`)
100
+ 2. **Score accuracy** from 0–100 (`accuracy`) — how well they understand what changed vs the reference
101
+ 3. **Judge alignment**: `high` (core concepts correct), `medium` (mostly right, minor gaps), `low` (wrong or too vague)
102
+ 4. **Pass** a question if `passed: true`, `accuracy >= passThreshold` (default 70 from config), and alignment is `high` or `medium`
103
+ 5. Do **not** fail answers for missing specific keywords — judge meaning, not wording
104
+
105
+ Write `.testme/answers.json` and `.testme/judgments.json`:
106
+
107
+ ```json
108
+ {
109
+ "diffHash": "<same as session.json>",
110
+ "gradedAt": "<ISO timestamp>",
111
+ "judgments": {
112
+ "q1": {
113
+ "passed": true,
114
+ "accuracy": 88,
115
+ "userSummary": "User explained the README now documents setup and the chat-based workflow.",
116
+ "alignment": "high",
117
+ "feedback": "Strong understanding of the documentation changes; minor detail on troubleshooting missing."
118
+ }
119
+ }
120
+ }
121
+ ```
122
+
123
+ Share grading feedback in chat for each question:
124
+ - accuracy score (0–100)
125
+ - alignment (`low` / `medium` / `high`)
126
+ - brief summary of what they got right or wrong
127
+
128
+ Then run:
129
+
130
+ ```bash
131
+ npx comp-gate verify
132
+ ```
133
+
134
+ **On PASS:** commit and push to protected branches are allowed.
135
+
136
+ **On FAIL:** re-ask only failed questions in chat, update answers + judgments, run `verify` again. Do not re-run `generate`.
137
+
138
+ ### Step 6: Commit and push
139
+
140
+ Only after verify passes:
141
+
142
+ ```bash
143
+ git commit -m "your message"
144
+ git push origin <protected-branch>
145
+ ```
146
+
147
+ ## Gate configuration
148
+
149
+ In `testme.config.json`:
150
+
151
+ ```json
152
+ {
153
+ "protectedBranches": ["main"],
154
+ "gateCommits": true,
155
+ "autoProtectCurrentBranch": true
156
+ }
157
+ ```
158
+
159
+ - `gateCommits: true` blocks `git commit` until `/testme` passes
160
+ - `autoProtectCurrentBranch: true` (default) also protects your current branch — no config edits when switching branches
161
+ - Pushes to protected branches are blocked with: `You must run the /testme skill before pushing to '<branch>'.`
162
+ - `npx comp-gate init` also installs **git** `pre-commit` / `pre-push` hooks (blocks the Cursor terminal and any other terminal)
163
+
164
+ ## Token efficiency rules
165
+
166
+ - Never scan the full repo for this workflow
167
+ - Read only files referenced in session questions
168
+ - Re-run verify after any last-minute edits (pass invalidates on diff change)
169
+
170
+ ## Grading mode
171
+
172
+ Default is **semantic** (`grading: "semantic"` in `testme.config.json`). Set `passThreshold` (default `70`) for minimum accuracy % per question. Legacy keyword mode: `"grading": "keywords"`.
173
+
174
+ ## SUMMARY.md
175
+
176
+ Update only when architecture, stack, or major conventions change — not every commit.
177
+
178
+ Add a `## Domain` section to steer auto-detection:
179
+
180
+ ```markdown
181
+ ## Domain
182
+
183
+ - Primary: machine learning
184
+ - Focus areas: model training, evaluation metrics, inference API
185
+ ```
186
+
187
+ ## Configure categories
188
+
189
+ Question count and knowledge areas are configured in `testme.config.json` (team defaults) with optional local overrides in `.testme/config.json`.
190
+
191
+ ### Checkbox-style categories
192
+
193
+ Set booleans in `categories` — `true` enables, `false` disables:
194
+
195
+ ```json
196
+ {
197
+ "questions": { "min": 2, "max": 5 },
198
+ "categories": {
199
+ "changeRationale": true,
200
+ "symbols": true,
201
+ "architecture": true,
202
+ "runtime": false,
203
+ "dataStructures": false,
204
+ "testing": true,
205
+ "machineLearning": false,
206
+ "cybersecurity": false
207
+ },
208
+ "autoDetect": true
209
+ }
210
+ ```
211
+
212
+ ### Core categories
213
+
214
+ `changeRationale`, `symbols`, `architecture`, `runtime`, `dataStructures`, `dependencies`, `testing`, `errorHandling`, `apiContracts`, `security`, `performance`, `database`
215
+
216
+ ### Domain categories (auto-suggested)
217
+
218
+ `machineLearning`, `cybersecurity`, `frontend`, `backend`, `devops`, `mobile`, `dataEngineering`
219
+
220
+ Run detection before editing config:
221
+
222
+ ```bash
223
+ npx comp-gate detect
224
+ npx comp-gate config init
225
+ npx comp-gate config show
226
+ ```
227
+
228
+ ### One-off overrides
229
+
230
+ ```bash
231
+ npx comp-gate generate --max-questions 3 --category changeRationale,runtime,testing
232
+ ```
233
+
234
+ ### Examples
235
+
236
+ **Machine learning project** — enable `machineLearning`, `dataStructures`; disable `cybersecurity`.
237
+
238
+ **Security tooling project** — enable `cybersecurity`, `security`; disable `machineLearning`.
239
+
240
+ Ask the user which categories matter if unclear, then update `testme.config.json`.
241
+
242
+ ## Troubleshooting
243
+
244
+ | Issue | Fix |
245
+ |-------|-----|
246
+ | Session stale | Re-run `npx comp-gate generate` |
247
+ | Missing terms | Add clearer bullets to `PROMPTS.md` |
248
+ | Commit blocked | `gateCommits` is on — run `/testme` before committing |
249
+ | Push blocked | Run `/testme` or `npx comp-gate generate` → answer → `verify` |
250
+ | Pass invalid | `npx comp-gate status` — verify then commit/push |
251
+ | Reset session | `npx comp-gate reset` |
252
+ | Verify failed | Re-ask failed questions; re-grade and update judgments.json |
253
+ | Missing judgments | Agent must grade semantically before running verify |
@@ -0,0 +1,29 @@
1
+ # Project Summary
2
+
3
+ Keep this file updated when architecture, stack, or major conventions change — not on every commit.
4
+
5
+ ## Stack
6
+
7
+ - Language:
8
+ - Framework:
9
+ - Runtime:
10
+
11
+ ## Architecture
12
+
13
+ - `src/` — application source
14
+ - `tests/` — test suites
15
+
16
+ ## Conventions
17
+
18
+ - Follow existing naming and import patterns in each directory.
19
+ - Prefer small, focused modules over large catch-all files.
20
+
21
+ ## Runtime Notes
22
+
23
+ - How to run locally:
24
+ - How to run tests:
25
+
26
+ ## Domain
27
+
28
+ - Primary:
29
+ - Focus areas:
@@ -0,0 +1,11 @@
1
+ ## testme comprehension gate
2
+
3
+ Before committing or pushing to a protected branch, run the testme workflow:
4
+
5
+ 1. Update `PROMPTS.md` with session change bullets per file.
6
+ 2. Run `npx comp-gate generate` to create questions in `.testme/session.json`.
7
+ 3. Answer each question in chat; the agent writes `.testme/answers.json` and `.testme/judgments.json`.
8
+ 4. Run `npx comp-gate verify` — on PASS, `.testme/pass.json` is written and git operations are allowed.
9
+ 5. After a successful push, `PROMPTS.md` resets automatically via hook.
10
+
11
+ Do not commit or push until `npx comp-gate verify` passes.
@@ -0,0 +1,8 @@
1
+ ---
2
+ name: testme
3
+ description: Generate and verify codebase comprehension tests before committing or pushing. Use when the user asks to commit or push, or when a hook blocks git commit/push.
4
+ ---
5
+
6
+ # testme
7
+
8
+ Use the shared workflow: update PROMPTS.md, run `npx comp-gate generate`, quiz the user in chat, grade semantically, then `npx comp-gate verify` before commit/push.
@@ -0,0 +1,16 @@
1
+ {
2
+ "hooks": {
3
+ "PreToolUse": [
4
+ {
5
+ "matcher": "Bash",
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": ".testme/hooks/claude-pre-tool.sh",
10
+ "timeout": 15
11
+ }
12
+ ]
13
+ }
14
+ ]
15
+ }
16
+ }
@@ -0,0 +1,9 @@
1
+ ---
2
+ name: testing
3
+ description: Toggle the testme comprehension gate on or off. Use when the user runs /testing or asks to enable/disable testme gating.
4
+ disable-model-invocation: true
5
+ ---
6
+
7
+ # testing
8
+
9
+ Run `npx comp-gate testing` (toggle), `on`, `off`, or `status`. Show the CLI banner output verbatim in chat.
@@ -0,0 +1,9 @@
1
+ ---
2
+ name: testme
3
+ description: Generate and verify codebase comprehension tests before committing or pushing. Use when the user runs /testme, asks to commit or push, or when a hook blocks git commit/push.
4
+ disable-model-invocation: true
5
+ ---
6
+
7
+ # testme
8
+
9
+ Use the shared workflow in the project `SKILL.md` template. Run `npx comp-gate generate`, quiz the user in chat, grade semantically, then `npx comp-gate verify` before commit/push.
@@ -0,0 +1,23 @@
1
+ {
2
+ "version": 1,
3
+ "hooks": {
4
+ "beforeShellExecution": [
5
+ {
6
+ "command": ".testme/hooks/block-commit.sh",
7
+ "matcher": "git\\s+commit",
8
+ "failClosed": true
9
+ },
10
+ {
11
+ "command": ".testme/hooks/block-push.sh",
12
+ "matcher": "git\\s+push",
13
+ "failClosed": true
14
+ }
15
+ ],
16
+ "afterShellExecution": [
17
+ {
18
+ "command": ".testme/hooks/after-push.sh",
19
+ "matcher": "git\\s+push"
20
+ }
21
+ ]
22
+ }
23
+ }
@@ -0,0 +1,9 @@
1
+ ---
2
+ name: testing
3
+ description: Toggle the testme comprehension gate on or off. Use when the user runs /testing or asks to enable/disable testme gating.
4
+ disable-model-invocation: true
5
+ ---
6
+
7
+ # testing
8
+
9
+ Run `npx comp-gate testing` (toggle), `on`, `off`, or `status`. Show the CLI banner output verbatim in chat.
@@ -0,0 +1,8 @@
1
+ ---
2
+ name: testme
3
+ description: Generate and verify codebase comprehension tests before committing or pushing. Use when the user asks to commit or push, or when a hook blocks git commit/push.
4
+ ---
5
+
6
+ # testme
7
+
8
+ Use the shared workflow: update PROMPTS.md, run `npx comp-gate generate`, quiz the user in chat, grade semantically, then `npx comp-gate verify` before commit/push.
@@ -0,0 +1,10 @@
1
+ {
2
+ "hooks": {
3
+ "pre_run_command": [
4
+ {
5
+ "command": ".testme/hooks/windsurf-pre-run.sh",
6
+ "show_output": true
7
+ }
8
+ ]
9
+ }
10
+ }
@@ -0,0 +1,9 @@
1
+ ---
2
+ name: testing
3
+ description: Toggle the testme comprehension gate on or off. Use when the user runs /testing or asks to enable/disable testme gating.
4
+ disable-model-invocation: true
5
+ ---
6
+
7
+ # testing
8
+
9
+ Run `npx comp-gate testing` (toggle), `on`, `off`, or `status`. Show the CLI banner output verbatim in chat.
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ input=$(cat)
5
+ command=$(node -e 'const i=JSON.parse(process.argv[1]); process.stdout.write(i.command||"")' "$input")
6
+ exit_code=$(node -e 'const i=JSON.parse(process.argv[1]); process.stdout.write(String(i.exit_code ?? i.exitCode ?? 1))' "$input")
7
+
8
+ if [ "$exit_code" != "0" ]; then
9
+ exit 0
10
+ fi
11
+
12
+ if ! echo "$command" | grep -qE '^git[[:space:]]+push'; then
13
+ exit 0
14
+ fi
15
+
16
+ npx --yes comp-gate hook after-push --command "$command" 2>/dev/null || true
17
+ exit 0
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ input=$(cat)
5
+ command=$(node -e 'const i=JSON.parse(process.argv[1]); process.stdout.write(i.command||"")' "$input")
6
+
7
+ if ! echo "$command" | grep -qE '^git[[:space:]]+commit'; then
8
+ echo '{"permission":"allow"}'
9
+ exit 0
10
+ fi
11
+
12
+ response=$(npx --yes comp-gate hook before-commit --command "$command" --json 2>/dev/null || true)
13
+
14
+ if [ -n "$response" ]; then
15
+ echo "$response"
16
+ if echo "$response" | grep -q '"permission"[[:space:]]*:[[:space:]]*"deny"'; then
17
+ exit 2
18
+ fi
19
+ exit 0
20
+ fi
21
+
22
+ cat <<'EOF'
23
+ {
24
+ "permission": "deny",
25
+ "user_message": "You must run the /testme skill before committing.",
26
+ "agent_message": "You must run the /testme skill before committing."
27
+ }
28
+ EOF
29
+ exit 2
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ input=$(cat)
5
+ command=$(node -e 'const i=JSON.parse(process.argv[1]); process.stdout.write(i.command||"")' "$input")
6
+
7
+ if ! echo "$command" | grep -qE '^git[[:space:]]+push'; then
8
+ echo '{"permission":"allow"}'
9
+ exit 0
10
+ fi
11
+
12
+ response=$(npx --yes comp-gate hook before-push --command "$command" --json 2>/dev/null || true)
13
+
14
+ if [ -n "$response" ]; then
15
+ echo "$response"
16
+ if echo "$response" | grep -q '"permission"[[:space:]]*:[[:space:]]*"deny"'; then
17
+ exit 2
18
+ fi
19
+ exit 0
20
+ fi
21
+
22
+ cat <<'EOF'
23
+ {
24
+ "permission": "deny",
25
+ "user_message": "You must run the /testme skill before pushing.",
26
+ "agent_message": "You must run the /testme skill before pushing."
27
+ }
28
+ EOF
29
+ exit 2
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ input=$(cat)
5
+ command=$(node -e '
6
+ const data = JSON.parse(process.argv[1]);
7
+ const tool = data.tool_name || "";
8
+ const toolInput = data.tool_input || {};
9
+ const cmd = toolInput.command || toolInput.cmd || "";
10
+ process.stdout.write(cmd);
11
+ ' "$input")
12
+
13
+ if [ -z "$command" ]; then
14
+ exit 0
15
+ fi
16
+
17
+ hook_kind=""
18
+ if echo "$command" | grep -qE '^git[[:space:]]+commit'; then
19
+ hook_kind="before-commit"
20
+ elif echo "$command" | grep -qE '^git[[:space:]]+push'; then
21
+ hook_kind="before-push"
22
+ else
23
+ exit 0
24
+ fi
25
+
26
+ response=$(npx --yes comp-gate hook "$hook_kind" --command "$command" --json 2>/dev/null || true)
27
+
28
+ if [ -n "$response" ] && echo "$response" | grep -q '"permission"[[:space:]]*:[[:space:]]*"deny"'; then
29
+ message=$(echo "$response" | node -e '
30
+ const data = JSON.parse(require("fs").readFileSync(0, "utf8"));
31
+ process.stdout.write(data.agent_message || data.user_message || "Blocked by testme.");
32
+ ')
33
+ node -e "
34
+ const reason = process.argv[1];
35
+ process.stdout.write(JSON.stringify({
36
+ hookSpecificOutput: {
37
+ hookEventName: 'PreToolUse',
38
+ permissionDecision: 'deny',
39
+ permissionDecisionReason: reason
40
+ }
41
+ }));
42
+ " "$message"
43
+ exit 0
44
+ fi
45
+
46
+ if [ -n "$response" ]; then
47
+ exit 0
48
+ fi
49
+
50
+ node -e '
51
+ process.stdout.write(JSON.stringify({
52
+ hookSpecificOutput: {
53
+ hookEventName: "PreToolUse",
54
+ permissionDecision: "deny",
55
+ permissionDecisionReason: "You must run the testme workflow before committing or pushing."
56
+ }
57
+ }));
58
+ '
59
+ exit 0
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ root="$(git rev-parse --show-toplevel)"
5
+ cd "$root"
6
+
7
+ run_comp_gate() {
8
+ if [ -x "$root/node_modules/.bin/comp-gate" ]; then
9
+ "$root/node_modules/.bin/comp-gate" "$@"
10
+ elif command -v comp-gate >/dev/null 2>&1; then
11
+ comp-gate "$@"
12
+ elif [ -x "$root/node_modules/.bin/testme" ]; then
13
+ "$root/node_modules/.bin/testme" "$@"
14
+ elif command -v testme >/dev/null 2>&1; then
15
+ testme "$@"
16
+ else
17
+ npx --yes comp-gate "$@"
18
+ fi
19
+ }
20
+
21
+ result=$(run_comp_gate hook before-commit --command "git commit" --json 2>/dev/null || true)
22
+
23
+ if [ -n "$result" ]; then
24
+ if echo "$result" | grep -q '"permission"[[:space:]]*:[[:space:]]*"deny"'; then
25
+ echo "$result" | node -e '
26
+ const input = JSON.parse(require("fs").readFileSync(0, "utf8"));
27
+ console.error(input.user_message ?? input.agent_message ?? "Commit blocked by testme.");
28
+ '
29
+ exit 1
30
+ fi
31
+ exit 0
32
+ fi
33
+
34
+ echo "You must run the /testme skill before committing." >&2
35
+ exit 1
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ root="$(git rev-parse --show-toplevel)"
5
+ cd "$root"
6
+
7
+ run_comp_gate() {
8
+ if [ -x "$root/node_modules/.bin/comp-gate" ]; then
9
+ "$root/node_modules/.bin/comp-gate" "$@"
10
+ elif command -v comp-gate >/dev/null 2>&1; then
11
+ comp-gate "$@"
12
+ elif [ -x "$root/node_modules/.bin/testme" ]; then
13
+ "$root/node_modules/.bin/testme" "$@"
14
+ elif command -v testme >/dev/null 2>&1; then
15
+ testme "$@"
16
+ else
17
+ npx --yes comp-gate "$@"
18
+ fi
19
+ }
20
+
21
+ zero="0000000000000000000000000000000000000000"
22
+
23
+ while read -r local_ref local_sha remote_ref remote_sha; do
24
+ if [ -z "${local_ref:-}" ]; then
25
+ continue
26
+ fi
27
+
28
+ if [ "$local_sha" = "$zero" ]; then
29
+ continue
30
+ fi
31
+
32
+ case "$remote_ref" in
33
+ refs/heads/*) ;;
34
+ *) continue ;;
35
+ esac
36
+
37
+ result=$(run_comp_gate hook before-push-ref --remote-ref "$remote_ref" --json 2>/dev/null || true)
38
+
39
+ if [ -z "$result" ]; then
40
+ echo "You must run the /testme skill before pushing." >&2
41
+ exit 1
42
+ fi
43
+
44
+ if echo "$result" | grep -q '"permission"[[:space:]]*:[[:space:]]*"deny"'; then
45
+ echo "$result" | node -e '
46
+ const input = JSON.parse(require("fs").readFileSync(0, "utf8"));
47
+ console.error(input.user_message ?? input.agent_message ?? "Push blocked by testme.");
48
+ '
49
+ exit 1
50
+ fi
51
+ done
52
+
53
+ exit 0
@@ -0,0 +1,3 @@
1
+ #!/bin/sh
2
+ cd "$(git rev-parse --show-toplevel 2>/dev/null)" || exit 0
3
+ npx comp-gate statusline 2>/dev/null || true
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ input=$(cat)
5
+ command=$(node -e '
6
+ const data = JSON.parse(process.argv[1]);
7
+ const toolInfo = data.tool_info || {};
8
+ process.stdout.write(toolInfo.command_line || "");
9
+ ' "$input")
10
+
11
+ if [ -z "$command" ]; then
12
+ exit 0
13
+ fi
14
+
15
+ hook_kind=""
16
+ if echo "$command" | grep -qE '^git[[:space:]]+commit'; then
17
+ hook_kind="before-commit"
18
+ elif echo "$command" | grep -qE '^git[[:space:]]+push'; then
19
+ hook_kind="before-push"
20
+ else
21
+ exit 0
22
+ fi
23
+
24
+ response=$(npx --yes comp-gate hook "$hook_kind" --command "$command" --json 2>/dev/null || true)
25
+
26
+ if [ -n "$response" ] && echo "$response" | grep -q '"permission"[[:space:]]*:[[:space:]]*"deny"'; then
27
+ echo "$response" | node -e '
28
+ const data = JSON.parse(require("fs").readFileSync(0, "utf8"));
29
+ console.error(data.user_message || data.agent_message || "Blocked by testme.");
30
+ ' >&2
31
+ exit 2
32
+ fi
33
+
34
+ if [ -n "$response" ]; then
35
+ exit 0
36
+ fi
37
+
38
+ echo "You must run the testme workflow before committing or pushing." >&2
39
+ exit 2