@tech-leads-club/harness-toolkit 0.2.1

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 (300) hide show
  1. package/CHANGELOG.md +95 -0
  2. package/LICENSE +84 -0
  3. package/NOTICE +9 -0
  4. package/README.md +480 -0
  5. package/bin/tlc +10 -0
  6. package/bin/tlc-build +80 -0
  7. package/bin/tlc-cli.ts +1509 -0
  8. package/bin/tlc-exec +10 -0
  9. package/bin/tlc-exec.cmd +4 -0
  10. package/bin/tlc-exec.d.mts +60 -0
  11. package/bin/tlc-exec.mjs +248 -0
  12. package/bin/tlc.cmd +4 -0
  13. package/bin/tlc.mjs +7 -0
  14. package/bin/write-user-hooks.d.mts +40 -0
  15. package/bin/write-user-hooks.mjs +123 -0
  16. package/capabilities/catalog.json +418 -0
  17. package/config.example.json +51 -0
  18. package/dist/compact-before.mjs +7839 -0
  19. package/dist/doctor.mjs +8263 -0
  20. package/dist/help-topic.mjs +82 -0
  21. package/dist/init-project.mjs +993 -0
  22. package/dist/install-runtime.mjs +969 -0
  23. package/dist/lessons-cli.mjs +7258 -0
  24. package/dist/obs-cli.mjs +7025 -0
  25. package/dist/price-lookup.mjs +221 -0
  26. package/dist/prompt-submit.mjs +7860 -0
  27. package/dist/refresh-model-prices.mjs +158 -0
  28. package/dist/response-after.mjs +7879 -0
  29. package/dist/run.mjs +7830 -0
  30. package/dist/session-end.mjs +7937 -0
  31. package/dist/session-start.mjs +8056 -0
  32. package/dist/shim.mjs +52 -0
  33. package/dist/stop.mjs +8494 -0
  34. package/dist/subagent-start.mjs +7861 -0
  35. package/dist/subagent-stop.mjs +7851 -0
  36. package/dist/support.mjs +7045 -0
  37. package/dist/tlc-cli.mjs +8063 -0
  38. package/dist/tool-after.mjs +8113 -0
  39. package/dist/tool-before.mjs +7985 -0
  40. package/dist/tool-failure.mjs +7850 -0
  41. package/dist/uninstall-runtime.mjs +1307 -0
  42. package/docs/architecture.md +270 -0
  43. package/docs/concepts.md +562 -0
  44. package/docs/coverage.md +55 -0
  45. package/docs/decisions/ad-001.md +32 -0
  46. package/docs/decisions/ad-002.md +51 -0
  47. package/docs/decisions/ad-003.md +30 -0
  48. package/docs/decisions/ad-004.md +37 -0
  49. package/docs/decisions/ad-005.md +36 -0
  50. package/docs/decisions/ad-006.md +49 -0
  51. package/docs/decisions/ad-007.md +36 -0
  52. package/docs/decisions/ad-008.md +54 -0
  53. package/docs/decisions/ad-009.md +61 -0
  54. package/docs/decisions/ad-010.md +45 -0
  55. package/docs/decisions/ad-011.md +59 -0
  56. package/docs/decisions/ad-012.md +71 -0
  57. package/docs/decisions/ad-013.md +87 -0
  58. package/docs/decisions/ad-014.md +56 -0
  59. package/docs/decisions/ad-015.md +33 -0
  60. package/docs/decisions/ad-016.md +98 -0
  61. package/docs/decisions/ad-017.md +65 -0
  62. package/docs/decisions/ad-018.md +77 -0
  63. package/docs/decisions/ad-019.md +75 -0
  64. package/docs/decisions/ad-020.md +88 -0
  65. package/docs/decisions/ad-021.md +57 -0
  66. package/docs/decisions/ad-022.md +120 -0
  67. package/docs/decisions/ad-023.md +87 -0
  68. package/docs/decisions/ad-024.md +85 -0
  69. package/docs/decisions/ad-025.md +92 -0
  70. package/docs/decisions/ad-026.md +131 -0
  71. package/docs/decisions/ad-027.md +90 -0
  72. package/docs/decisions/ad-028.md +90 -0
  73. package/docs/decisions/ad-029.md +73 -0
  74. package/docs/decisions/ad-030.md +97 -0
  75. package/docs/decisions/ad-031.md +94 -0
  76. package/docs/decisions/ad-032.md +83 -0
  77. package/docs/decisions/ad-033.md +89 -0
  78. package/docs/decisions/ad-034.md +86 -0
  79. package/docs/decisions/ad-035.md +86 -0
  80. package/docs/decisions/ad-036.md +68 -0
  81. package/docs/decisions/ad-037.md +47 -0
  82. package/docs/decisions/ad-038.md +52 -0
  83. package/docs/decisions/ad-039.md +69 -0
  84. package/docs/decisions/ad-040.md +89 -0
  85. package/docs/decisions/ad-041.md +98 -0
  86. package/docs/decisions/ad-042.md +82 -0
  87. package/docs/decisions/ad-043.md +79 -0
  88. package/docs/decisions/ad-044.md +61 -0
  89. package/docs/decisions/ad-045.md +94 -0
  90. package/docs/decisions/ad-046.md +111 -0
  91. package/docs/decisions/ad-047.md +96 -0
  92. package/docs/decisions/ad-048.md +85 -0
  93. package/docs/decisions/ad-049.md +66 -0
  94. package/docs/decisions/ad-050.md +94 -0
  95. package/docs/decisions/ad-051.md +69 -0
  96. package/docs/decisions/ad-052.md +69 -0
  97. package/docs/decisions/ad-053.md +78 -0
  98. package/docs/decisions/ad-054.md +98 -0
  99. package/docs/decisions/ad-055.md +74 -0
  100. package/docs/decisions/ad-056.md +85 -0
  101. package/docs/decisions/ad-057.md +68 -0
  102. package/docs/decisions/ad-058.md +97 -0
  103. package/docs/decisions/ad-059.md +82 -0
  104. package/docs/decisions/ad-060.md +75 -0
  105. package/docs/decisions/ad-061.md +68 -0
  106. package/docs/decisions/ad-062.md +72 -0
  107. package/docs/decisions/ad-063.md +84 -0
  108. package/docs/decisions/ad-064.md +79 -0
  109. package/docs/decisions/ad-065.md +81 -0
  110. package/docs/decisions/ad-066.md +111 -0
  111. package/docs/decisions/ad-067.md +64 -0
  112. package/docs/decisions/ad-068.md +79 -0
  113. package/docs/decisions/ad-069.md +74 -0
  114. package/docs/decisions/ad-070.md +86 -0
  115. package/docs/decisions/ad-071.md +93 -0
  116. package/docs/decisions/ad-072.md +82 -0
  117. package/docs/decisions/ad-073.md +102 -0
  118. package/docs/decisions/ad-074.md +91 -0
  119. package/docs/decisions/ad-075.md +79 -0
  120. package/docs/decisions/ad-076.md +102 -0
  121. package/docs/decisions/ad-077.md +94 -0
  122. package/docs/decisions/ad-078.md +84 -0
  123. package/docs/decisions/ad-079.md +73 -0
  124. package/docs/decisions/ad-080.md +86 -0
  125. package/docs/decisions/ad-081.md +70 -0
  126. package/docs/decisions/ad-082.md +79 -0
  127. package/docs/decisions/ad-083.md +88 -0
  128. package/docs/decisions/index.md +111 -0
  129. package/docs/diagnose.md +248 -0
  130. package/docs/index.md +52 -0
  131. package/docs/init.md +101 -0
  132. package/docs/lessons.md +294 -0
  133. package/docs/log.md +139 -0
  134. package/docs/measure.md +178 -0
  135. package/docs/providers/claude-code.md +118 -0
  136. package/docs/providers/cursor.md +110 -0
  137. package/docs/providers/index.md +71 -0
  138. package/docs/troubleshooting.md +138 -0
  139. package/model-aliases.json +12 -0
  140. package/model-prices.cursor.json +410 -0
  141. package/model-prices.json +1 -0
  142. package/package.json +57 -0
  143. package/skills/harness-init/SKILL.md +241 -0
  144. package/skills/harness-init/evals/trigger_evals.json +86 -0
  145. package/skills/harness-init/references/capabilities.md +113 -0
  146. package/src/contracts/capabilities.ts +30 -0
  147. package/src/contracts/decision.ts +21 -0
  148. package/src/contracts/effort.ts +15 -0
  149. package/src/contracts/harness-event.ts +87 -0
  150. package/src/contracts/index.ts +6 -0
  151. package/src/contracts/policy-defaults.ts +14 -0
  152. package/src/contracts/wiring.ts +20 -0
  153. package/src/core/attest/attest.service.ts +0 -0
  154. package/src/core/capability/capability.service.ts +62 -0
  155. package/src/core/capability/capability.store.ts +51 -0
  156. package/src/core/capability/capability.types.ts +56 -0
  157. package/src/core/comment-policy/comment-policy.service.ts +307 -0
  158. package/src/core/comment-policy/comment-policy.types.ts +6 -0
  159. package/src/core/comment-policy/comment-resolvability.ts +134 -0
  160. package/src/core/comment-policy/comment-syntax.catalog.ts +310 -0
  161. package/src/core/comment-policy/comment-syntax.store.ts +65 -0
  162. package/src/core/comment-policy/comment-syntax.types.ts +24 -0
  163. package/src/core/core.facade.ts +461 -0
  164. package/src/core/duplication/duplication.service.ts +219 -0
  165. package/src/core/floor/floor.catalog.ts +54 -0
  166. package/src/core/floor/floor.paths.ts +90 -0
  167. package/src/core/floor/floor.policy-surface.ts +311 -0
  168. package/src/core/floor/floor.service.ts +306 -0
  169. package/src/core/floor/floor.tokenize.ts +179 -0
  170. package/src/core/floor/floor.verb.ts +28 -0
  171. package/src/core/floor/index.ts +1 -0
  172. package/src/core/gate/gate.artifact.ts +157 -0
  173. package/src/core/gate/gate.command.ts +130 -0
  174. package/src/core/gate/gate.findings.ts +201 -0
  175. package/src/core/gate/gate.inputs.ts +0 -0
  176. package/src/core/gate/gate.lock.ts +283 -0
  177. package/src/core/gate/gate.service.ts +28 -0
  178. package/src/core/gate/gate.types.ts +67 -0
  179. package/src/core/handoff/handoff.service.ts +43 -0
  180. package/src/core/handoff/handoff.store.ts +59 -0
  181. package/src/core/handoff/handoff.types.ts +89 -0
  182. package/src/core/index.ts +52 -0
  183. package/src/core/integrity/state-seal.ts +81 -0
  184. package/src/core/lesson/lesson.authored.ts +96 -0
  185. package/src/core/lesson/lesson.credit.ts +51 -0
  186. package/src/core/lesson/lesson.garden.ts +283 -0
  187. package/src/core/lesson/lesson.link.ts +93 -0
  188. package/src/core/lesson/lesson.score.ts +61 -0
  189. package/src/core/lesson/lesson.select.ts +209 -0
  190. package/src/core/lesson/lesson.service.ts +110 -0
  191. package/src/core/lesson/lesson.store.ts +317 -0
  192. package/src/core/lesson/lesson.sync.ts +70 -0
  193. package/src/core/lesson/lesson.types.ts +92 -0
  194. package/src/core/lesson/lesson.validity.ts +44 -0
  195. package/src/core/observability/observability.report.ts +326 -0
  196. package/src/core/observability/observability.service.ts +328 -0
  197. package/src/core/observability/observability.store.ts +269 -0
  198. package/src/core/observability/observability.types.ts +193 -0
  199. package/src/core/observability/observability.why.ts +206 -0
  200. package/src/core/observe/observe.service.ts +76 -0
  201. package/src/core/plan/plan.detect.ts +47 -0
  202. package/src/core/plan/plan.service.ts +81 -0
  203. package/src/core/plan/plan.types.ts +25 -0
  204. package/src/core/policy/policy.defaults.ts +103 -0
  205. package/src/core/policy/policy.guard.ts +34 -0
  206. package/src/core/policy/policy.integrity.ts +238 -0
  207. package/src/core/policy/policy.loader.ts +118 -0
  208. package/src/core/policy/policy.operator.ts +82 -0
  209. package/src/core/policy/policy.posture.ts +79 -0
  210. package/src/core/policy/policy.rails.ts +45 -0
  211. package/src/core/policy/policy.types.ts +157 -0
  212. package/src/core/presence/presence.service.ts +111 -0
  213. package/src/core/presence/presence.store.ts +59 -0
  214. package/src/core/presence/presence.types.ts +9 -0
  215. package/src/core/release/release.decisions.ts +147 -0
  216. package/src/core/release/release.seen.ts +38 -0
  217. package/src/core/shell-policy/shell-policy.service.ts +215 -0
  218. package/src/core/shell-policy/shell-policy.stall.ts +57 -0
  219. package/src/core/shell-policy/shell-policy.types.ts +26 -0
  220. package/src/core/ship/ship.ledger.ts +76 -0
  221. package/src/core/ship/ship.service.ts +137 -0
  222. package/src/core/ship/ship.types.ts +19 -0
  223. package/src/core/stagnation/stagnation.resolution.ts +87 -0
  224. package/src/core/stagnation/stagnation.service.ts +20 -0
  225. package/src/core/stagnation/stagnation.store.ts +49 -0
  226. package/src/core/stagnation/stagnation.types.ts +12 -0
  227. package/src/core/subagent-policy/subagent-policy.parent-model.ts +202 -0
  228. package/src/core/subagent-policy/subagent-policy.service.ts +139 -0
  229. package/src/core/subagent-policy/subagent-policy.types.ts +22 -0
  230. package/src/core/supply-chain/supply-chain.catalog.ts +51 -0
  231. package/src/core/supply-chain/supply-chain.service.ts +217 -0
  232. package/src/core/turn/turn.activity.ts +94 -0
  233. package/src/core/turn/turn.autopilot.ts +131 -0
  234. package/src/core/turn/turn.failure-signals.ts +193 -0
  235. package/src/core/turn/turn.loop-counter.ts +71 -0
  236. package/src/core/turn/turn.types.ts +14 -0
  237. package/src/core/untrusted/untrusted.detect.ts +53 -0
  238. package/src/core/untrusted/untrusted.recall.ts +87 -0
  239. package/src/core/untrusted/untrusted.service.ts +129 -0
  240. package/src/core/untrusted/untrusted.store.ts +75 -0
  241. package/src/core/untrusted/untrusted.types.ts +42 -0
  242. package/src/entrypoints/compact-before.ts +14 -0
  243. package/src/entrypoints/prompt-submit.ts +25 -0
  244. package/src/entrypoints/response-after.ts +60 -0
  245. package/src/entrypoints/run.ts +179 -0
  246. package/src/entrypoints/session-end.ts +58 -0
  247. package/src/entrypoints/session-start.ts +172 -0
  248. package/src/entrypoints/shim.ts +46 -0
  249. package/src/entrypoints/stop.ts +876 -0
  250. package/src/entrypoints/subagent-start.ts +16 -0
  251. package/src/entrypoints/subagent-stop.ts +32 -0
  252. package/src/entrypoints/support.ts +182 -0
  253. package/src/entrypoints/tool-after.ts +111 -0
  254. package/src/entrypoints/tool-before.ts +186 -0
  255. package/src/entrypoints/tool-failure.ts +26 -0
  256. package/src/platform/backoff.ts +49 -0
  257. package/src/platform/cli-output.ts +30 -0
  258. package/src/platform/env-scope.ts +22 -0
  259. package/src/platform/fs-atomic.ts +142 -0
  260. package/src/platform/fs-jsonl.ts +24 -0
  261. package/src/platform/git.ts +187 -0
  262. package/src/platform/paths.ts +80 -0
  263. package/src/platform/pricing.ts +229 -0
  264. package/src/platform/process.ts +64 -0
  265. package/src/platform/sanitize.ts +23 -0
  266. package/src/platform/screen.ts +46 -0
  267. package/src/platform/style.ts +103 -0
  268. package/src/providers/claude/claude.capabilities.ts +25 -0
  269. package/src/providers/claude/claude.detect.ts +14 -0
  270. package/src/providers/claude/claude.inbound.ts +252 -0
  271. package/src/providers/claude/claude.lessons-view.ts +33 -0
  272. package/src/providers/claude/claude.outbound.ts +65 -0
  273. package/src/providers/claude/claude.policy-defaults.ts +9 -0
  274. package/src/providers/claude/claude.transcript.ts +62 -0
  275. package/src/providers/claude/claude.wiring.ts +245 -0
  276. package/src/providers/claude/index.ts +17 -0
  277. package/src/providers/cursor/cursor.capabilities.ts +28 -0
  278. package/src/providers/cursor/cursor.detect.ts +14 -0
  279. package/src/providers/cursor/cursor.inbound.ts +203 -0
  280. package/src/providers/cursor/cursor.lessons-view.ts +30 -0
  281. package/src/providers/cursor/cursor.outbound.ts +43 -0
  282. package/src/providers/cursor/cursor.policy-defaults.ts +9 -0
  283. package/src/providers/cursor/cursor.wiring.ts +214 -0
  284. package/src/providers/cursor/index.ts +17 -0
  285. package/src/providers/index.ts +9 -0
  286. package/src/providers/provider.degrade.ts +152 -0
  287. package/src/providers/provider.port.ts +20 -0
  288. package/src/providers/provider.registry.ts +28 -0
  289. package/tools/doctor.ts +631 -0
  290. package/tools/help-topic.ts +74 -0
  291. package/tools/init-project.ts +277 -0
  292. package/tools/install-runtime.ts +164 -0
  293. package/tools/lessons-cli.ts +474 -0
  294. package/tools/obs-cli.ts +175 -0
  295. package/tools/price-lookup.ts +57 -0
  296. package/tools/refresh-model-prices.ts +210 -0
  297. package/tools/test-env.mjs +28 -0
  298. package/tools/test-env.names.d.mts +1 -0
  299. package/tools/test-env.names.mjs +14 -0
  300. package/tools/uninstall-runtime.ts +463 -0
