oh-my-opencode 4.4.0 → 4.5.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 (218) hide show
  1. package/.agents/command/get-unpublished-changes.md +148 -0
  2. package/.agents/command/omomomo.md +37 -0
  3. package/.agents/command/publish.md +376 -0
  4. package/.agents/command/remove-deadcode.md +221 -0
  5. package/.agents/command/security-research.md +16 -0
  6. package/.agents/skills/get-unpublished-changes/SKILL.md +24 -0
  7. package/.agents/skills/github-triage/SKILL.md +587 -0
  8. package/.agents/skills/github-triage/scripts/gh_fetch.py +398 -0
  9. package/.agents/skills/hyperplan/SKILL.md +450 -0
  10. package/.agents/skills/omomomo/SKILL.md +36 -0
  11. package/.agents/skills/pre-publish-review/SKILL.md +407 -0
  12. package/.agents/skills/publish/SKILL.md +428 -0
  13. package/.agents/skills/remove-deadcode/SKILL.md +216 -0
  14. package/.agents/skills/security-research/SKILL.md +204 -0
  15. package/.agents/skills/work-with-pr/SKILL.md +360 -0
  16. package/.agents/skills/work-with-pr-workspace/evals/evals.json +76 -0
  17. package/.agents/skills/work-with-pr-workspace/iteration-1/benchmark.json +138 -0
  18. package/.agents/skills/work-with-pr-workspace/iteration-1/benchmark.md +42 -0
  19. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-1/eval_metadata.json +57 -0
  20. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-1/with_skill/grading.json +15 -0
  21. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-1/with_skill/outputs/code-changes.md +454 -0
  22. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-1/with_skill/outputs/execution-plan.md +136 -0
  23. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-1/with_skill/outputs/pr-description.md +47 -0
  24. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-1/with_skill/outputs/verification-strategy.md +163 -0
  25. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-1/with_skill/timing.json +1 -0
  26. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-1/without_skill/grading.json +15 -0
  27. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-1/without_skill/outputs/code-changes.md +615 -0
  28. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-1/without_skill/outputs/execution-plan.md +99 -0
  29. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-1/without_skill/outputs/pr-description.md +50 -0
  30. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-1/without_skill/outputs/verification-strategy.md +111 -0
  31. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-1/without_skill/timing.json +1 -0
  32. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-2/eval_metadata.json +37 -0
  33. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-2/with_skill/grading.json +11 -0
  34. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-2/with_skill/outputs/code-changes.md +205 -0
  35. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-2/with_skill/outputs/execution-plan.md +78 -0
  36. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-2/with_skill/outputs/pr-description.md +42 -0
  37. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-2/with_skill/outputs/verification-strategy.md +87 -0
  38. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-2/with_skill/timing.json +1 -0
  39. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-2/without_skill/grading.json +11 -0
  40. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-2/without_skill/outputs/code-changes.md +334 -0
  41. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-2/without_skill/outputs/execution-plan.md +86 -0
  42. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-2/without_skill/outputs/pr-description.md +23 -0
  43. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-2/without_skill/outputs/verification-strategy.md +119 -0
  44. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-2/without_skill/timing.json +1 -0
  45. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-3/eval_metadata.json +32 -0
  46. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-3/with_skill/grading.json +10 -0
  47. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-3/with_skill/outputs/code-changes.md +221 -0
  48. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-3/with_skill/outputs/execution-plan.md +104 -0
  49. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-3/with_skill/outputs/pr-description.md +41 -0
  50. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-3/with_skill/outputs/verification-strategy.md +84 -0
  51. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-3/with_skill/timing.json +1 -0
  52. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-3/without_skill/grading.json +10 -0
  53. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-3/without_skill/outputs/code-changes.md +342 -0
  54. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-3/without_skill/outputs/execution-plan.md +131 -0
  55. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-3/without_skill/outputs/pr-description.md +39 -0
  56. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-3/without_skill/outputs/verification-strategy.md +128 -0
  57. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-3/without_skill/timing.json +1 -0
  58. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-4/eval_metadata.json +32 -0
  59. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-4/with_skill/grading.json +10 -0
  60. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-4/with_skill/outputs/code-changes.md +143 -0
  61. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-4/with_skill/outputs/execution-plan.md +82 -0
  62. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-4/with_skill/outputs/pr-description.md +51 -0
  63. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-4/with_skill/outputs/verification-strategy.md +69 -0
  64. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-4/with_skill/timing.json +1 -0
  65. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-4/without_skill/grading.json +10 -0
  66. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-4/without_skill/outputs/code-changes.md +252 -0
  67. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-4/without_skill/outputs/execution-plan.md +83 -0
  68. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-4/without_skill/outputs/pr-description.md +33 -0
  69. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-4/without_skill/outputs/verification-strategy.md +101 -0
  70. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-4/without_skill/timing.json +1 -0
  71. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-5/eval_metadata.json +32 -0
  72. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-5/with_skill/grading.json +10 -0
  73. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-5/with_skill/outputs/code-changes.md +387 -0
  74. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-5/with_skill/outputs/execution-plan.md +112 -0
  75. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-5/with_skill/outputs/pr-description.md +51 -0
  76. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-5/with_skill/outputs/verification-strategy.md +75 -0
  77. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-5/with_skill/timing.json +1 -0
  78. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-5/without_skill/grading.json +10 -0
  79. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-5/without_skill/outputs/code-changes.md +529 -0
  80. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-5/without_skill/outputs/execution-plan.md +127 -0
  81. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-5/without_skill/outputs/pr-description.md +42 -0
  82. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-5/without_skill/outputs/verification-strategy.md +120 -0
  83. package/.agents/skills/work-with-pr-workspace/iteration-1/eval-5/without_skill/timing.json +1 -0
  84. package/.agents/skills/work-with-pr-workspace/iteration-1/review.html +1326 -0
  85. package/.opencode/command/get-unpublished-changes.md +148 -0
  86. package/.opencode/command/omomomo.md +37 -0
  87. package/.opencode/command/publish.md +376 -0
  88. package/.opencode/command/remove-deadcode.md +221 -0
  89. package/.opencode/command/security-research.md +16 -0
  90. package/.opencode/skills/github-triage/SKILL.md +587 -0
  91. package/.opencode/skills/github-triage/scripts/gh_fetch.py +398 -0
  92. package/.opencode/skills/hyperplan/SKILL.md +450 -0
  93. package/.opencode/skills/pre-publish-review/SKILL.md +407 -0
  94. package/.opencode/skills/work-with-pr/SKILL.md +360 -0
  95. package/.opencode/skills/work-with-pr-workspace/evals/evals.json +76 -0
  96. package/.opencode/skills/work-with-pr-workspace/iteration-1/benchmark.json +138 -0
  97. package/.opencode/skills/work-with-pr-workspace/iteration-1/benchmark.md +42 -0
  98. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-1/eval_metadata.json +57 -0
  99. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-1/with_skill/grading.json +15 -0
  100. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-1/with_skill/outputs/code-changes.md +454 -0
  101. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-1/with_skill/outputs/execution-plan.md +136 -0
  102. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-1/with_skill/outputs/pr-description.md +47 -0
  103. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-1/with_skill/outputs/verification-strategy.md +163 -0
  104. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-1/with_skill/timing.json +1 -0
  105. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-1/without_skill/grading.json +15 -0
  106. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-1/without_skill/outputs/code-changes.md +615 -0
  107. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-1/without_skill/outputs/execution-plan.md +99 -0
  108. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-1/without_skill/outputs/pr-description.md +50 -0
  109. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-1/without_skill/outputs/verification-strategy.md +111 -0
  110. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-1/without_skill/timing.json +1 -0
  111. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-2/eval_metadata.json +37 -0
  112. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-2/with_skill/grading.json +11 -0
  113. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-2/with_skill/outputs/code-changes.md +205 -0
  114. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-2/with_skill/outputs/execution-plan.md +78 -0
  115. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-2/with_skill/outputs/pr-description.md +42 -0
  116. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-2/with_skill/outputs/verification-strategy.md +87 -0
  117. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-2/with_skill/timing.json +1 -0
  118. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-2/without_skill/grading.json +11 -0
  119. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-2/without_skill/outputs/code-changes.md +334 -0
  120. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-2/without_skill/outputs/execution-plan.md +86 -0
  121. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-2/without_skill/outputs/pr-description.md +23 -0
  122. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-2/without_skill/outputs/verification-strategy.md +119 -0
  123. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-2/without_skill/timing.json +1 -0
  124. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-3/eval_metadata.json +32 -0
  125. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-3/with_skill/grading.json +10 -0
  126. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-3/with_skill/outputs/code-changes.md +221 -0
  127. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-3/with_skill/outputs/execution-plan.md +104 -0
  128. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-3/with_skill/outputs/pr-description.md +41 -0
  129. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-3/with_skill/outputs/verification-strategy.md +84 -0
  130. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-3/with_skill/timing.json +1 -0
  131. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-3/without_skill/grading.json +10 -0
  132. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-3/without_skill/outputs/code-changes.md +342 -0
  133. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-3/without_skill/outputs/execution-plan.md +131 -0
  134. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-3/without_skill/outputs/pr-description.md +39 -0
  135. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-3/without_skill/outputs/verification-strategy.md +128 -0
  136. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-3/without_skill/timing.json +1 -0
  137. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-4/eval_metadata.json +32 -0
  138. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-4/with_skill/grading.json +10 -0
  139. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-4/with_skill/outputs/code-changes.md +143 -0
  140. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-4/with_skill/outputs/execution-plan.md +82 -0
  141. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-4/with_skill/outputs/pr-description.md +51 -0
  142. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-4/with_skill/outputs/verification-strategy.md +69 -0
  143. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-4/with_skill/timing.json +1 -0
  144. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-4/without_skill/grading.json +10 -0
  145. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-4/without_skill/outputs/code-changes.md +252 -0
  146. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-4/without_skill/outputs/execution-plan.md +83 -0
  147. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-4/without_skill/outputs/pr-description.md +33 -0
  148. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-4/without_skill/outputs/verification-strategy.md +101 -0
  149. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-4/without_skill/timing.json +1 -0
  150. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-5/eval_metadata.json +32 -0
  151. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-5/with_skill/grading.json +10 -0
  152. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-5/with_skill/outputs/code-changes.md +387 -0
  153. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-5/with_skill/outputs/execution-plan.md +112 -0
  154. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-5/with_skill/outputs/pr-description.md +51 -0
  155. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-5/with_skill/outputs/verification-strategy.md +75 -0
  156. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-5/with_skill/timing.json +1 -0
  157. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-5/without_skill/grading.json +10 -0
  158. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-5/without_skill/outputs/code-changes.md +529 -0
  159. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-5/without_skill/outputs/execution-plan.md +127 -0
  160. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-5/without_skill/outputs/pr-description.md +42 -0
  161. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-5/without_skill/outputs/verification-strategy.md +120 -0
  162. package/.opencode/skills/work-with-pr-workspace/iteration-1/eval-5/without_skill/timing.json +1 -0
  163. package/.opencode/skills/work-with-pr-workspace/iteration-1/review.html +1326 -0
  164. package/README.ja.md +1 -1
  165. package/README.ko.md +1 -1
  166. package/README.md +1 -1
  167. package/README.ru.md +1 -1
  168. package/README.zh-cn.md +1 -1
  169. package/dist/agents/atlas/agent.d.ts +6 -6
  170. package/dist/agents/prometheus/gemini.d.ts +0 -11
  171. package/dist/agents/prometheus/gpt.d.ts +0 -10
  172. package/dist/agents/prometheus/system-prompt.d.ts +2 -20
  173. package/dist/agents/types.d.ts +1 -16
  174. package/dist/cli/index.js +50 -17
  175. package/dist/config/schema/agent-names.d.ts +3 -3
  176. package/dist/config/schema/agent-overrides.d.ts +208 -208
  177. package/dist/config/schema/categories.d.ts +28 -28
  178. package/dist/config/schema/fallback-models.d.ts +20 -20
  179. package/dist/config/schema/oh-my-opencode-config.d.ts +208 -208
  180. package/dist/features/background-agent/parent-wake-notifier.d.ts +8 -1
  181. package/dist/help/schema/acp.d.ts +95 -0
  182. package/dist/help/schema/doctor.d.ts +147 -0
  183. package/dist/help/schema/sandbox.d.ts +74 -0
  184. package/dist/help/schema/status.d.ts +139 -0
  185. package/dist/hooks/keyword-detector/analyze/default.d.ts +1 -1
  186. package/dist/hooks/keyword-detector/hyperplan/default.d.ts +1 -1
  187. package/dist/hooks/keyword-detector/search/default.d.ts +1 -1
  188. package/dist/hooks/keyword-detector/team/default.d.ts +2 -7
  189. package/dist/hooks/keyword-detector/ultrawork/default.d.ts +1 -9
  190. package/dist/hooks/keyword-detector/ultrawork/gemini.d.ts +1 -16
  191. package/dist/hooks/keyword-detector/ultrawork/gpt.d.ts +1 -10
  192. package/dist/hooks/keyword-detector/ultrawork/planner.d.ts +1 -5
  193. package/dist/hooks/ralph-loop/no-progress-turn-detector.d.ts +7 -0
  194. package/dist/hooks/ralph-loop/pending-verification-handler.d.ts +1 -0
  195. package/dist/hooks/ralph-loop/types.d.ts +1 -0
  196. package/dist/hooks/runtime-fallback/error-classifier.d.ts +1 -0
  197. package/dist/index.js +51910 -50310
  198. package/dist/shared/prompt-async-gate/pending-tool-turn.d.ts +1 -0
  199. package/dist/shared/prompt-async-gate/types.d.ts +4 -3
  200. package/package.json +19 -13
  201. package/dist/agents/atlas/default-prompt-sections.d.ts +0 -6
  202. package/dist/agents/atlas/default.d.ts +0 -2
  203. package/dist/agents/atlas/gemini-prompt-sections.d.ts +0 -6
  204. package/dist/agents/atlas/gemini.d.ts +0 -2
  205. package/dist/agents/atlas/gpt-prompt-sections.d.ts +0 -6
  206. package/dist/agents/atlas/gpt.d.ts +0 -2
  207. package/dist/agents/atlas/kimi-prompt-sections.d.ts +0 -6
  208. package/dist/agents/atlas/kimi.d.ts +0 -2
  209. package/dist/agents/atlas/opus-4-7-prompt-sections.d.ts +0 -6
  210. package/dist/agents/atlas/opus-4-7.d.ts +0 -2
  211. package/dist/agents/atlas/shared-prompt.d.ts +0 -9
  212. package/dist/agents/prometheus/behavioral-summary.d.ts +0 -6
  213. package/dist/agents/prometheus/high-accuracy-mode.d.ts +0 -6
  214. package/dist/agents/prometheus/identity-constraints.d.ts +0 -7
  215. package/dist/agents/prometheus/interview-mode.d.ts +0 -7
  216. package/dist/agents/prometheus/plan-generation.d.ts +0 -7
  217. package/dist/agents/prometheus/plan-template.d.ts +0 -7
  218. package/dist/agents/prometheus/spec-driven-mode.d.ts +0 -7
