@humanbased/crosscheck 1.2.0-beta.80 → 1.2.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 (301) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +388 -149
  3. package/README.zh.md +1 -1
  4. package/crosscheck.config.example.yml +2 -63
  5. package/dist/__tests__/codex.test.js +27 -14
  6. package/dist/__tests__/codex.test.js.map +1 -1
  7. package/dist/__tests__/comment-bodies.test.js +1 -49
  8. package/dist/__tests__/comment-bodies.test.js.map +1 -1
  9. package/dist/__tests__/conflict-resolve.test.js +1 -44
  10. package/dist/__tests__/conflict-resolve.test.js.map +1 -1
  11. package/dist/__tests__/fix.test.js +0 -33
  12. package/dist/__tests__/fix.test.js.map +1 -1
  13. package/dist/__tests__/onboard-preservation.test.js +0 -5
  14. package/dist/__tests__/onboard-preservation.test.js.map +1 -1
  15. package/dist/__tests__/optimize.test.js +0 -2
  16. package/dist/__tests__/optimize.test.js.map +1 -1
  17. package/dist/__tests__/repo-picker.test.js +1 -7
  18. package/dist/__tests__/repo-picker.test.js.map +1 -1
  19. package/dist/__tests__/review-comment-body.test.js +0 -35
  20. package/dist/__tests__/review-comment-body.test.js.map +1 -1
  21. package/dist/__tests__/review-models.test.js +3 -19
  22. package/dist/__tests__/review-models.test.js.map +1 -1
  23. package/dist/__tests__/runner.test.js +1 -29
  24. package/dist/__tests__/runner.test.js.map +1 -1
  25. package/dist/cli.js +0 -29
  26. package/dist/cli.js.map +1 -1
  27. package/dist/commands/onboard.d.ts +0 -11
  28. package/dist/commands/onboard.d.ts.map +1 -1
  29. package/dist/commands/onboard.js +2 -88
  30. package/dist/commands/onboard.js.map +1 -1
  31. package/dist/commands/review.d.ts.map +1 -1
  32. package/dist/commands/review.js +6 -65
  33. package/dist/commands/review.js.map +1 -1
  34. package/dist/commands/run.d.ts.map +1 -1
  35. package/dist/commands/run.js +3 -23
  36. package/dist/commands/run.js.map +1 -1
  37. package/dist/commands/status.d.ts.map +1 -1
  38. package/dist/commands/status.js +1 -53
  39. package/dist/commands/status.js.map +1 -1
  40. package/dist/commands/watch.d.ts.map +1 -1
  41. package/dist/commands/watch.js +6 -52
  42. package/dist/commands/watch.js.map +1 -1
  43. package/dist/config/loader.d.ts +1 -3
  44. package/dist/config/loader.d.ts.map +1 -1
  45. package/dist/config/loader.js +0 -13
  46. package/dist/config/loader.js.map +1 -1
  47. package/dist/config/review-model-tiers.json +3 -3
  48. package/dist/config/schema.d.ts +10 -254
  49. package/dist/config/schema.d.ts.map +1 -1
  50. package/dist/config/schema.js +2 -62
  51. package/dist/config/schema.js.map +1 -1
  52. package/dist/github/client.d.ts +1 -6
  53. package/dist/github/client.d.ts.map +1 -1
  54. package/dist/github/client.js +7 -15
  55. package/dist/github/client.js.map +1 -1
  56. package/dist/issues/ticket-ref.d.ts.map +1 -1
  57. package/dist/issues/ticket-ref.js +5 -6
  58. package/dist/issues/ticket-ref.js.map +1 -1
  59. package/dist/lib/clone.d.ts +0 -1
  60. package/dist/lib/clone.d.ts.map +1 -1
  61. package/dist/lib/clone.js +10 -32
  62. package/dist/lib/clone.js.map +1 -1
  63. package/dist/lib/comment-bodies.d.ts +0 -35
  64. package/dist/lib/comment-bodies.d.ts.map +1 -1
  65. package/dist/lib/comment-bodies.js +9 -43
  66. package/dist/lib/comment-bodies.js.map +1 -1
  67. package/dist/lib/repo-picker.d.ts +0 -3
  68. package/dist/lib/repo-picker.d.ts.map +1 -1
  69. package/dist/lib/repo-picker.js +9 -45
  70. package/dist/lib/repo-picker.js.map +1 -1
  71. package/dist/lib/review-models.d.ts +2 -15
  72. package/dist/lib/review-models.d.ts.map +1 -1
  73. package/dist/lib/review-models.js +6 -26
  74. package/dist/lib/review-models.js.map +1 -1
  75. package/dist/lib/runner.d.ts +0 -12
  76. package/dist/lib/runner.d.ts.map +1 -1
  77. package/dist/lib/runner.js +42 -186
  78. package/dist/lib/runner.js.map +1 -1
  79. package/dist/lib/workflow.d.ts +0 -9
  80. package/dist/lib/workflow.d.ts.map +1 -1
  81. package/dist/lib/workflow.js +0 -20
  82. package/dist/lib/workflow.js.map +1 -1
  83. package/dist/reviewers/claude.d.ts +1 -4
  84. package/dist/reviewers/claude.d.ts.map +1 -1
  85. package/dist/reviewers/claude.js +7 -39
  86. package/dist/reviewers/claude.js.map +1 -1
  87. package/dist/reviewers/codex.d.ts +1 -3
  88. package/dist/reviewers/codex.d.ts.map +1 -1
  89. package/dist/reviewers/codex.js +70 -76
  90. package/dist/reviewers/codex.js.map +1 -1
  91. package/dist/reviewers/conflict-resolve.d.ts +1 -3
  92. package/dist/reviewers/conflict-resolve.d.ts.map +1 -1
  93. package/dist/reviewers/conflict-resolve.js +6 -21
  94. package/dist/reviewers/conflict-resolve.js.map +1 -1
  95. package/dist/reviewers/fix.d.ts +2 -5
  96. package/dist/reviewers/fix.d.ts.map +1 -1
  97. package/dist/reviewers/fix.js +10 -26
  98. package/dist/reviewers/fix.js.map +1 -1
  99. package/get-started.md +4 -139
  100. package/package.json +3 -4
  101. package/assets/icon-256.png +0 -0
  102. package/assets/linear-comment.svg +0 -18
  103. package/assets/linear-onboard.svg +0 -30
  104. package/assets/linear-status.svg +0 -23
  105. package/assets/linear-test.svg +0 -34
  106. package/assets/skills/code-review/.crosscheck-skill.json +0 -9
  107. package/assets/skills/code-review/LICENSE +0 -21
  108. package/assets/skills/code-review/SKILL.md +0 -89
  109. package/assets/skills/code-review/agents/openai.yaml +0 -3
  110. package/assets/skills/code-review-skill/.crosscheck-skill.json +0 -9
  111. package/assets/skills/code-review-skill/LICENSE +0 -21
  112. package/assets/skills/code-review-skill/SKILL.md +0 -231
  113. package/assets/skills/code-review-skill/assets/pr-review-template.md +0 -137
  114. package/assets/skills/code-review-skill/assets/review-checklist.md +0 -123
  115. package/assets/skills/code-review-skill/reference/angular.md +0 -768
  116. package/assets/skills/code-review-skill/reference/architecture-review-guide.md +0 -472
  117. package/assets/skills/code-review-skill/reference/c.md +0 -890
  118. package/assets/skills/code-review-skill/reference/code-quality-universal.md +0 -488
  119. package/assets/skills/code-review-skill/reference/code-review-best-practices.md +0 -136
  120. package/assets/skills/code-review-skill/reference/common-bugs-checklist.md +0 -286
  121. package/assets/skills/code-review-skill/reference/cpp.md +0 -893
  122. package/assets/skills/code-review-skill/reference/cross-cutting/async-concurrency-patterns.md +0 -515
  123. package/assets/skills/code-review-skill/reference/cross-cutting/error-handling-principles.md +0 -492
  124. package/assets/skills/code-review-skill/reference/cross-cutting/n-plus-one-queries.md +0 -309
  125. package/assets/skills/code-review-skill/reference/cross-cutting/sql-injection-prevention.md +0 -308
  126. package/assets/skills/code-review-skill/reference/cross-cutting/xss-prevention.md +0 -264
  127. package/assets/skills/code-review-skill/reference/csharp.md +0 -525
  128. package/assets/skills/code-review-skill/reference/css-less-sass.md +0 -661
  129. package/assets/skills/code-review-skill/reference/django.md +0 -985
  130. package/assets/skills/code-review-skill/reference/fastapi.md +0 -580
  131. package/assets/skills/code-review-skill/reference/go.md +0 -993
  132. package/assets/skills/code-review-skill/reference/java.md +0 -409
  133. package/assets/skills/code-review-skill/reference/java8.md +0 -586
  134. package/assets/skills/code-review-skill/reference/kotlin.md +0 -1018
  135. package/assets/skills/code-review-skill/reference/nestjs.md +0 -593
  136. package/assets/skills/code-review-skill/reference/performance-review-guide.md +0 -816
  137. package/assets/skills/code-review-skill/reference/php.md +0 -684
  138. package/assets/skills/code-review-skill/reference/python.md +0 -1073
  139. package/assets/skills/code-review-skill/reference/qt.md +0 -757
  140. package/assets/skills/code-review-skill/reference/react.md +0 -871
  141. package/assets/skills/code-review-skill/reference/ruby.md +0 -964
  142. package/assets/skills/code-review-skill/reference/rust.md +0 -846
  143. package/assets/skills/code-review-skill/reference/security-review-guide.md +0 -494
  144. package/assets/skills/code-review-skill/reference/svelte.md +0 -1064
  145. package/assets/skills/code-review-skill/reference/swift.md +0 -936
  146. package/assets/skills/code-review-skill/reference/typescript.md +0 -1016
  147. package/assets/skills/code-review-skill/reference/vue.md +0 -924
  148. package/assets/skills/code-review-skill/reference/zig.md +0 -440
  149. package/assets/skills/code-review-skill/scripts/pr-analyzer.py +0 -435
  150. package/assets/skills/code-review-skill/scripts/test_pr_analyzer.py +0 -380
  151. package/assets/skills/codebase-design/.crosscheck-skill.json +0 -9
  152. package/assets/skills/codebase-design/DEEPENING.md +0 -37
  153. package/assets/skills/codebase-design/DESIGN-IT-TWICE.md +0 -44
  154. package/assets/skills/codebase-design/LICENSE +0 -21
  155. package/assets/skills/codebase-design/SKILL.md +0 -114
  156. package/assets/skills/codebase-design/agents/openai.yaml +0 -3
  157. package/assets/skills/diagnosing-bugs/.crosscheck-skill.json +0 -9
  158. package/assets/skills/diagnosing-bugs/LICENSE +0 -21
  159. package/assets/skills/diagnosing-bugs/SKILL.md +0 -134
  160. package/assets/skills/diagnosing-bugs/agents/openai.yaml +0 -3
  161. package/assets/skills/diagnosing-bugs/scripts/hitl-loop.template.sh +0 -41
  162. package/dist/__tests__/can-write-verdict.test.d.ts +0 -2
  163. package/dist/__tests__/can-write-verdict.test.d.ts.map +0 -1
  164. package/dist/__tests__/can-write-verdict.test.js +0 -31
  165. package/dist/__tests__/can-write-verdict.test.js.map +0 -1
  166. package/dist/__tests__/linear-branding.test.d.ts +0 -2
  167. package/dist/__tests__/linear-branding.test.d.ts.map +0 -1
  168. package/dist/__tests__/linear-branding.test.js +0 -156
  169. package/dist/__tests__/linear-branding.test.js.map +0 -1
  170. package/dist/__tests__/linear-client.test.d.ts +0 -2
  171. package/dist/__tests__/linear-client.test.d.ts.map +0 -1
  172. package/dist/__tests__/linear-client.test.js +0 -120
  173. package/dist/__tests__/linear-client.test.js.map +0 -1
  174. package/dist/__tests__/linear-comment.test.d.ts +0 -2
  175. package/dist/__tests__/linear-comment.test.d.ts.map +0 -1
  176. package/dist/__tests__/linear-comment.test.js +0 -151
  177. package/dist/__tests__/linear-comment.test.js.map +0 -1
  178. package/dist/__tests__/linear-identity.test.d.ts +0 -2
  179. package/dist/__tests__/linear-identity.test.d.ts.map +0 -1
  180. package/dist/__tests__/linear-identity.test.js +0 -253
  181. package/dist/__tests__/linear-identity.test.js.map +0 -1
  182. package/dist/__tests__/linear-notify.test.d.ts +0 -2
  183. package/dist/__tests__/linear-notify.test.d.ts.map +0 -1
  184. package/dist/__tests__/linear-notify.test.js +0 -144
  185. package/dist/__tests__/linear-notify.test.js.map +0 -1
  186. package/dist/__tests__/linear-ref.test.d.ts +0 -2
  187. package/dist/__tests__/linear-ref.test.d.ts.map +0 -1
  188. package/dist/__tests__/linear-ref.test.js +0 -261
  189. package/dist/__tests__/linear-ref.test.js.map +0 -1
  190. package/dist/__tests__/linear-test-ref.test.d.ts +0 -2
  191. package/dist/__tests__/linear-test-ref.test.d.ts.map +0 -1
  192. package/dist/__tests__/linear-test-ref.test.js +0 -81
  193. package/dist/__tests__/linear-test-ref.test.js.map +0 -1
  194. package/dist/__tests__/linear-verify.test.d.ts +0 -2
  195. package/dist/__tests__/linear-verify.test.d.ts.map +0 -1
  196. package/dist/__tests__/linear-verify.test.js +0 -132
  197. package/dist/__tests__/linear-verify.test.js.map +0 -1
  198. package/dist/__tests__/linear-worker.test.d.ts +0 -2
  199. package/dist/__tests__/linear-worker.test.d.ts.map +0 -1
  200. package/dist/__tests__/linear-worker.test.js +0 -83
  201. package/dist/__tests__/linear-worker.test.js.map +0 -1
  202. package/dist/__tests__/linear-write-possible.test.d.ts +0 -2
  203. package/dist/__tests__/linear-write-possible.test.d.ts.map +0 -1
  204. package/dist/__tests__/linear-write-possible.test.js +0 -30
  205. package/dist/__tests__/linear-write-possible.test.js.map +0 -1
  206. package/dist/__tests__/repository-guidance.test.d.ts +0 -2
  207. package/dist/__tests__/repository-guidance.test.d.ts.map +0 -1
  208. package/dist/__tests__/repository-guidance.test.js +0 -107
  209. package/dist/__tests__/repository-guidance.test.js.map +0 -1
  210. package/dist/__tests__/review-strategy.test.d.ts +0 -2
  211. package/dist/__tests__/review-strategy.test.d.ts.map +0 -1
  212. package/dist/__tests__/review-strategy.test.js +0 -195
  213. package/dist/__tests__/review-strategy.test.js.map +0 -1
  214. package/dist/__tests__/skill-attribution.test.d.ts +0 -2
  215. package/dist/__tests__/skill-attribution.test.d.ts.map +0 -1
  216. package/dist/__tests__/skill-attribution.test.js +0 -53
  217. package/dist/__tests__/skill-attribution.test.js.map +0 -1
  218. package/dist/__tests__/skill-broker.test.d.ts +0 -2
  219. package/dist/__tests__/skill-broker.test.d.ts.map +0 -1
  220. package/dist/__tests__/skill-broker.test.js +0 -144
  221. package/dist/__tests__/skill-broker.test.js.map +0 -1
  222. package/dist/__tests__/skill-catalog.test.d.ts +0 -2
  223. package/dist/__tests__/skill-catalog.test.d.ts.map +0 -1
  224. package/dist/__tests__/skill-catalog.test.js +0 -40
  225. package/dist/__tests__/skill-catalog.test.js.map +0 -1
  226. package/dist/__tests__/skill-installer.test.d.ts +0 -2
  227. package/dist/__tests__/skill-installer.test.d.ts.map +0 -1
  228. package/dist/__tests__/skill-installer.test.js +0 -96
  229. package/dist/__tests__/skill-installer.test.js.map +0 -1
  230. package/dist/__tests__/skills-config.test.d.ts +0 -2
  231. package/dist/__tests__/skills-config.test.d.ts.map +0 -1
  232. package/dist/__tests__/skills-config.test.js +0 -12
  233. package/dist/__tests__/skills-config.test.js.map +0 -1
  234. package/dist/commands/linear-test.d.ts +0 -18
  235. package/dist/commands/linear-test.d.ts.map +0 -1
  236. package/dist/commands/linear-test.js +0 -130
  237. package/dist/commands/linear-test.js.map +0 -1
  238. package/dist/commands/skill.d.ts +0 -2
  239. package/dist/commands/skill.d.ts.map +0 -1
  240. package/dist/commands/skill.js +0 -16
  241. package/dist/commands/skill.js.map +0 -1
  242. package/dist/config/review-strategy.json +0 -202
  243. package/dist/lib/repository-guidance.d.ts +0 -2
  244. package/dist/lib/repository-guidance.d.ts.map +0 -1
  245. package/dist/lib/repository-guidance.js +0 -55
  246. package/dist/lib/repository-guidance.js.map +0 -1
  247. package/dist/lib/review-strategy.d.ts +0 -62
  248. package/dist/lib/review-strategy.d.ts.map +0 -1
  249. package/dist/lib/review-strategy.js +0 -235
  250. package/dist/lib/review-strategy.js.map +0 -1
  251. package/dist/linear/client.d.ts +0 -18
  252. package/dist/linear/client.d.ts.map +0 -1
  253. package/dist/linear/client.js +0 -67
  254. package/dist/linear/client.js.map +0 -1
  255. package/dist/linear/comment.d.ts +0 -20
  256. package/dist/linear/comment.d.ts.map +0 -1
  257. package/dist/linear/comment.js +0 -57
  258. package/dist/linear/comment.js.map +0 -1
  259. package/dist/linear/identity.d.ts +0 -59
  260. package/dist/linear/identity.d.ts.map +0 -1
  261. package/dist/linear/identity.js +0 -187
  262. package/dist/linear/identity.js.map +0 -1
  263. package/dist/linear/notify.d.ts +0 -35
  264. package/dist/linear/notify.d.ts.map +0 -1
  265. package/dist/linear/notify.js +0 -76
  266. package/dist/linear/notify.js.map +0 -1
  267. package/dist/linear/ref.d.ts +0 -13
  268. package/dist/linear/ref.d.ts.map +0 -1
  269. package/dist/linear/ref.js +0 -90
  270. package/dist/linear/ref.js.map +0 -1
  271. package/dist/linear/verify.d.ts +0 -26
  272. package/dist/linear/verify.d.ts.map +0 -1
  273. package/dist/linear/verify.js +0 -67
  274. package/dist/linear/verify.js.map +0 -1
  275. package/dist/skills/attribution.d.ts +0 -4
  276. package/dist/skills/attribution.d.ts.map +0 -1
  277. package/dist/skills/attribution.js +0 -14
  278. package/dist/skills/attribution.js.map +0 -1
  279. package/dist/skills/broker-server.d.ts +0 -2
  280. package/dist/skills/broker-server.d.ts.map +0 -1
  281. package/dist/skills/broker-server.js +0 -17
  282. package/dist/skills/broker-server.js.map +0 -1
  283. package/dist/skills/broker.d.ts +0 -42
  284. package/dist/skills/broker.d.ts.map +0 -1
  285. package/dist/skills/broker.js +0 -285
  286. package/dist/skills/broker.js.map +0 -1
  287. package/dist/skills/catalog.d.ts +0 -28
  288. package/dist/skills/catalog.d.ts.map +0 -1
  289. package/dist/skills/catalog.js +0 -104
  290. package/dist/skills/catalog.js.map +0 -1
  291. package/dist/skills/installer.d.ts +0 -10
  292. package/dist/skills/installer.d.ts.map +0 -1
  293. package/dist/skills/installer.js +0 -138
  294. package/dist/skills/installer.js.map +0 -1
  295. package/dist/skills/integrity.d.ts +0 -4
  296. package/dist/skills/integrity.d.ts.map +0 -1
  297. package/dist/skills/integrity.js +0 -36
  298. package/dist/skills/integrity.js.map +0 -1
  299. package/docs/dynamic-thoroughness.md +0 -286
  300. package/docs/linear-identity-contract.md +0 -139
  301. package/docs/linear-identity.md +0 -293
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=linear-ref.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"linear-ref.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/linear-ref.test.ts"],"names":[],"mappings":""}
@@ -1,261 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { extractLinearRef } from '../linear/ref.js';
3
- describe('extractLinearRef', () => {
4
- describe('Linear URLs (no team_keys needed)', () => {
5
- it('finds an issue URL in the PR body', () => {
6
- const ref = extractLinearRef({ body: 'Closes https://linear.app/inductive-network/issue/IN-2269/some-slug' }, []);
7
- expect(ref).toEqual({ id: 'IN-2269', key: 'IN', number: 2269, source: 'body', workspace: 'inductive-network' });
8
- });
9
- it('finds an issue URL in the PR title', () => {
10
- const ref = extractLinearRef({ title: 'fix: see linear.app/acme/issue/ENG-7/thing' }, []);
11
- expect(ref?.id).toBe('ENG-7');
12
- expect(ref?.source).toBe('title');
13
- });
14
- it('accepts a URL with no trailing slug', () => {
15
- const ref = extractLinearRef({ body: 'https://linear.app/acme/issue/AB-12' }, []);
16
- expect(ref?.id).toBe('AB-12');
17
- });
18
- });
19
- describe('bare identifiers require configured team_keys', () => {
20
- it('ignores bare identifiers when team_keys is empty', () => {
21
- expect(extractLinearRef({ branch: 'feat/in-2269-thing', title: 'IN-2269 fix' }, [])).toBeNull();
22
- });
23
- it('matches a configured key in a branch name, case-insensitively', () => {
24
- const ref = extractLinearRef({ branch: 'feat/in-2269-tiered-identity' }, ['IN']);
25
- expect(ref).toEqual({ id: 'IN-2269', key: 'IN', number: 2269, source: 'branch' });
26
- });
27
- it('matches an uppercase key in a title', () => {
28
- const ref = extractLinearRef({ title: 'IN-543: unified resolver' }, ['IN']);
29
- expect(ref?.id).toBe('IN-543');
30
- expect(ref?.source).toBe('title');
31
- });
32
- it('does not match a key that is not configured', () => {
33
- expect(extractLinearRef({ branch: 'feat/eng-1-thing' }, ['IN'])).toBeNull();
34
- });
35
- });
36
- describe('false-positive resistance', () => {
37
- // The reason bare-identifier matching is gated behind team_keys: these all
38
- // look exactly like Linear identifiers to a naive regex.
39
- const traps = ['UTF-8', 'SHA-256', 'ISO-8601', 'GPT-5', 'RFC-2119'];
40
- for (const trap of traps) {
41
- it(`does not treat ${trap} as an issue ref`, () => {
42
- expect(extractLinearRef({ title: `chore: switch to ${trap}` }, [])).toBeNull();
43
- });
44
- }
45
- it('still ignores traps when unrelated team_keys are configured', () => {
46
- expect(extractLinearRef({ title: 'chore: SHA-256 hashing' }, ['IN'])).toBeNull();
47
- });
48
- it('requires a word boundary so SUBIN-1 does not match key IN', () => {
49
- expect(extractLinearRef({ title: 'SUBIN-1 nope' }, ['IN'])).toBeNull();
50
- });
51
- });
52
- describe('precedence', () => {
53
- it('prefers branch over title and body', () => {
54
- const ref = extractLinearRef({ branch: 'feat/in-1-a', title: 'IN-2 b', body: 'IN-3 c' }, ['IN']);
55
- expect(ref?.id).toBe('IN-1');
56
- expect(ref?.source).toBe('branch');
57
- });
58
- it('prefers title over body', () => {
59
- const ref = extractLinearRef({ title: 'IN-2 b', body: 'IN-3 c' }, ['IN']);
60
- expect(ref?.id).toBe('IN-2');
61
- });
62
- it('prefers an unambiguous URL over a bare key in the same field', () => {
63
- const ref = extractLinearRef({ body: 'IN-99 mentioned, real one: https://linear.app/x/issue/IN-2269/z' }, ['IN']);
64
- expect(ref?.id).toBe('IN-2269');
65
- });
66
- });
67
- it('returns null when nothing matches', () => {
68
- expect(extractLinearRef({ branch: 'main', title: 'chore: bump', body: '' }, ['IN'])).toBeNull();
69
- });
70
- it('handles absent fields', () => {
71
- expect(extractLinearRef({}, ['IN'])).toBeNull();
72
- });
73
- });
74
- describe('hostname anchoring', () => {
75
- // Regression: an unanchored `linear.app/` fragment let any domain ending in
76
- // "linear.app" bypass the team_keys gate and target an arbitrary issue.
77
- const impostors = [
78
- 'https://notlinear.app/acme/issue/IN-2269',
79
- 'https://evil-linear.app/acme/issue/IN-2269',
80
- 'https://mylinear.app/x/issue/IN-1/slug',
81
- ];
82
- for (const url of impostors) {
83
- it(`does not trust ${url.replace('https://', '').split('/')[0]}`, () => {
84
- expect(extractLinearRef({ body: url }, [])).toBeNull();
85
- });
86
- }
87
- it('still trusts the real host', () => {
88
- expect(extractLinearRef({ body: 'https://linear.app/acme/issue/IN-2269' }, [])?.id).toBe('IN-2269');
89
- });
90
- it('trusts it bare, without a scheme', () => {
91
- expect(extractLinearRef({ body: 'see linear.app/acme/issue/IN-7' }, [])?.id).toBe('IN-7');
92
- });
93
- it('trusts it at the very start of a field', () => {
94
- expect(extractLinearRef({ body: 'linear.app/acme/issue/IN-8' }, [])?.id).toBe('IN-8');
95
- });
96
- it('falls through to team_keys when an impostor URL is present', () => {
97
- // The impostor must not shadow a legitimate bare ref elsewhere in the text.
98
- const ref = extractLinearRef({ body: 'https://notlinear.app/x/issue/IN-999 but really IN-42' }, ['IN']);
99
- expect(ref?.id).toBe('IN-999');
100
- });
101
- });
102
- describe('hostname is parsed, not pattern-matched', () => {
103
- // A path segment named linear.app is not the linear.app host. A boundary check
104
- // on the surrounding character passes here; only real parsing rejects it.
105
- const impostors = [
106
- 'https://evil.example/linear.app/acme/issue/IN-2269',
107
- 'https://evil.example/?u=https://linear.app/acme/issue/IN-2269',
108
- 'https://linear.app.evil.example/acme/issue/IN-2269',
109
- 'https://user@evil.example/linear.app/acme/issue/IN-1',
110
- ];
111
- for (const url of impostors) {
112
- it(`rejects ${url.slice(8, 40)}...`, () => {
113
- expect(extractLinearRef({ body: url }, [])).toBeNull();
114
- });
115
- }
116
- it('accepts the real host over https', () => {
117
- expect(extractLinearRef({ body: 'https://linear.app/acme/issue/IN-2269/slug' }, [])?.id).toBe('IN-2269');
118
- });
119
- it('accepts the real host case-insensitively', () => {
120
- expect(extractLinearRef({ body: 'https://LINEAR.APP/acme/issue/IN-3' }, [])?.id).toBe('IN-3');
121
- });
122
- it('ignores a malformed URL without throwing', () => {
123
- expect(extractLinearRef({ body: 'https://[not-a-url/issue/IN-9' }, [])).toBeNull();
124
- });
125
- it('finds a real URL after an impostor one', () => {
126
- const body = 'https://evil.example/linear.app/x/issue/IN-1 and https://linear.app/acme/issue/IN-42';
127
- expect(extractLinearRef({ body }, [])?.id).toBe('IN-42');
128
- });
129
- });
130
- describe('workspace and issue-number boundaries', () => {
131
- // Identifiers are unique only within a workspace, so an explicit URL must carry
132
- // its slug — otherwise a URL for workspace A resolves against credentials for
133
- // workspace B and comments on B's same-numbered issue.
134
- it('carries the workspace slug from an absolute URL', () => {
135
- const ref = extractLinearRef({ body: 'https://linear.app/acme/issue/IN-42' }, []);
136
- expect(ref?.workspace).toBe('acme');
137
- });
138
- it('carries it from a scheme-less URL', () => {
139
- expect(extractLinearRef({ body: 'see linear.app/beta-corp/issue/IN-42' }, [])?.workspace).toBe('beta-corp');
140
- });
141
- it('lower-cases the slug for comparison', () => {
142
- expect(extractLinearRef({ body: 'https://linear.app/ACME/issue/IN-42' }, [])?.workspace).toBe('acme');
143
- });
144
- it('leaves a bare ref with no workspace, since it names none', () => {
145
- const ref = extractLinearRef({ branch: 'feat/in-42-x' }, ['IN']);
146
- expect(ref?.id).toBe('IN-42');
147
- expect(ref?.workspace).toBeUndefined();
148
- });
149
- // Without a boundary after the digits, /issue/IN-123abc matched the IN-123
150
- // prefix and could post to an unrelated issue while bypassing team_keys.
151
- it('rejects a malformed identifier with a trailing suffix', () => {
152
- expect(extractLinearRef({ body: 'https://linear.app/acme/issue/IN-123abc' }, [])).toBeNull();
153
- });
154
- it('accepts an identifier followed by a slug', () => {
155
- expect(extractLinearRef({ body: 'https://linear.app/acme/issue/IN-123/some-slug' }, [])?.id).toBe('IN-123');
156
- });
157
- it('accepts an identifier at the end of the path', () => {
158
- expect(extractLinearRef({ body: 'https://linear.app/acme/issue/IN-123' }, [])?.id).toBe('IN-123');
159
- });
160
- it('rejects a suffixed identifier in the scheme-less form too', () => {
161
- expect(extractLinearRef({ body: 'see linear.app/acme/issue/IN-123abc' }, [])).toBeNull();
162
- });
163
- });
164
- describe('punctuation after a URL', () => {
165
- // A ref at the end of a sentence is still a ref. Requiring a slash or the exact
166
- // end of the path silently missed these.
167
- const cases = [
168
- ['Fixes https://linear.app/acme/issue/IN-42.', 'IN-42'],
169
- ['See https://linear.app/acme/issue/IN-42, then merge', 'IN-42'],
170
- ['(https://linear.app/acme/issue/IN-42)', 'IN-42'],
171
- ['see linear.app/acme/issue/IN-42.', 'IN-42'],
172
- ['see linear.app/acme/issue/IN-42, ok', 'IN-42'],
173
- ];
174
- for (const [body, expected] of cases) {
175
- it(`resolves ${expected} from ${JSON.stringify(body.slice(0, 46))}`, () => {
176
- expect(extractLinearRef({ body }, [])?.id).toBe(expected);
177
- });
178
- }
179
- it('still rejects an alphanumeric suffix', () => {
180
- expect(extractLinearRef({ body: 'https://linear.app/acme/issue/IN-123abc' }, [])).toBeNull();
181
- expect(extractLinearRef({ body: 'see linear.app/acme/issue/IN-123abc' }, [])).toBeNull();
182
- });
183
- it('still rejects extra digits', () => {
184
- expect(extractLinearRef({ body: 'https://linear.app/acme/issue/IN-12/x' }, [])?.id).toBe('IN-12');
185
- });
186
- });
187
- describe('the identifier must be a whole path segment', () => {
188
- // Two lookahead attempts got this wrong in opposite directions: requiring a
189
- // slash missed "IN-42." at the end of a sentence; allowing any non-alphanumeric
190
- // accepted "IN-123-typo" as IN-123. The segment is now parsed whole.
191
- const rejected = [
192
- 'https://linear.app/acme/issue/IN-123-typo',
193
- 'https://linear.app/acme/issue/IN-123abc',
194
- 'https://linear.app/acme/issue/IN-123_x',
195
- 'see linear.app/acme/issue/IN-123-typo',
196
- ];
197
- for (const url of rejected) {
198
- it(`rejects ${url.split('/issue/')[1]}`, () => {
199
- expect(extractLinearRef({ body: url }, [])).toBeNull();
200
- });
201
- }
202
- const accepted = [
203
- ['https://linear.app/acme/issue/IN-42', 'IN-42'],
204
- ['https://linear.app/acme/issue/IN-42/some-slug', 'IN-42'],
205
- ['Fixes https://linear.app/acme/issue/IN-42.', 'IN-42'],
206
- ['See https://linear.app/acme/issue/IN-42, then merge', 'IN-42'],
207
- ['(https://linear.app/acme/issue/IN-42)', 'IN-42'],
208
- ['see linear.app/acme/issue/IN-42.', 'IN-42'],
209
- ];
210
- for (const [body, expected] of accepted) {
211
- it(`accepts ${JSON.stringify(body.slice(0, 44))}`, () => {
212
- expect(extractLinearRef({ body }, [])?.id).toBe(expected);
213
- });
214
- }
215
- });
216
- describe('a malformed candidate does not hide a valid one', () => {
217
- it('skips a malformed scheme-less URL and finds the later valid one', () => {
218
- const body = 'linear.app/acme/issue/IN-bad and then linear.app/acme/issue/IN-42';
219
- expect(extractLinearRef({ body }, [])?.id).toBe('IN-42');
220
- });
221
- it('skips a malformed absolute URL and finds the later valid one', () => {
222
- const body = 'https://linear.app/acme/issue/IN-bad https://linear.app/acme/issue/IN-42';
223
- expect(extractLinearRef({ body }, [])?.id).toBe('IN-42');
224
- });
225
- it('returns null when every candidate is malformed', () => {
226
- expect(extractLinearRef({ body: 'linear.app/a/issue/IN-bad linear.app/b/issue/X' }, [])).toBeNull();
227
- });
228
- it('keeps the workspace of the candidate that actually resolved', () => {
229
- const body = 'linear.app/wrong/issue/IN-bad linear.app/right/issue/IN-42';
230
- expect(extractLinearRef({ body }, [])?.workspace).toBe('right');
231
- });
232
- });
233
- describe('punctuated scheme-less URLs keep their workspace', () => {
234
- // Regression: `(linear.app/...)` missed the URL matcher, fell through to the
235
- // bare-ID extractor, and came back without a workspace — silently losing the
236
- // workspace-mismatch protection that an explicit URL is supposed to carry.
237
- const wrapped = ['(linear.app/acme/issue/IN-42)', '[linear.app/acme/issue/IN-42]', '"linear.app/acme/issue/IN-42"', 'see: linear.app/acme/issue/IN-42'];
238
- for (const body of wrapped) {
239
- it(`keeps the workspace for ${JSON.stringify(body.slice(0, 32))}`, () => {
240
- const ref = extractLinearRef({ body }, ['IN']);
241
- expect(ref?.id).toBe('IN-42');
242
- expect(ref?.workspace).toBe('acme');
243
- });
244
- }
245
- it('still refuses a lookalike host after punctuation', () => {
246
- expect(extractLinearRef({ body: '(notlinear.app/acme/issue/IN-42)' }, [])).toBeNull();
247
- });
248
- });
249
- describe('one-character team keys', () => {
250
- // Linear permits them; requiring two silently skipped those workspaces.
251
- it('resolves a one-character key from a URL', () => {
252
- expect(extractLinearRef({ body: 'https://linear.app/acme/issue/X-42' }, [])?.id).toBe('X-42');
253
- });
254
- it('resolves a one-character key as a configured bare ref', () => {
255
- expect(extractLinearRef({ branch: 'feat/x-42-thing' }, ['X'])?.id).toBe('X-42');
256
- });
257
- it('still rejects a bare ref whose key is not configured', () => {
258
- expect(extractLinearRef({ branch: 'feat/y-42-thing' }, ['X'])).toBeNull();
259
- });
260
- });
261
- //# sourceMappingURL=linear-ref.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"linear-ref.test.js","sourceRoot":"","sources":["../../src/__tests__/linear-ref.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=linear-test-ref.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"linear-test-ref.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/linear-test-ref.test.ts"],"names":[],"mappings":""}
@@ -1,81 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { resolveTestRef, softWrap } from '../commands/linear-test.js';
3
- describe('resolveTestRef', () => {
4
- it('takes a named issue verbatim, upper-cased', () => {
5
- expect(resolveTestRef('eng-42', {}, [])).toEqual({ id: 'ENG-42', source: 'argument' });
6
- });
7
- it('lets a named issue bypass the team_keys gate', () => {
8
- // Typing the ref is unambiguous in a way that finding it in a branch is not,
9
- // so `crosscheck linear-test ENG-42` works before team_keys is configured.
10
- expect(resolveTestRef('ENG-42', {}, [])).toEqual({ id: 'ENG-42', source: 'argument' });
11
- });
12
- it('prefers the named issue over anything inferable', () => {
13
- expect(resolveTestRef('ENG-1', { branch: 'feat/in-2269-x' }, ['IN']))
14
- .toEqual({ id: 'ENG-1', source: 'argument' });
15
- });
16
- it('falls back to the branch when no issue is named', () => {
17
- expect(resolveTestRef(undefined, { branch: 'feat/in-2269-x' }, ['IN']))
18
- .toEqual({ id: 'IN-2269', source: 'branch' });
19
- });
20
- it('falls back to the title', () => {
21
- expect(resolveTestRef(undefined, { title: 'IN-543: resolver' }, ['IN']))
22
- .toEqual({ id: 'IN-543', source: 'title' });
23
- });
24
- it('still honours the team_keys gate for inferred refs', () => {
25
- expect(resolveTestRef(undefined, { branch: 'feat/in-2269-x' }, [])).toBeNull();
26
- });
27
- it('returns null with nothing to go on', () => {
28
- expect(resolveTestRef(undefined, {}, ['IN'])).toBeNull();
29
- });
30
- it('treats a blank argument as absent', () => {
31
- expect(resolveTestRef(' ', { branch: 'feat/in-7-x' }, ['IN']))
32
- .toEqual({ id: 'IN-7', source: 'branch' });
33
- });
34
- });
35
- describe('softWrap', () => {
36
- it('leaves a short line alone', () => {
37
- expect(softWrap('short', 20)).toEqual(['short']);
38
- });
39
- it('wraps on whitespace at the boundary', () => {
40
- expect(softWrap('aaa bbb ccc ddd', 7)).toEqual(['aaa bbb', 'ccc ddd']);
41
- });
42
- it('never breaks a token, even one longer than the width', () => {
43
- const url = 'https://github.com/acme/app/pull/42';
44
- expect(softWrap(`see ${url} ok`, 10)).toEqual(['see', url, 'ok']);
45
- });
46
- it('wraps the annotation without splitting a field', () => {
47
- const line = '<!-- crosscheck: origin=claude reviewer=codex model=gpt-5.6-terra type=review round=1 verdict=NEEDS_WORK -->';
48
- for (const chunk of softWrap(line, 80))
49
- expect(chunk.length).toBeLessThanOrEqual(80);
50
- expect(softWrap(line, 80).join(' ')).toBe(line);
51
- });
52
- it('preserves content exactly when rejoined', () => {
53
- const line = 'the quick brown fox jumps over the lazy dog';
54
- expect(softWrap(line, 12).join(' ')).toBe(line);
55
- });
56
- });
57
- describe('onboard Linear decision — regression guards', () => {
58
- // These encode the two onboarding defects the recheck found. The prompt itself
59
- // needs a TTY, so these pin the decision rules the prompt implements.
60
- it('Enter must map to the current mode, not to off', () => {
61
- const decide = (answer, currentMode) => answer === '1' ? 'off'
62
- : answer === '2' ? 'api_key'
63
- : answer === '3' ? 'client_credentials'
64
- : currentMode;
65
- expect(decide('', 'client_credentials')).toBe('client_credentials');
66
- expect(decide('', 'api_key')).toBe('api_key');
67
- expect(decide('', 'off')).toBe('off');
68
- expect(decide('1', 'client_credentials')).toBe('off');
69
- expect(decide('2', 'off')).toBe('api_key');
70
- expect(decide('3', 'off')).toBe('client_credentials');
71
- });
72
- it('an explicit clear must be distinguishable from Enter', () => {
73
- const resolveKeys = (answer, current) => answer === '-' ? []
74
- : answer ? answer.split(',').map(k => k.trim().toUpperCase()).filter(Boolean)
75
- : current;
76
- expect(resolveKeys('', ['IN'])).toEqual(['IN']);
77
- expect(resolveKeys('-', ['IN'])).toEqual([]);
78
- expect(resolveKeys('eng,ops', ['IN'])).toEqual(['ENG', 'OPS']);
79
- });
80
- });
81
- //# sourceMappingURL=linear-test-ref.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"linear-test-ref.test.js","sourceRoot":"","sources":["../../src/__tests__/linear-test-ref.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=linear-verify.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"linear-verify.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/linear-verify.test.ts"],"names":[],"mappings":""}
@@ -1,132 +0,0 @@
1
- import { describe, it, expect, vi } from 'vitest';
2
- import { verifyLinearIdentity } from '../linear/verify.js';
3
- import { LinearConfigSchema } from '../config/schema.js';
4
- function cfg(overrides = {}) {
5
- return LinearConfigSchema.parse({ enabled: true, ...overrides });
6
- }
7
- const T1 = () => cfg({ auth: { mode: 'client_credentials' } });
8
- const T1_CREDS = { clientId: 'id', clientSecret: 'super-secret' };
9
- function json(payload, status = 200) {
10
- return new Response(JSON.stringify(payload), { status });
11
- }
12
- /** Mint replies first (T1 only), then the GraphQL probe. */
13
- function sequence(...responses) {
14
- let i = 0;
15
- return vi.fn(async () => responses[Math.min(i++, responses.length - 1)]);
16
- }
17
- describe('verifyLinearIdentity — T1 (client_credentials)', () => {
18
- it('reports app attribution when the minted token is accepted', async () => {
19
- const fetchImpl = sequence(json({ access_token: 'minted' }), json({ data: { organization: { name: 'Inductive Network' } } }));
20
- const report = await verifyLinearIdentity(T1(), T1_CREDS, { fetchImpl });
21
- expect(report).toMatchObject({
22
- ok: true,
23
- mode: 'client_credentials',
24
- actor: 'crosscheck',
25
- attribution: 'app',
26
- organization: 'Inductive Network',
27
- });
28
- // The resolved identity comes back so callers reuse it instead of minting again.
29
- expect(report.auth?.token).toBe('minted');
30
- });
31
- it('does not ask for a viewer — an app token has none', async () => {
32
- const fetchImpl = sequence(json({ access_token: 'minted' }), json({ data: { organization: { name: 'Acme' } } }));
33
- await verifyLinearIdentity(T1(), T1_CREDS, { fetchImpl });
34
- const probe = JSON.parse(fetchImpl.mock.calls[1][1].body);
35
- expect(probe.query).not.toContain('viewer');
36
- });
37
- it('reports failure when the mint is rejected', async () => {
38
- const fetchImpl = sequence(json({ error: 'invalid_client' }, 401));
39
- const report = await verifyLinearIdentity(T1(), T1_CREDS, { fetchImpl });
40
- expect(report.ok).toBe(false);
41
- expect(report.error).toContain('401');
42
- expect(report.attribution).toBe('app');
43
- });
44
- it('reports failure when credentials are missing, naming the env var', async () => {
45
- const report = await verifyLinearIdentity(T1(), {});
46
- expect(report.ok).toBe(false);
47
- expect(report.error).toContain('LINEAR_CLIENT_ID');
48
- });
49
- it('reports failure when the token is minted but rejected by the API', async () => {
50
- const fetchImpl = sequence(json({ access_token: 'minted' }), json({ errors: [{ message: 'Access denied' }] }));
51
- const report = await verifyLinearIdentity(T1(), T1_CREDS, { fetchImpl });
52
- expect(report.ok).toBe(false);
53
- expect(report.error).toContain('Access denied');
54
- });
55
- it('never leaks the secret or the token in an error', async () => {
56
- const fetchImpl = sequence(json({ error: 'bad' }, 500));
57
- const report = await verifyLinearIdentity(T1(), T1_CREDS, { fetchImpl });
58
- expect(report.error).not.toContain('super-secret');
59
- expect(report.error).not.toContain('id');
60
- });
61
- });
62
- describe('verifyLinearIdentity — T0 (api_key)', () => {
63
- it('names the human account writes will attribute to', async () => {
64
- const fetchImpl = sequence(json({ data: { viewer: { name: 'Yi', email: 'yi@example.com' }, organization: { name: 'Acme' } } }));
65
- const report = await verifyLinearIdentity(cfg(), { apiKey: 'lin_api_x' }, { fetchImpl });
66
- expect(report).toMatchObject({
67
- ok: true,
68
- mode: 'api_key',
69
- actor: 'crosscheck',
70
- attribution: 'user',
71
- organization: 'Acme',
72
- attributesTo: 'yi@example.com',
73
- });
74
- expect(report.auth?.mode).toBe('api_key');
75
- });
76
- it('falls back to the display name when there is no email', async () => {
77
- const fetchImpl = sequence(json({ data: { viewer: { name: 'Yi', email: null }, organization: { name: 'Acme' } } }));
78
- const report = await verifyLinearIdentity(cfg(), { apiKey: 'k' }, { fetchImpl });
79
- expect(report.attributesTo).toBe('Yi');
80
- });
81
- it('still succeeds when the viewer is absent', async () => {
82
- const fetchImpl = sequence(json({ data: { viewer: null, organization: { name: 'Acme' } } }));
83
- const report = await verifyLinearIdentity(cfg(), { apiKey: 'k' }, { fetchImpl });
84
- expect(report.ok).toBe(true);
85
- expect(report.attributesTo).toBeUndefined();
86
- });
87
- it('performs no mint', async () => {
88
- const fetchImpl = sequence(json({ data: { viewer: null, organization: { name: 'Acme' } } }));
89
- await verifyLinearIdentity(cfg(), { apiKey: 'k' }, { fetchImpl });
90
- const [url] = fetchImpl.mock.calls[0];
91
- expect(url).toBe('https://api.linear.app/graphql');
92
- });
93
- it('reports failure when the key is missing', async () => {
94
- const report = await verifyLinearIdentity(cfg(), {});
95
- expect(report.ok).toBe(false);
96
- expect(report.error).toContain('LINEAR_API_KEY');
97
- });
98
- it('never leaks the key in an error', async () => {
99
- const fetchImpl = sequence(json({ error: 'nope' }, 401));
100
- const report = await verifyLinearIdentity(cfg(), { apiKey: 'lin_api_secret_value' }, { fetchImpl });
101
- expect(report.error).not.toContain('lin_api_secret_value');
102
- });
103
- });
104
- describe('verifyLinearIdentity — contract', () => {
105
- it('never throws, whatever the transport does', async () => {
106
- const fetchImpl = vi.fn(async () => { throw new Error('ECONNREFUSED'); });
107
- const report = await verifyLinearIdentity(cfg(), { apiKey: 'k' }, { fetchImpl });
108
- expect(report.ok).toBe(false);
109
- expect(report.error).toContain('ECONNREFUSED');
110
- });
111
- it('reports the configured actor even when resolution fails', async () => {
112
- const report = await verifyLinearIdentity(cfg({ identity: { actor: 'acme-bot' } }), {});
113
- expect(report.actor).toBe('acme-bot');
114
- });
115
- });
116
- describe('the probe hands back its identity', () => {
117
- // linear-test resolved a second time for the issue lookup, minting a second
118
- // token — breaking one-token-per-run and letting a transient second mint fail a
119
- // dry run whose verification had already passed.
120
- it('returns the resolved auth on success', async () => {
121
- const fetchImpl = sequence(json({ data: { viewer: null, organization: { name: 'Acme' } } }));
122
- const report = await verifyLinearIdentity(cfg(), { apiKey: 'k' }, { fetchImpl });
123
- expect(report.auth).toBeDefined();
124
- expect(report.auth?.token).toBe('k');
125
- });
126
- it('omits it when resolution failed', async () => {
127
- const report = await verifyLinearIdentity(cfg(), {});
128
- expect(report.ok).toBe(false);
129
- expect(report.auth).toBeUndefined();
130
- });
131
- });
132
- //# sourceMappingURL=linear-verify.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"linear-verify.test.js","sourceRoot":"","sources":["../../src/__tests__/linear-verify.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAGxD,SAAS,GAAG,CAAC,YAAqC,EAAE;IAClD,OAAO,kBAAkB,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,SAAS,EAAE,CAAC,CAAA;AAClE,CAAC;AAED,MAAM,EAAE,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,oBAAoB,EAAE,EAAE,CAAC,CAAA;AAC9D,MAAM,QAAQ,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,EAAE,cAAc,EAAE,CAAA;AAEjE,SAAS,IAAI,CAAC,OAAgB,EAAE,MAAM,GAAG,GAAG;IAC1C,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,CAAA;AAC1D,CAAC;AAED,4DAA4D;AAC5D,SAAS,QAAQ,CAAC,GAAG,SAAqB;IACxC,IAAI,CAAC,GAAG,CAAC,CAAA;IACT,OAAO,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;AAC1E,CAAC;AAED,QAAQ,CAAC,gDAAgD,EAAE,GAAG,EAAE;IAC9D,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;QACzE,MAAM,SAAS,GAAG,QAAQ,CACxB,IAAI,CAAC,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC,EAChC,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,mBAAmB,EAAE,EAAE,EAAE,CAAC,CAChE,CAAA;QACD,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,SAAS,EAAE,CAAC,CAAA;QAExE,MAAM,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC;YAC3B,EAAE,EAAE,IAAI;YACR,IAAI,EAAE,oBAAoB;YAC1B,KAAK,EAAE,YAAY;YACnB,WAAW,EAAE,KAAK;YAClB,YAAY,EAAE,mBAAmB;SAClC,CAAC,CAAA;QACF,iFAAiF;QACjF,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IAC3C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;QACjE,MAAM,SAAS,GAAG,QAAQ,CACxB,IAAI,CAAC,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC,EAChC,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CACnD,CAAA;QACD,MAAM,oBAAoB,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,SAAS,EAAE,CAAC,CAAA;QAEzD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAE,SAAsC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAc,CAAC,CAAA;QACjG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAA;IAC7C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;QACzD,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,gBAAgB,EAAE,EAAE,GAAG,CAAC,CAAC,CAAA;QAClE,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,SAAS,EAAE,CAAC,CAAA;QAExE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC7B,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;QACrC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACxC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;QAChF,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAA;QAEnD,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC7B,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAA;IACpD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;QAChF,MAAM,SAAS,GAAG,QAAQ,CACxB,IAAI,CAAC,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC,EAChC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC,EAAE,CAAC,CACjD,CAAA;QACD,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,SAAS,EAAE,CAAC,CAAA;QAExE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC7B,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,CAAA;IACjD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;QAC/D,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,GAAG,CAAC,CAAC,CAAA;QACvD,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,SAAS,EAAE,CAAC,CAAA;QAExE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,cAAc,CAAC,CAAA;QAClD,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;IAC1C,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,qCAAqC,EAAE,GAAG,EAAE;IACnD,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;QAChE,MAAM,SAAS,GAAG,QAAQ,CACxB,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,gBAAgB,EAAE,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CACpG,CAAA;QACD,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,CAAA;QAExF,MAAM,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC;YAC3B,EAAE,EAAE,IAAI;YACR,IAAI,EAAE,SAAS;YACf,KAAK,EAAE,YAAY;YACnB,WAAW,EAAE,MAAM;YACnB,YAAY,EAAE,MAAM;YACpB,YAAY,EAAE,gBAAgB;SAC/B,CAAC,CAAA;QACF,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;IAC3C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;QACrE,MAAM,SAAS,GAAG,QAAQ,CACxB,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CACxF,CAAA;QACD,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,CAAA;QAChF,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACxC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;QACxD,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,CAAA;QAC5F,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,CAAA;QAEhF,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC5B,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,aAAa,EAAE,CAAA;IAC7C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kBAAkB,EAAE,KAAK,IAAI,EAAE;QAChC,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,CAAA;QAC5F,MAAM,oBAAoB,CAAC,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,CAAA;QAEjE,MAAM,CAAC,GAAG,CAAC,GAAI,SAAsC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;QACnE,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAA;IACpD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;QACvD,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,GAAG,EAAE,EAAE,EAAE,CAAC,CAAA;QAEpD,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC7B,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAA;IAClD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;QAC/C,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,GAAG,CAAC,CAAC,CAAA;QACxD,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE,sBAAsB,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,CAAA;QACnG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAA;IAC5D,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,iCAAiC,EAAE,GAAG,EAAE;IAC/C,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;QACzD,MAAM,SAAS,GAAc,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,GAAG,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,CAAA,CAAC,CAAC,CAAC,CAAA;QACnF,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,CAAA;QAEhF,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC7B,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,CAAA;IAChD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,yDAAyD,EAAE,KAAK,IAAI,EAAE;QACvE,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAA;QACvF,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IACvC,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,mCAAmC,EAAE,GAAG,EAAE;IACjD,4EAA4E;IAC5E,gFAAgF;IAChF,iDAAiD;IACjD,EAAE,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;QACpD,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,CAAA;QAC5F,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,CAAA;QAChF,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAA;QACjC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACtC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;QAC/C,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,GAAG,EAAE,EAAE,EAAE,CAAC,CAAA;QACpD,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC7B,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,CAAA;IACrC,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=linear-worker.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"linear-worker.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/linear-worker.test.ts"],"names":[],"mappings":""}