@@ -0,0 +1,310 @@
1
+ import type { CommentSyntaxEntry } from "./comment-syntax.types.ts";
2
+
3
+ /**
4
+ * why: the whole per-language knowledge of the comment gate, as one table. It replaced three hand-written regexes
5
+ * and a ten-extension list; adding a language is an entry here and nothing else
6
+ * ([/decisions/ad-058.md](/decisions/ad-058.md)).
7
+ *
8
+ * invariant: a module rather than a JSON file read at runtime. A hook is a process, so a data file would be one
9
+ * more read on every invocation and one more path to resolve differently under Bun, under `dist/` and under a
10
+ * hermetic test home — which is exactly how the first version of this broke its own suite. Bundled, it costs
11
+ * nothing and behaves identically everywhere.
12
+ *
13
+ * invariant: shapes follow the `comments` block of an editor language-configuration file, which is the maintained
14
+ * machine-readable form of this knowledge. `middle` is the continuation prefix a block conventionally carries.
15
+ */
16
+ export const COMMENT_SYNTAX: readonly CommentSyntaxEntry[] = [
17
+ {
18
+ id: "typescript",
19
+ extensions: [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"],
20
+ line: ["//"],
21
+ block: [["/*", "*/"]],
22
+ middle: ["*"],
23
+ },
24
+ {
25
+ id: "python",
26
+ extensions: [".py", ".pyi", ".pyw"],
27
+ line: ["#"],
28
+ block: [
29
+ ['"""', '"""'],
30
+ ["'''", "'''"],
31
+ ],
32
+ middle: [],
33
+ },
34
+ {
35
+ id: "ruby",
36
+ extensions: [".rb", ".rake", ".gemspec"],
37
+ line: ["#"],
38
+ block: [["=begin", "=end"]],
39
+ middle: [],
40
+ },
41
+ {
42
+ id: "shell",
43
+ extensions: [".sh", ".bash", ".zsh", ".ksh", ".fish"],
44
+ line: ["#"],
45
+ block: [],
46
+ middle: [],
47
+ },
48
+ {
49
+ id: "go",
50
+ extensions: [".go"],
51
+ line: ["//"],
52
+ block: [["/*", "*/"]],
53
+ middle: ["*"],
54
+ },
55
+ {
56
+ id: "rust",
57
+ extensions: [".rs"],
58
+ line: ["//"],
59
+ block: [["/*", "*/"]],
60
+ middle: ["*"],
61
+ },
62
+ {
63
+ id: "java",
64
+ extensions: [".java"],
65
+ line: ["//"],
66
+ block: [["/*", "*/"]],
67
+ middle: ["*"],
68
+ },
69
+ {
70
+ id: "kotlin",
71
+ extensions: [".kt", ".kts"],
72
+ line: ["//"],
73
+ block: [["/*", "*/"]],
74
+ middle: ["*"],
75
+ },
76
+ {
77
+ id: "swift",
78
+ extensions: [".swift"],
79
+ line: ["//"],
80
+ block: [["/*", "*/"]],
81
+ middle: ["*"],
82
+ },
83
+ {
84
+ id: "c",
85
+ extensions: [".c", ".h"],
86
+ line: ["//"],
87
+ block: [["/*", "*/"]],
88
+ middle: ["*"],
89
+ },
90
+ {
91
+ id: "cpp",
92
+ extensions: [".cc", ".cpp", ".cxx", ".hpp", ".hh", ".hxx"],
93
+ line: ["//"],
94
+ block: [["/*", "*/"]],
95
+ middle: ["*"],
96
+ },
97
+ {
98
+ id: "csharp",
99
+ extensions: [".cs"],
100
+ line: ["//"],
101
+ block: [["/*", "*/"]],
102
+ middle: ["*"],
103
+ },
104
+ {
105
+ id: "php",
106
+ extensions: [".php"],
107
+ line: ["//", "#"],
108
+ block: [["/*", "*/"]],
109
+ middle: ["*"],
110
+ },
111
+ {
112
+ id: "scala",
113
+ extensions: [".scala", ".sc"],
114
+ line: ["//"],
115
+ block: [["/*", "*/"]],
116
+ middle: ["*"],
117
+ },
118
+ {
119
+ id: "dart",
120
+ extensions: [".dart"],
121
+ line: ["//"],
122
+ block: [["/*", "*/"]],
123
+ middle: ["*"],
124
+ },
125
+ {
126
+ id: "elixir",
127
+ extensions: [".ex", ".exs"],
128
+ line: ["#"],
129
+ block: [],
130
+ middle: [],
131
+ },
132
+ {
133
+ id: "erlang",
134
+ extensions: [".erl", ".hrl"],
135
+ line: ["%"],
136
+ block: [],
137
+ middle: [],
138
+ },
139
+ {
140
+ id: "haskell",
141
+ extensions: [".hs"],
142
+ line: ["--"],
143
+ block: [["{-", "-}"]],
144
+ middle: [],
145
+ },
146
+ {
147
+ id: "lua",
148
+ extensions: [".lua"],
149
+ line: ["--"],
150
+ block: [["--[[", "]]"]],
151
+ middle: [],
152
+ },
153
+ {
154
+ id: "sql",
155
+ extensions: [".sql"],
156
+ line: ["--"],
157
+ block: [["/*", "*/"]],
158
+ middle: ["*"],
159
+ },
160
+ {
161
+ id: "css",
162
+ extensions: [".css", ".scss", ".sass", ".less"],
163
+ line: ["//"],
164
+ block: [["/*", "*/"]],
165
+ middle: ["*"],
166
+ },
167
+ {
168
+ id: "yaml",
169
+ extensions: [".yaml", ".yml"],
170
+ line: ["#"],
171
+ block: [],
172
+ middle: [],
173
+ },
174
+ {
175
+ id: "toml",
176
+ extensions: [".toml"],
177
+ line: ["#"],
178
+ block: [],
179
+ middle: [],
180
+ },
181
+ {
182
+ id: "ini",
183
+ extensions: [".ini", ".cfg", ".conf", ".properties"],
184
+ line: [";", "#"],
185
+ block: [],
186
+ middle: [],
187
+ },
188
+ {
189
+ id: "dockerfile",
190
+ extensions: [".dockerfile", "dockerfile"],
191
+ line: ["#"],
192
+ block: [],
193
+ middle: [],
194
+ },
195
+ {
196
+ id: "makefile",
197
+ extensions: [".mk", "makefile"],
198
+ line: ["#"],
199
+ block: [],
200
+ middle: [],
201
+ },
202
+ {
203
+ id: "terraform",
204
+ extensions: [".tf", ".tfvars"],
205
+ line: ["#", "//"],
206
+ block: [["/*", "*/"]],
207
+ middle: ["*"],
208
+ },
209
+ {
210
+ id: "powershell",
211
+ extensions: [".ps1", ".psm1", ".psd1"],
212
+ line: ["#"],
213
+ block: [["<#", "#>"]],
214
+ middle: [],
215
+ },
216
+ {
217
+ id: "perl",
218
+ extensions: [".pl", ".pm"],
219
+ line: ["#"],
220
+ block: [],
221
+ middle: [],
222
+ },
223
+ {
224
+ id: "r",
225
+ extensions: [".r"],
226
+ line: ["#"],
227
+ block: [],
228
+ middle: [],
229
+ },
230
+ {
231
+ id: "julia",
232
+ extensions: [".jl"],
233
+ line: ["#"],
234
+ block: [["#=", "=#"]],
235
+ middle: [],
236
+ },
237
+ {
238
+ id: "vue",
239
+ extensions: [".vue", ".svelte"],
240
+ line: ["//"],
241
+ block: [
242
+ ["/*", "*/"],
243
+ ["<!--", "-->"],
244
+ ],
245
+ middle: ["*"],
246
+ },
247
+ {
248
+ id: "html",
249
+ extensions: [".html", ".htm", ".xml", ".xhtml"],
250
+ line: [],
251
+ block: [["<!--", "-->"]],
252
+ middle: [],
253
+ },
254
+ {
255
+ id: "graphql",
256
+ extensions: [".graphql", ".gql"],
257
+ line: ["#"],
258
+ block: [],
259
+ middle: [],
260
+ },
261
+ {
262
+ id: "protobuf",
263
+ extensions: [".proto"],
264
+ line: ["//"],
265
+ block: [["/*", "*/"]],
266
+ middle: ["*"],
267
+ },
268
+ {
269
+ id: "zig",
270
+ extensions: [".zig"],
271
+ line: ["//"],
272
+ block: [],
273
+ middle: [],
274
+ },
275
+ {
276
+ id: "clojure",
277
+ extensions: [".clj", ".cljs", ".cljc", ".edn"],
278
+ line: [";"],
279
+ block: [],
280
+ middle: [],
281
+ },
282
+ {
283
+ id: "ocaml",
284
+ extensions: [".ml", ".mli"],
285
+ line: [],
286
+ block: [["(*", "*)"]],
287
+ middle: ["*"],
288
+ },
289
+ {
290
+ id: "fsharp",
291
+ extensions: [".fs", ".fsi", ".fsx"],
292
+ line: ["//"],
293
+ block: [["(*", "*)"]],
294
+ middle: ["*"],
295
+ },
296
+ {
297
+ id: "vim",
298
+ extensions: [".vim"],
299
+ line: ['"'],
300
+ block: [],
301
+ middle: [],
302
+ },
303
+ {
304
+ id: "tex",
305
+ extensions: [".tex", ".sty", ".cls"],
306
+ line: ["%"],
307
+ block: [],
308
+ middle: [],
309
+ },
310
+ ];
@@ -0,0 +1,65 @@
1
+ import { COMMENT_SYNTAX } from "./comment-syntax.catalog.ts";
2
+ import type { CommentSyntax, CommentSyntaxEntry } from "./comment-syntax.types.ts";
3
+
4
+ /**
5
+ * why: the layer between the catalog's shape and the question the scanner asks. Everything the scanner knows
6
+ * about languages arrives through `syntaxFor`, so the table can grow, be reordered or be regenerated from an
7
+ * upstream language-configuration set without the scanner changing
8
+ * ([/decisions/ad-058.md](/decisions/ad-058.md)).
9
+ */
10
+ export function buildIndex(entries: readonly CommentSyntaxEntry[]): Map<string, CommentSyntax> {
11
+ const byKey = new Map<string, CommentSyntax>();
12
+ for (const entry of entries) {
13
+ const syntax: CommentSyntax = { line: entry.line, block: entry.block, middle: entry.middle };
14
+ for (const extension of entry.extensions) {
15
+ byKey.set(extension.toLowerCase(), syntax);
16
+ }
17
+ }
18
+ return byKey;
19
+ }
20
+
21
+ const INDEX = buildIndex(COMMENT_SYNTAX);
22
+
23
+ /**
24
+ * invariant: the longest matching extension wins, so a two-part extension cannot be shadowed by its own tail. A
25
+ * name with no dot is matched by the whole name, which is how `Dockerfile` and `Makefile` are reached.
26
+ *
27
+ * invariant: an unknown extension returns `null`, never a guess. Assuming a delimiter for an unrecognised
28
+ * language is how `#` came to mean "comment" in TypeScript, where it starts a private field.
29
+ */
30
+ export function lookupSyntax(file: string, index = INDEX): CommentSyntax | null {
31
+ const lower = file.toLowerCase().replace(/\\/g, "/");
32
+ const name = lower.slice(lower.lastIndexOf("/") + 1);
33
+ const direct = index.get(name);
34
+ if (direct) {
35
+ return direct;
36
+ }
37
+ let best: CommentSyntax | null = null;
38
+ let bestLength = 0;
39
+ for (const [extension, syntax] of index) {
40
+ if (extension.startsWith(".") && name.endsWith(extension) && extension.length > bestLength) {
41
+ best = syntax;
42
+ bestLength = extension.length;
43
+ }
44
+ }
45
+ return best;
46
+ }
47
+
48
+ export function syntaxFor(file: string): CommentSyntax | null {
49
+ return lookupSyntax(file);
50
+ }
51
+
52
+ /** why: the operator needs the coverage gap named. A language nobody listed is a rail that silently passes. */
53
+ export function unknownExtensions(files: readonly string[]): string[] {
54
+ const unknown = new Set<string>();
55
+ for (const file of files) {
56
+ if (lookupSyntax(file) === null) {
57
+ const name = file.toLowerCase().replace(/\\/g, "/").split("/").pop() ?? file;
58
+ const dot = name.lastIndexOf(".");
59
+ unknown.add(dot > 0 ? name.slice(dot) : name);
60
+ }
61
+ }
62
+ return [...unknown].sort();
63
+ }
64
+
65
+ export const KNOWN_EXTENSION_COUNT = INDEX.size;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * The domain's own vocabulary for "how does this file write a comment". The scanner asks that question and gets
3
+ * this answer; it knows nothing about extensions, languages or delimiters beyond what is in here.
4
+ */
5
+ export type CommentSyntax = {
6
+ /** Prefixes that start a comment running to end of line. */
7
+ line: readonly string[];
8
+ /** Open/close pairs. A pair whose open and close are equal is a symmetric fence, like a Python docstring. */
9
+ block: readonly (readonly [string, string])[];
10
+ /**
11
+ * Prefixes a continuation line inside a block conventionally carries — `*` in the C family. Without it a
12
+ * multi-line doc block reads as one comment followed by unrelated lines, and a marker on its first line stops
13
+ * covering the rest of it.
14
+ */
15
+ middle: readonly string[];
16
+ };
17
+
18
+ export type CommentSyntaxEntry = CommentSyntax & {
19
+ id: string;
20
+ /** Extensions including the dot, or a bare filename for the ones that have none (`Dockerfile`, `Makefile`). */
21
+ extensions: readonly string[];
22
+ };
23
+
24
+ export const NO_COMMENT_SYNTAX: CommentSyntax = { line: [], block: [], middle: [] };