@@ -0,0 +1,51 @@
1
+ # PR: fix(comment-checker): relax regex to stop flagging legitimate Note: comments
2
+
3
+ **Title:** `fix(comment-checker): relax regex to stop flagging legitimate Note: comments`
4
+ **Base:** `dev`
5
+ **Branch:** `fix/comment-checker-note-false-positive`
6
+
7
+ ---
8
+
9
+ ## Summary
10
+
11
+ - Add `exclude_patterns` config to comment-checker schema, allowing users to whitelist comment prefixes (e.g. `["^Note:", "^TODO:"]`) that should not be flagged as AI slop
12
+ - Thread the exclude patterns through `cli-runner.ts` and `cli.ts` to the Go binary via `--exclude-pattern` flags
13
+ - Add test cases covering false positive scenarios: legitimate technical notes, RFC references, and AI memo detection with/without exclusions
14
+
15
+ ## Context
16
+
17
+ The comment-checker Go binary (`go-claude-code-comment-checker` v0.4.1) contains the regex `(?i)^[\s#/*-]*note:\s*\w` which matches ALL comments starting with "Note:" followed by a word character. This produces false positives for legitimate technical comments:
18
+
19
+ ```typescript
20
+ // Note: Thread-safe by design <- flagged as AI slop
21
+ # Note: See RFC 7231 for details <- flagged as AI slop
22
+ // Note: This edge case requires... <- flagged as AI slop
23
+ ```
24
+
25
+ These are standard engineering comments, not AI agent memos.
26
+
27
+ ## Changes
28
+
29
+ | File | Change |
30
+ |------|--------|
31
+ | `src/config/schema/comment-checker.ts` | Add `exclude_patterns: string[]` optional field |
32
+ | `src/hooks/comment-checker/cli.ts` | Pass `--exclude-pattern` flags to binary |
33
+ | `src/hooks/comment-checker/cli-runner.ts` | Thread `excludePatterns` through `processWithCli` and `processApplyPatchEditsWithCli` |
34
+ | `src/hooks/comment-checker/hook.ts` | Pass `config.exclude_patterns` to CLI runner calls |
35
+ | `src/hooks/comment-checker/cli.test.ts` | Add 6 new test cases for false positive scenarios |
36
+ | `src/hooks/comment-checker/hook.apply-patch.test.ts` | Add test verifying exclude_patterns config threading |
37
+
38
+ ## Usage
39
+
40
+ ```jsonc
41
+ // .opencode/oh-my-opencode.jsonc
42
+ {
43
+ "comment_checker": {
44
+ "exclude_patterns": ["^Note:", "^TODO:", "^FIXME:"]
45
+ }
46
+ }
47
+ ```
48
+
49
+ ## Related
50
+
51
+ - Go binary repo: `code-yeongyu/go-claude-code-comment-checker` (needs corresponding `--exclude-pattern` flag support)
@@ -0,0 +1,75 @@
1
+ # Verification Strategy
2
+
3
+ ## Gate A: CI (`ci.yml`)
4
+
5
+ ### Pre-push local validation
6
+ ```bash
7
+ bun run typecheck # Zero new type errors
8
+ bun test src/hooks/comment-checker/ # All comment-checker tests pass
9
+ bun test src/config/ # Config schema tests pass
10
+ bun run build # Build succeeds
11
+ ```
12
+
13
+ ### CI pipeline expectations
14
+ | Step | Expected |
15
+ |------|----------|
16
+ | Tests (mock-heavy isolated) | Pass - comment-checker tests run in isolation |
17
+ | Tests (batch) | Pass - no regression in other hook tests |
18
+ | Typecheck (`tsc --noEmit`) | Pass - new `exclude_patterns` field is `z.array(z.string()).optional()` |
19
+ | Build | Pass - schema change is additive |
20
+ | Schema auto-commit | May trigger if schema JSON is auto-generated |
21
+
22
+ ### Failure handling
23
+ - Type errors: Fix in worktree, new commit, push
24
+ - Test failures: Investigate, fix, new commit, push
25
+ - Schema auto-commit conflicts: Rebase on dev, resolve, force push
26
+
27
+ ## Gate B: review-work (5-agent)
28
+
29
+ ### Agent expectations
30
+
31
+ | Agent | Role | Focus Areas |
32
+ |-------|------|-------------|
33
+ | Oracle (goal) | Verify fix addresses false positive issue | Config schema matches PR description, exclude_patterns flows correctly |
34
+ | Oracle (code quality) | Code quality check | Factory pattern consistency, no catch-all files, <200 LOC |
35
+ | Oracle (security) | Security review | Regex patterns are user-supplied - verify no ReDoS risk from config |
36
+ | Hephaestus (QA) | Hands-on execution | Run tests, verify mock binary tests actually exercise the exclude flow |
37
+ | Hephaestus (context) | Context mining | Check git history for related changes, verify no conflicting PRs |
38
+
39
+ ### Potential review-work flags
40
+ 1. **ReDoS concern**: User-supplied regex patterns in `exclude_patterns` could theoretically cause ReDoS in the Go binary. Mitigation: the patterns are passed as CLI args, Go's `regexp` package is RE2-based (linear time guarantee).
41
+ 2. **Breaking change check**: Adding optional field to config schema is non-breaking (Zod `z.optional()` fills default).
42
+ 3. **Go binary dependency**: The `--exclude-pattern` flag must exist in the Go binary for this to work. If the binary doesn't support it yet, the patterns are silently ignored (binary treats unknown flags differently).
43
+
44
+ ### Failure handling
45
+ - If any Oracle flags issues: address feedback, push new commit, re-run review-work
46
+ - If Hephaestus QA finds test gaps: add missing tests, push, re-verify
47
+
48
+ ## Gate C: Cubic (`cubic-dev-ai[bot]`)
49
+
50
+ ### Expected review focus
51
+ - Schema change additive and backward-compatible
52
+ - Parameter threading is mechanical and low-risk
53
+ - Tests use mock binaries (shell scripts) - standard project pattern per `cli.test.ts`
54
+
55
+ ### Success criteria
56
+ - `cubic-dev-ai[bot]` comments "No issues found"
57
+ - No requested changes
58
+
59
+ ### Failure handling
60
+ - If Cubic flags issues: read comment, address, push fix, re-request review via:
61
+ ```bash
62
+ gh pr review --request-changes --body "Addressed Cubic feedback"
63
+ ```
64
+ Then push fix and wait for re-review.
65
+
66
+ ## Post-merge verification
67
+
68
+ 1. Confirm squash merge landed on `dev`
69
+ 2. Verify CI passes on `dev` branch post-merge
70
+ 3. Clean up worktree:
71
+ ```bash
72
+ git worktree remove ../omo-wt/fix/comment-checker-note-false-positive
73
+ git branch -d fix/comment-checker-note-false-positive
74
+ ```
75
+ 4. File issue on `code-yeongyu/go-claude-code-comment-checker` to add `--exclude-pattern` flag support and relax the `note:` regex upstream
@@ -0,0 +1 @@
1
+ {"total_tokens": null, "duration_ms": 570000, "total_duration_seconds": 570}
@@ -0,0 +1,10 @@
1
+ {
2
+ "run_id": "eval-5-without_skill",
3
+ "expectations": [
4
+ {"text": "Plan uses git worktree in a sibling directory", "passed": false, "evidence": "git checkout -b, no worktree"},
5
+ {"text": "References actual comment-checker hook files", "passed": true, "evidence": "Deep analysis of Go binary, tree-sitter, formatter.go, agent_memo.go with line numbers"},
6
+ {"text": "Adds test cases for Note: false positive scenarios", "passed": true, "evidence": "Detailed test cases distinguishing legit vs AI slop patterns"},
7
+ {"text": "Verification loop includes all 3 gates", "passed": false, "evidence": "Only bun test and typecheck. No review-work or Cubic."},
8
+ {"text": "Only modifies regex and adds tests — no unrelated changes", "passed": true, "evidence": "Adds allowed-prefix filter module — focused approach with config extension"}
9
+ ]
10
+ }
@@ -0,0 +1,529 @@
1
+ # Code Changes: comment-checker false positive fix
2
+
3
+ ## Change 1: Extend config schema
4
+
5
+ **File: `src/config/schema/comment-checker.ts`**
6
+
7
+ ```typescript
8
+ // BEFORE
9
+ import { z } from "zod"
10
+
11
+ export const CommentCheckerConfigSchema = z.object({
12
+ /** Custom prompt to replace the default warning message. Use {{comments}} placeholder for detected comments XML. */
13
+ custom_prompt: z.string().optional(),
14
+ })
15
+
16
+ export type CommentCheckerConfig = z.infer<typeof CommentCheckerConfigSchema>
17
+ ```
18
+
19
+ ```typescript
20
+ // AFTER
21
+ import { z } from "zod"
22
+
23
+ const DEFAULT_ALLOWED_COMMENT_PREFIXES = [
24
+ "note:",
25
+ "todo:",
26
+ "fixme:",
27
+ "hack:",
28
+ "xxx:",
29
+ "warning:",
30
+ "important:",
31
+ "bug:",
32
+ "optimize:",
33
+ "workaround:",
34
+ "safety:",
35
+ "security:",
36
+ "perf:",
37
+ "see:",
38
+ "ref:",
39
+ "cf.",
40
+ ]
41
+
42
+ export const CommentCheckerConfigSchema = z.object({
43
+ /** Custom prompt to replace the default warning message. Use {{comments}} placeholder for detected comments XML. */
44
+ custom_prompt: z.string().optional(),
45
+ /** Comment prefixes considered legitimate (not AI slop). Case-insensitive. Defaults include Note:, TODO:, FIXME:, etc. */
46
+ allowed_comment_prefixes: z.array(z.string()).optional().default(DEFAULT_ALLOWED_COMMENT_PREFIXES),
47
+ })
48
+
49
+ export type CommentCheckerConfig = z.infer<typeof CommentCheckerConfigSchema>
50
+ ```
51
+
52
+ ## Change 2: Create allowed-prefix-filter module
53
+
54
+ **File: `src/hooks/comment-checker/allowed-prefix-filter.ts`** (NEW)
55
+
56
+ ```typescript
57
+ const COMMENT_XML_REGEX = /<comment\s+line-number="\d+">([\s\S]*?)<\/comment>/g
58
+ const COMMENTS_BLOCK_REGEX = /<comments\s+file="[^"]*">\s*([\s\S]*?)\s*<\/comments>/g
59
+ const AGENT_MEMO_HEADER_REGEX = /🚨 AGENT MEMO COMMENT DETECTED.*?---\n\n/s
60
+
61
+ function stripCommentPrefix(text: string): string {
62
+ let stripped = text.trim()
63
+ for (const prefix of ["//", "#", "/*", "--", "*"]) {
64
+ if (stripped.startsWith(prefix)) {
65
+ stripped = stripped.slice(prefix.length).trim()
66
+ break
67
+ }
68
+ }
69
+ return stripped
70
+ }
71
+
72
+ function isAllowedComment(commentText: string, allowedPrefixes: string[]): boolean {
73
+ const stripped = stripCommentPrefix(commentText).toLowerCase()
74
+ return allowedPrefixes.some((prefix) => stripped.startsWith(prefix.toLowerCase()))
75
+ }
76
+
77
+ function extractCommentTexts(xmlBlock: string): string[] {
78
+ const texts: string[] = []
79
+ let match: RegExpExecArray | null
80
+ const regex = new RegExp(COMMENT_XML_REGEX.source, COMMENT_XML_REGEX.flags)
81
+ while ((match = regex.exec(xmlBlock)) !== null) {
82
+ texts.push(match[1])
83
+ }
84
+ return texts
85
+ }
86
+
87
+ export function filterAllowedComments(
88
+ message: string,
89
+ allowedPrefixes: string[],
90
+ ): { hasRemainingComments: boolean; filteredMessage: string } {
91
+ if (!message || allowedPrefixes.length === 0) {
92
+ return { hasRemainingComments: true, filteredMessage: message }
93
+ }
94
+
95
+ const commentTexts = extractCommentTexts(message)
96
+
97
+ if (commentTexts.length === 0) {
98
+ return { hasRemainingComments: true, filteredMessage: message }
99
+ }
100
+
101
+ const disallowedComments = commentTexts.filter(
102
+ (text) => !isAllowedComment(text, allowedPrefixes),
103
+ )
104
+
105
+ if (disallowedComments.length === 0) {
106
+ return { hasRemainingComments: false, filteredMessage: "" }
107
+ }
108
+
109
+ if (disallowedComments.length === commentTexts.length) {
110
+ return { hasRemainingComments: true, filteredMessage: message }
111
+ }
112
+
113
+ let filteredMessage = message
114
+ for (const text of commentTexts) {
115
+ if (isAllowedComment(text, allowedPrefixes)) {
116
+ const escapedText = text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
117
+ const lineRegex = new RegExp(`\\s*<comment\\s+line-number="\\d+">${escapedText}</comment>\\n?`, "g")
118
+ filteredMessage = filteredMessage.replace(lineRegex, "")
119
+ }
120
+ }
121
+
122
+ filteredMessage = filteredMessage.replace(AGENT_MEMO_HEADER_REGEX, "")
123
+
124
+ return { hasRemainingComments: true, filteredMessage }
125
+ }
126
+ ```
127
+
128
+ ## Change 3: Thread config through cli-runner.ts
129
+
130
+ **File: `src/hooks/comment-checker/cli-runner.ts`**
131
+
132
+ ```typescript
133
+ // BEFORE (processWithCli signature and body)
134
+ export async function processWithCli(
135
+ input: { tool: string; sessionID: string; callID: string },
136
+ pendingCall: PendingCall,
137
+ output: { output: string },
138
+ cliPath: string,
139
+ customPrompt: string | undefined,
140
+ debugLog: (...args: unknown[]) => void,
141
+ ): Promise<void> {
142
+ await withCommentCheckerLock(async () => {
143
+ // ...
144
+ const result = await runCommentChecker(hookInput, cliPath, customPrompt)
145
+ if (result.hasComments && result.message) {
146
+ debugLog("CLI detected comments, appending message")
147
+ output.output += `\n\n${result.message}`
148
+ } else {
149
+ debugLog("CLI: no comments detected")
150
+ }
151
+ }, undefined, debugLog)
152
+ }
153
+ ```
154
+
155
+ ```typescript
156
+ // AFTER
157
+ import { filterAllowedComments } from "./allowed-prefix-filter"
158
+
159
+ export async function processWithCli(
160
+ input: { tool: string; sessionID: string; callID: string },
161
+ pendingCall: PendingCall,
162
+ output: { output: string },
163
+ cliPath: string,
164
+ customPrompt: string | undefined,
165
+ allowedPrefixes: string[],
166
+ debugLog: (...args: unknown[]) => void,
167
+ ): Promise<void> {
168
+ await withCommentCheckerLock(async () => {
169
+ void input
170
+ debugLog("using CLI mode with path:", cliPath)
171
+
172
+ const hookInput: HookInput = {
173
+ session_id: pendingCall.sessionID,
174
+ tool_name: pendingCall.tool.charAt(0).toUpperCase() + pendingCall.tool.slice(1),
175
+ transcript_path: "",
176
+ cwd: process.cwd(),
177
+ hook_event_name: "PostToolUse",
178
+ tool_input: {
179
+ file_path: pendingCall.filePath,
180
+ content: pendingCall.content,
181
+ old_string: pendingCall.oldString,
182
+ new_string: pendingCall.newString,
183
+ edits: pendingCall.edits,
184
+ },
185
+ }
186
+
187
+ const result = await runCommentChecker(hookInput, cliPath, customPrompt)
188
+
189
+ if (result.hasComments && result.message) {
190
+ const { hasRemainingComments, filteredMessage } = filterAllowedComments(
191
+ result.message,
192
+ allowedPrefixes,
193
+ )
194
+ if (hasRemainingComments && filteredMessage) {
195
+ debugLog("CLI detected comments, appending filtered message")
196
+ output.output += `\n\n${filteredMessage}`
197
+ } else {
198
+ debugLog("CLI: all detected comments matched allowed prefixes, suppressing")
199
+ }
200
+ } else {
201
+ debugLog("CLI: no comments detected")
202
+ }
203
+ }, undefined, debugLog)
204
+ }
205
+
206
+ // Same change applied to processApplyPatchEditsWithCli - add allowedPrefixes parameter
207
+ export async function processApplyPatchEditsWithCli(
208
+ sessionID: string,
209
+ edits: ApplyPatchEdit[],
210
+ output: { output: string },
211
+ cliPath: string,
212
+ customPrompt: string | undefined,
213
+ allowedPrefixes: string[],
214
+ debugLog: (...args: unknown[]) => void,
215
+ ): Promise<void> {
216
+ debugLog("processing apply_patch edits:", edits.length)
217
+
218
+ for (const edit of edits) {
219
+ await withCommentCheckerLock(async () => {
220
+ const hookInput: HookInput = {
221
+ session_id: sessionID,
222
+ tool_name: "Edit",
223
+ transcript_path: "",
224
+ cwd: process.cwd(),
225
+ hook_event_name: "PostToolUse",
226
+ tool_input: {
227
+ file_path: edit.filePath,
228
+ old_string: edit.before,
229
+ new_string: edit.after,
230
+ },
231
+ }
232
+
233
+ const result = await runCommentChecker(hookInput, cliPath, customPrompt)
234
+
235
+ if (result.hasComments && result.message) {
236
+ const { hasRemainingComments, filteredMessage } = filterAllowedComments(
237
+ result.message,
238
+ allowedPrefixes,
239
+ )
240
+ if (hasRemainingComments && filteredMessage) {
241
+ debugLog("CLI detected comments for apply_patch file:", edit.filePath)
242
+ output.output += `\n\n${filteredMessage}`
243
+ }
244
+ }
245
+ }, undefined, debugLog)
246
+ }
247
+ }
248
+ ```
249
+
250
+ ## Change 4: Update hook.ts to pass config
251
+
252
+ **File: `src/hooks/comment-checker/hook.ts`**
253
+
254
+ ```typescript
255
+ // BEFORE (in tool.execute.after handler, around line 177)
256
+ await processWithCli(input, pendingCall, output, cliPath, config?.custom_prompt, debugLog)
257
+
258
+ // AFTER
259
+ const allowedPrefixes = config?.allowed_comment_prefixes ?? []
260
+ await processWithCli(input, pendingCall, output, cliPath, config?.custom_prompt, allowedPrefixes, debugLog)
261
+ ```
262
+
263
+ ```typescript
264
+ // BEFORE (in apply_patch section, around line 147-154)
265
+ await processApplyPatchEditsWithCli(
266
+ input.sessionID,
267
+ edits,
268
+ output,
269
+ cliPath,
270
+ config?.custom_prompt,
271
+ debugLog,
272
+ )
273
+
274
+ // AFTER
275
+ const allowedPrefixes = config?.allowed_comment_prefixes ?? []
276
+ await processApplyPatchEditsWithCli(
277
+ input.sessionID,
278
+ edits,
279
+ output,
280
+ cliPath,
281
+ config?.custom_prompt,
282
+ allowedPrefixes,
283
+ debugLog,
284
+ )
285
+ ```
286
+
287
+ ## Change 5: Test file for allowed-prefix-filter
288
+
289
+ **File: `src/hooks/comment-checker/allowed-prefix-filter.test.ts`** (NEW)
290
+
291
+ ```typescript
292
+ import { describe, test, expect } from "bun:test"
293
+
294
+ import { filterAllowedComments } from "./allowed-prefix-filter"
295
+
296
+ const DEFAULT_PREFIXES = [
297
+ "note:", "todo:", "fixme:", "hack:", "xxx:", "warning:",
298
+ "important:", "bug:", "optimize:", "workaround:", "safety:",
299
+ "security:", "perf:", "see:", "ref:", "cf.",
300
+ ]
301
+
302
+ function buildMessage(comments: { line: number; text: string }[], filePath = "/tmp/test.ts"): string {
303
+ const xml = comments
304
+ .map((c) => `\t<comment line-number="${c.line}">${c.text}</comment>`)
305
+ .join("\n")
306
+ return `COMMENT/DOCSTRING DETECTED - IMMEDIATE ACTION REQUIRED\n\n` +
307
+ `Your recent changes contain comments or docstrings, which triggered this hook.\n` +
308
+ `Detected comments/docstrings:\n` +
309
+ `<comments file="${filePath}">\n${xml}\n</comments>\n`
310
+ }
311
+
312
+ describe("allowed-prefix-filter", () => {
313
+ describe("#given default allowed prefixes", () => {
314
+ describe("#when message contains only Note: comments", () => {
315
+ test("#then should suppress the entire message", () => {
316
+ const message = buildMessage([
317
+ { line: 5, text: "// Note: Thread-safe implementation" },
318
+ { line: 12, text: "// NOTE: See RFC 7231 for details" },
319
+ ])
320
+
321
+ const result = filterAllowedComments(message, DEFAULT_PREFIXES)
322
+
323
+ expect(result.hasRemainingComments).toBe(false)
324
+ expect(result.filteredMessage).toBe("")
325
+ })
326
+ })
327
+
328
+ describe("#when message contains only TODO/FIXME comments", () => {
329
+ test("#then should suppress the entire message", () => {
330
+ const message = buildMessage([
331
+ { line: 3, text: "// TODO: implement caching" },
332
+ { line: 7, text: "// FIXME: race condition here" },
333
+ { line: 15, text: "# HACK: workaround for upstream bug" },
334
+ ])
335
+
336
+ const result = filterAllowedComments(message, DEFAULT_PREFIXES)
337
+
338
+ expect(result.hasRemainingComments).toBe(false)
339
+ expect(result.filteredMessage).toBe("")
340
+ })
341
+ })
342
+
343
+ describe("#when message contains only AI slop comments", () => {
344
+ test("#then should keep the entire message", () => {
345
+ const message = buildMessage([
346
+ { line: 2, text: "// Added new validation logic" },
347
+ { line: 8, text: "// Refactored for better performance" },
348
+ ])
349
+
350
+ const result = filterAllowedComments(message, DEFAULT_PREFIXES)
351
+
352
+ expect(result.hasRemainingComments).toBe(true)
353
+ expect(result.filteredMessage).toBe(message)
354
+ })
355
+ })
356
+
357
+ describe("#when message contains mix of legitimate and slop comments", () => {
358
+ test("#then should keep message but remove allowed comment XML entries", () => {
359
+ const message = buildMessage([
360
+ { line: 5, text: "// Note: Thread-safe implementation" },
361
+ { line: 10, text: "// Changed from old API to new API" },
362
+ ])
363
+
364
+ const result = filterAllowedComments(message, DEFAULT_PREFIXES)
365
+
366
+ expect(result.hasRemainingComments).toBe(true)
367
+ expect(result.filteredMessage).not.toContain("Thread-safe implementation")
368
+ expect(result.filteredMessage).toContain("Changed from old API to new API")
369
+ })
370
+ })
371
+
372
+ describe("#when Note: comment has lowercase prefix", () => {
373
+ test("#then should still be treated as allowed (case-insensitive)", () => {
374
+ const message = buildMessage([
375
+ { line: 1, text: "// note: this is case insensitive" },
376
+ ])
377
+
378
+ const result = filterAllowedComments(message, DEFAULT_PREFIXES)
379
+
380
+ expect(result.hasRemainingComments).toBe(false)
381
+ })
382
+ })
383
+
384
+ describe("#when comment uses hash prefix", () => {
385
+ test("#then should strip prefix before matching", () => {
386
+ const message = buildMessage([
387
+ { line: 1, text: "# Note: Python style comment" },
388
+ { line: 5, text: "# TODO: something to do" },
389
+ ])
390
+
391
+ const result = filterAllowedComments(message, DEFAULT_PREFIXES)
392
+
393
+ expect(result.hasRemainingComments).toBe(false)
394
+ })
395
+ })
396
+
397
+ describe("#when comment has Security: prefix", () => {
398
+ test("#then should be treated as allowed", () => {
399
+ const message = buildMessage([
400
+ { line: 1, text: "// Security: validate input before processing" },
401
+ ])
402
+
403
+ const result = filterAllowedComments(message, DEFAULT_PREFIXES)
404
+
405
+ expect(result.hasRemainingComments).toBe(false)
406
+ })
407
+ })
408
+
409
+ describe("#when comment has Warning: prefix", () => {
410
+ test("#then should be treated as allowed", () => {
411
+ const message = buildMessage([
412
+ { line: 1, text: "// WARNING: This mutates the input array" },
413
+ ])
414
+
415
+ const result = filterAllowedComments(message, DEFAULT_PREFIXES)
416
+
417
+ expect(result.hasRemainingComments).toBe(false)
418
+ })
419
+ })
420
+ })
421
+
422
+ describe("#given empty allowed prefixes", () => {
423
+ describe("#when any comments are detected", () => {
424
+ test("#then should pass through unfiltered", () => {
425
+ const message = buildMessage([
426
+ { line: 1, text: "// Note: this should pass through" },
427
+ ])
428
+
429
+ const result = filterAllowedComments(message, [])
430
+
431
+ expect(result.hasRemainingComments).toBe(true)
432
+ expect(result.filteredMessage).toBe(message)
433
+ })
434
+ })
435
+ })
436
+
437
+ describe("#given custom allowed prefixes", () => {
438
+ describe("#when comment matches custom prefix", () => {
439
+ test("#then should suppress it", () => {
440
+ const message = buildMessage([
441
+ { line: 1, text: "// PERF: O(n log n) complexity" },
442
+ ])
443
+
444
+ const result = filterAllowedComments(message, ["perf:"])
445
+
446
+ expect(result.hasRemainingComments).toBe(false)
447
+ })
448
+ })
449
+ })
450
+
451
+ describe("#given empty message", () => {
452
+ describe("#when filterAllowedComments is called", () => {
453
+ test("#then should return hasRemainingComments true with empty string", () => {
454
+ const result = filterAllowedComments("", DEFAULT_PREFIXES)
455
+
456
+ expect(result.hasRemainingComments).toBe(true)
457
+ expect(result.filteredMessage).toBe("")
458
+ })
459
+ })
460
+ })
461
+
462
+ describe("#given message with agent memo header", () => {
463
+ describe("#when all flagged comments are legitimate Note: comments", () => {
464
+ test("#then should suppress agent memo header along with comments", () => {
465
+ const message =
466
+ "🚨 AGENT MEMO COMMENT DETECTED - CODE SMELL ALERT 🚨\n\n" +
467
+ "⚠️ AGENT MEMO COMMENTS DETECTED - THIS IS A CODE SMELL ⚠️\n\n" +
468
+ "You left \"memo-style\" comments...\n\n---\n\n" +
469
+ "Your recent changes contain comments...\n" +
470
+ "Detected comments/docstrings:\n" +
471
+ '<comments file="/tmp/test.ts">\n' +
472
+ '\t<comment line-number="5">// Note: Thread-safe</comment>\n' +
473
+ "</comments>\n"
474
+
475
+ const result = filterAllowedComments(message, DEFAULT_PREFIXES)
476
+
477
+ expect(result.hasRemainingComments).toBe(false)
478
+ expect(result.filteredMessage).toBe("")
479
+ })
480
+ })
481
+ })
482
+ })
483
+ ```
484
+
485
+ ## Change 6: Update existing test for new parameter
486
+
487
+ **File: `src/hooks/comment-checker/hook.apply-patch.test.ts`**
488
+
489
+ The `processApplyPatchEditsWithCli` mock needs to account for the new `allowedPrefixes` parameter:
490
+
491
+ ```typescript
492
+ // BEFORE (line 58)
493
+ expect(processApplyPatchEditsWithCli).toHaveBeenCalledWith(
494
+ "ses_test",
495
+ [
496
+ { filePath: "/repo/src/a.ts", before: "const a = 1\n", after: "// comment\nconst a = 1\n" },
497
+ { filePath: "/repo/src/new.ts", before: "const b = 1\n", after: "// moved comment\nconst b = 1\n" },
498
+ ],
499
+ expect.any(Object),
500
+ "/tmp/fake-comment-checker",
501
+ undefined,
502
+ expect.any(Function),
503
+ )
504
+
505
+ // AFTER - add allowed_comment_prefixes argument
506
+ expect(processApplyPatchEditsWithCli).toHaveBeenCalledWith(
507
+ "ses_test",
508
+ [
509
+ { filePath: "/repo/src/a.ts", before: "const a = 1\n", after: "// comment\nconst a = 1\n" },
510
+ { filePath: "/repo/src/new.ts", before: "const b = 1\n", after: "// moved comment\nconst b = 1\n" },
511
+ ],
512
+ expect.any(Object),
513
+ "/tmp/fake-comment-checker",
514
+ undefined,
515
+ expect.any(Array),
516
+ expect.any(Function),
517
+ )
518
+ ```
519
+
520
+ ## Summary of all touched files
521
+
522
+ | File | Action | Description |
523
+ |------|--------|-------------|
524
+ | `src/config/schema/comment-checker.ts` | Modified | Add `allowed_comment_prefixes` with defaults |
525
+ | `src/hooks/comment-checker/allowed-prefix-filter.ts` | **New** | Post-processing filter for legitimate comment prefixes |
526
+ | `src/hooks/comment-checker/allowed-prefix-filter.test.ts` | **New** | 11 test cases covering false positives and edge cases |
527
+ | `src/hooks/comment-checker/cli-runner.ts` | Modified | Thread `allowedPrefixes` param, apply filter after binary result |
528
+ | `src/hooks/comment-checker/hook.ts` | Modified | Pass `allowed_comment_prefixes` from config to CLI runner |
529
+ | `src/hooks/comment-checker/hook.apply-patch.test.ts` | Modified | Update mock assertions for new parameter |