@skillsmith/core 0.5.4 → 0.5.5

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 (107) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/src/api/client.d.ts +4 -66
  4. package/dist/src/api/client.d.ts.map +1 -1
  5. package/dist/src/api/client.events.d.ts.map +1 -1
  6. package/dist/src/api/client.events.js +10 -1
  7. package/dist/src/api/client.events.js.map +1 -1
  8. package/dist/src/api/client.js +40 -66
  9. package/dist/src/api/client.js.map +1 -1
  10. package/dist/src/api/client.token-refresh.d.ts +3 -0
  11. package/dist/src/api/client.token-refresh.d.ts.map +1 -0
  12. package/dist/src/api/client.token-refresh.js +19 -0
  13. package/dist/src/api/client.token-refresh.js.map +1 -0
  14. package/dist/src/api/client.token-refresh.test.d.ts +2 -0
  15. package/dist/src/api/client.token-refresh.test.d.ts.map +1 -0
  16. package/dist/src/api/client.token-refresh.test.js +73 -0
  17. package/dist/src/api/client.token-refresh.test.js.map +1 -0
  18. package/dist/src/api/client.types.d.ts +2 -0
  19. package/dist/src/api/client.types.d.ts.map +1 -1
  20. package/dist/src/api/index.d.ts +1 -1
  21. package/dist/src/api/index.d.ts.map +1 -1
  22. package/dist/src/api/index.js +1 -1
  23. package/dist/src/api/index.js.map +1 -1
  24. package/dist/src/api/schemas.d.ts +319 -70
  25. package/dist/src/config/index.d.ts +4 -0
  26. package/dist/src/config/index.d.ts.map +1 -1
  27. package/dist/src/config/index.js +6 -0
  28. package/dist/src/config/index.js.map +1 -1
  29. package/dist/src/config/token-credentials.d.ts +13 -0
  30. package/dist/src/config/token-credentials.d.ts.map +1 -0
  31. package/dist/src/config/token-credentials.js +126 -0
  32. package/dist/src/config/token-credentials.js.map +1 -0
  33. package/dist/src/config/token-credentials.test.d.ts +10 -0
  34. package/dist/src/config/token-credentials.test.d.ts.map +1 -0
  35. package/dist/src/config/token-credentials.test.js +91 -0
  36. package/dist/src/config/token-credentials.test.js.map +1 -0
  37. package/dist/src/index.d.ts +4 -2
  38. package/dist/src/index.d.ts.map +1 -1
  39. package/dist/src/index.js +5 -2
  40. package/dist/src/index.js.map +1 -1
  41. package/dist/src/scripts/__tests__/scan-imported-skills.test.js +34 -5
  42. package/dist/src/scripts/__tests__/scan-imported-skills.test.js.map +1 -1
  43. package/dist/src/scripts/github-import/blocklist.d.ts +65 -0
  44. package/dist/src/scripts/github-import/blocklist.d.ts.map +1 -0
  45. package/dist/src/scripts/github-import/blocklist.js +124 -0
  46. package/dist/src/scripts/github-import/blocklist.js.map +1 -0
  47. package/dist/src/scripts/github-import/index.d.ts +1 -0
  48. package/dist/src/scripts/github-import/index.d.ts.map +1 -1
  49. package/dist/src/scripts/github-import/index.js +3 -0
  50. package/dist/src/scripts/github-import/index.js.map +1 -1
  51. package/dist/src/scripts/github-import/signal-of-intent.d.ts +87 -0
  52. package/dist/src/scripts/github-import/signal-of-intent.d.ts.map +1 -0
  53. package/dist/src/scripts/github-import/signal-of-intent.js +213 -0
  54. package/dist/src/scripts/github-import/signal-of-intent.js.map +1 -0
  55. package/dist/src/scripts/github-import/types.d.ts +22 -0
  56. package/dist/src/scripts/github-import/types.d.ts.map +1 -1
  57. package/dist/src/scripts/github-import/types.js.map +1 -1
  58. package/dist/src/scripts/import-github-skills.js +73 -3
  59. package/dist/src/scripts/import-github-skills.js.map +1 -1
  60. package/dist/src/scripts/skill-scanner/allowlist.d.ts +38 -0
  61. package/dist/src/scripts/skill-scanner/allowlist.d.ts.map +1 -0
  62. package/dist/src/scripts/skill-scanner/allowlist.js +178 -0
  63. package/dist/src/scripts/skill-scanner/allowlist.js.map +1 -0
  64. package/dist/src/scripts/skill-scanner/scanner.d.ts +10 -2
  65. package/dist/src/scripts/skill-scanner/scanner.d.ts.map +1 -1
  66. package/dist/src/scripts/skill-scanner/scanner.js +15 -3
  67. package/dist/src/scripts/skill-scanner/scanner.js.map +1 -1
  68. package/dist/src/scripts/skill-scanner/trust-scorer.d.ts +20 -6
  69. package/dist/src/scripts/skill-scanner/trust-scorer.d.ts.map +1 -1
  70. package/dist/src/scripts/skill-scanner/trust-scorer.js +28 -9
  71. package/dist/src/scripts/skill-scanner/trust-scorer.js.map +1 -1
  72. package/dist/src/scripts/skill-scanner/types.d.ts +50 -0
  73. package/dist/src/scripts/skill-scanner/types.d.ts.map +1 -1
  74. package/dist/src/security/scanner/SecurityScanner.helpers.d.ts +18 -0
  75. package/dist/src/security/scanner/SecurityScanner.helpers.d.ts.map +1 -1
  76. package/dist/src/security/scanner/SecurityScanner.helpers.js +54 -6
  77. package/dist/src/security/scanner/SecurityScanner.helpers.js.map +1 -1
  78. package/dist/src/security/scanner/patterns.d.ts.map +1 -1
  79. package/dist/src/security/scanner/patterns.js +45 -5
  80. package/dist/src/security/scanner/patterns.js.map +1 -1
  81. package/dist/tests/api/client.events.test.d.ts +10 -0
  82. package/dist/tests/api/client.events.test.d.ts.map +1 -0
  83. package/dist/tests/api/client.events.test.js +85 -0
  84. package/dist/tests/api/client.events.test.js.map +1 -0
  85. package/dist/tests/github-import/blocklist.test.d.ts +15 -0
  86. package/dist/tests/github-import/blocklist.test.d.ts.map +1 -0
  87. package/dist/tests/github-import/blocklist.test.js +182 -0
  88. package/dist/tests/github-import/blocklist.test.js.map +1 -0
  89. package/dist/tests/github-import/signal-of-intent.test.d.ts +15 -0
  90. package/dist/tests/github-import/signal-of-intent.test.d.ts.map +1 -0
  91. package/dist/tests/github-import/signal-of-intent.test.js +171 -0
  92. package/dist/tests/github-import/signal-of-intent.test.js.map +1 -0
  93. package/dist/tests/security/scanner-regression-guard.test.d.ts +12 -0
  94. package/dist/tests/security/scanner-regression-guard.test.d.ts.map +1 -1
  95. package/dist/tests/security/scanner-regression-guard.test.js +15 -3
  96. package/dist/tests/security/scanner-regression-guard.test.js.map +1 -1
  97. package/dist/tests/security/scanner-wave2-fixtures.test.d.ts +12 -0
  98. package/dist/tests/security/scanner-wave2-fixtures.test.d.ts.map +1 -0
  99. package/dist/tests/security/scanner-wave2-fixtures.test.js +173 -0
  100. package/dist/tests/security/scanner-wave2-fixtures.test.js.map +1 -0
  101. package/dist/tests/security.test.js +1 -0
  102. package/dist/tests/security.test.js.map +1 -1
  103. package/dist/tests/skill-scanner/allowlist.test.d.ts +16 -0
  104. package/dist/tests/skill-scanner/allowlist.test.d.ts.map +1 -0
  105. package/dist/tests/skill-scanner/allowlist.test.js +332 -0
  106. package/dist/tests/skill-scanner/allowlist.test.js.map +1 -0
  107. package/package.json +1 -1
@@ -0,0 +1,182 @@
1
+ /**
2
+ * SMI-4408: Indexer blocklist tests.
3
+ *
4
+ * Covers:
5
+ * - Exact-match blocking (owner/name, case-sensitive)
6
+ * - Non-blocklisted repos pass through
7
+ * - Empty/missing blocklist file returns EMPTY_BLOCKLIST (no-op)
8
+ * - Schema validation: version=1, required fields, valid repo format, valid dates
9
+ * - Duplicate entries rejected at load
10
+ * - Malformed JSON rejected at load
11
+ * - Ship-it sanity check: data/indexer-blocklist.json parses and contains
12
+ * the 2 known-bad entries from SMI-4396 Wave 2 residuals.
13
+ */
14
+ import { describe, it, expect } from 'vitest';
15
+ import * as fs from 'fs';
16
+ import * as os from 'os';
17
+ import * as path from 'path';
18
+ import { buildBlocklist, EMPTY_BLOCKLIST, loadBlocklist, parseBlocklistFile, } from '../../src/scripts/github-import/blocklist.js';
19
+ const VALID_ENTRY = {
20
+ repo: 'vinayaksavle/UploadDownloadPDF',
21
+ reason: 'ASP.NET MVC tutorial, not a Claude skill',
22
+ addedBy: 'ryansmith108',
23
+ addedAt: '2026-04-21',
24
+ };
25
+ // ------------------------ matcher behavior ------------------------
26
+ describe('BlocklistMatcher (SMI-4408)', () => {
27
+ it('blocks exact-match owner/name (case-sensitive)', () => {
28
+ const matcher = buildBlocklist([VALID_ENTRY]);
29
+ expect(matcher.isBlocked('vinayaksavle/UploadDownloadPDF')).toBe(true);
30
+ });
31
+ it('does not block case-mismatched repo (exact match)', () => {
32
+ const matcher = buildBlocklist([VALID_ENTRY]);
33
+ expect(matcher.isBlocked('vinayaksavle/uploaddownloadpdf')).toBe(false);
34
+ expect(matcher.isBlocked('Vinayaksavle/UploadDownloadPDF')).toBe(false);
35
+ });
36
+ it('does not block non-blocklisted repos', () => {
37
+ const matcher = buildBlocklist([VALID_ENTRY]);
38
+ expect(matcher.isBlocked('anthropics/skills')).toBe(false);
39
+ expect(matcher.isBlocked('smith-horn/skill-image-pipeline')).toBe(false);
40
+ });
41
+ it('does not match partial strings (substring not allowed)', () => {
42
+ const matcher = buildBlocklist([VALID_ENTRY]);
43
+ expect(matcher.isBlocked('vinayaksavle/UploadDownloadPDF-extra')).toBe(false);
44
+ expect(matcher.isBlocked('other/vinayaksavle/UploadDownloadPDF')).toBe(false);
45
+ });
46
+ it('exposes entries() for audit-log output', () => {
47
+ const matcher = buildBlocklist([VALID_ENTRY]);
48
+ const entries = matcher.entries();
49
+ expect(entries).toHaveLength(1);
50
+ expect(entries[0]).toEqual(VALID_ENTRY);
51
+ });
52
+ it('EMPTY_BLOCKLIST blocks nothing', () => {
53
+ expect(EMPTY_BLOCKLIST.isBlocked('anything/at-all')).toBe(false);
54
+ expect(EMPTY_BLOCKLIST.entries()).toEqual([]);
55
+ });
56
+ });
57
+ // ------------------------ schema validation ------------------------
58
+ describe('parseBlocklistFile (SMI-4408)', () => {
59
+ const validFile = {
60
+ version: 1,
61
+ updatedAt: '2026-04-21',
62
+ blocked: [VALID_ENTRY],
63
+ };
64
+ it('parses a valid file', () => {
65
+ const result = parseBlocklistFile(validFile);
66
+ expect(result.version).toBe(1);
67
+ expect(result.updatedAt).toBe('2026-04-21');
68
+ expect(result.blocked).toHaveLength(1);
69
+ expect(result.blocked[0]).toEqual(VALID_ENTRY);
70
+ });
71
+ it('rejects non-object root', () => {
72
+ expect(() => parseBlocklistFile(null)).toThrow(/must be an object/i);
73
+ expect(() => parseBlocklistFile('string')).toThrow(/must be an object/i);
74
+ // Arrays pass typeof === 'object' but fail on missing `version` field.
75
+ expect(() => parseBlocklistFile([])).toThrow(/unsupported blocklist file version/i);
76
+ });
77
+ it('rejects unsupported version', () => {
78
+ expect(() => parseBlocklistFile({ ...validFile, version: 2 })).toThrow(/unsupported blocklist file version/i);
79
+ expect(() => parseBlocklistFile({ ...validFile, version: 0 })).toThrow(/unsupported blocklist file version/i);
80
+ });
81
+ it('rejects invalid updatedAt', () => {
82
+ expect(() => parseBlocklistFile({ ...validFile, updatedAt: '04/21/2026' })).toThrow(/updatedAt must be YYYY-MM-DD/i);
83
+ expect(() => parseBlocklistFile({ ...validFile, updatedAt: 42 })).toThrow(/updatedAt must be YYYY-MM-DD/i);
84
+ });
85
+ it('rejects blocked field when not an array', () => {
86
+ expect(() => parseBlocklistFile({ ...validFile, blocked: {} })).toThrow(/blocked must be an array/i);
87
+ });
88
+ it('rejects entry with missing required field', () => {
89
+ for (const field of ['repo', 'reason', 'addedBy', 'addedAt']) {
90
+ const badEntry = { ...VALID_ENTRY };
91
+ delete badEntry[field];
92
+ expect(() => parseBlocklistFile({ ...validFile, blocked: [badEntry] })).toThrow(new RegExp(`missing or empty required field: ${field}`, 'i'));
93
+ }
94
+ });
95
+ it('rejects entry with empty required field', () => {
96
+ expect(() => parseBlocklistFile({ ...validFile, blocked: [{ ...VALID_ENTRY, reason: '' }] })).toThrow(/missing or empty required field: reason/i);
97
+ });
98
+ it('rejects malformed repo string', () => {
99
+ const bad = ['no-slash', '/leading', 'trailing/', 'too/many/slashes', 'has spaces/ok'];
100
+ for (const repo of bad) {
101
+ expect(() => parseBlocklistFile({ ...validFile, blocked: [{ ...VALID_ENTRY, repo }] })).toThrow(/repo must be 'owner\/name'/i);
102
+ }
103
+ });
104
+ it('accepts GitHub-valid repo names with common punctuation', () => {
105
+ const good = ['foo/bar', 'foo-bar/baz.qux', 'Foo123/Bar_v2', 'org.name/repo-name'];
106
+ for (const repo of good) {
107
+ expect(() => parseBlocklistFile({ ...validFile, blocked: [{ ...VALID_ENTRY, repo }] })).not.toThrow();
108
+ }
109
+ });
110
+ it('rejects invalid addedAt format', () => {
111
+ expect(() => parseBlocklistFile({ ...validFile, blocked: [{ ...VALID_ENTRY, addedAt: 'yesterday' }] })).toThrow(/addedAt must be YYYY-MM-DD/i);
112
+ });
113
+ it('rejects duplicate repo entries', () => {
114
+ expect(() => parseBlocklistFile({
115
+ ...validFile,
116
+ blocked: [VALID_ENTRY, { ...VALID_ENTRY, addedAt: '2026-04-22' }],
117
+ })).toThrow(/duplicate entry: vinayaksavle\/UploadDownloadPDF/i);
118
+ });
119
+ it('non-object entry rejected with index', () => {
120
+ expect(() => parseBlocklistFile({ ...validFile, blocked: [VALID_ENTRY, 'string-entry'] })).toThrow(/entry #1 is not an object/i);
121
+ });
122
+ });
123
+ // ------------------------ loadBlocklist ------------------------
124
+ describe('loadBlocklist (SMI-4408)', () => {
125
+ it('returns EMPTY_BLOCKLIST when file is absent', () => {
126
+ const tmp = path.join(os.tmpdir(), `blocklist-absent-${Date.now()}.json`);
127
+ const matcher = loadBlocklist(tmp);
128
+ expect(matcher).toBe(EMPTY_BLOCKLIST);
129
+ expect(matcher.isBlocked('anything/at-all')).toBe(false);
130
+ });
131
+ it('throws on malformed JSON', () => {
132
+ const tmp = path.join(os.tmpdir(), `blocklist-malformed-${Date.now()}.json`);
133
+ fs.writeFileSync(tmp, '{ not valid json');
134
+ try {
135
+ expect(() => loadBlocklist(tmp)).toThrow(/is not valid JSON/i);
136
+ }
137
+ finally {
138
+ fs.unlinkSync(tmp);
139
+ }
140
+ });
141
+ it('throws on invalid schema', () => {
142
+ const tmp = path.join(os.tmpdir(), `blocklist-invalid-${Date.now()}.json`);
143
+ fs.writeFileSync(tmp, JSON.stringify({ version: 2, updatedAt: '2026-04-21', blocked: [] }));
144
+ try {
145
+ expect(() => loadBlocklist(tmp)).toThrow(/unsupported blocklist file version/i);
146
+ }
147
+ finally {
148
+ fs.unlinkSync(tmp);
149
+ }
150
+ });
151
+ it('loads a valid file', () => {
152
+ const tmp = path.join(os.tmpdir(), `blocklist-valid-${Date.now()}.json`);
153
+ fs.writeFileSync(tmp, JSON.stringify({
154
+ version: 1,
155
+ updatedAt: '2026-04-21',
156
+ blocked: [VALID_ENTRY],
157
+ }));
158
+ try {
159
+ const matcher = loadBlocklist(tmp);
160
+ expect(matcher.isBlocked('vinayaksavle/UploadDownloadPDF')).toBe(true);
161
+ expect(matcher.isBlocked('anthropics/skills')).toBe(false);
162
+ }
163
+ finally {
164
+ fs.unlinkSync(tmp);
165
+ }
166
+ });
167
+ });
168
+ // ------------------------ ship-it sanity ------------------------
169
+ describe('data/indexer-blocklist.json (ship-it sanity)', () => {
170
+ it('is parseable and contains the 2 SMI-4396 Wave 2 residuals', () => {
171
+ const filePath = path.resolve(__dirname, '../../../../data/indexer-blocklist.json');
172
+ const raw = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
173
+ const parsed = parseBlocklistFile(raw);
174
+ expect(parsed.blocked.length).toBe(2);
175
+ const repos = parsed.blocked.map((e) => e.repo).sort();
176
+ expect(repos).toEqual(['Sfedfcv/redesigned-pancake', 'vinayaksavle/UploadDownloadPDF'].sort());
177
+ // Each entry must carry a reason for audit trail.
178
+ expect(parsed.blocked.every((e) => e.reason.length > 0)).toBe(true);
179
+ expect(parsed.blocked.every((e) => e.addedBy.length > 0)).toBe(true);
180
+ });
181
+ });
182
+ //# sourceMappingURL=blocklist.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blocklist.test.js","sourceRoot":"","sources":["../../../tests/github-import/blocklist.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,KAAK,EAAE,MAAM,IAAI,CAAA;AACxB,OAAO,KAAK,EAAE,MAAM,IAAI,CAAA;AACxB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAE5B,OAAO,EACL,cAAc,EACd,eAAe,EACf,aAAa,EACb,kBAAkB,GACnB,MAAM,8CAA8C,CAAA;AAGrD,MAAM,WAAW,GAAmB;IAClC,IAAI,EAAE,gCAAgC;IACtC,MAAM,EAAE,0CAA0C;IAClD,OAAO,EAAE,cAAc;IACvB,OAAO,EAAE,YAAY;CACtB,CAAA;AAED,qEAAqE;AAErE,QAAQ,CAAC,6BAA6B,EAAE,GAAG,EAAE;IAC3C,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,MAAM,OAAO,GAAG,cAAc,CAAC,CAAC,WAAW,CAAC,CAAC,CAAA;QAC7C,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,gCAAgC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACxE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,OAAO,GAAG,cAAc,CAAC,CAAC,WAAW,CAAC,CAAC,CAAA;QAC7C,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,gCAAgC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACvE,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,gCAAgC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACzE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,OAAO,GAAG,cAAc,CAAC,CAAC,WAAW,CAAC,CAAC,CAAA;QAC7C,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC1D,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,iCAAiC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC1E,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAChE,MAAM,OAAO,GAAG,cAAc,CAAC,CAAC,WAAW,CAAC,CAAC,CAAA;QAC7C,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,sCAAsC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC7E,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,sCAAsC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC/E,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,OAAO,GAAG,cAAc,CAAC,CAAC,WAAW,CAAC,CAAC,CAAA;QAC7C,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,CAAA;QACjC,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;QAC/B,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAA;IACzC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;QACxC,MAAM,CAAC,eAAe,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAChE,MAAM,CAAC,eAAe,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;IAC/C,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,sEAAsE;AAEtE,QAAQ,CAAC,+BAA+B,EAAE,GAAG,EAAE;IAC7C,MAAM,SAAS,GAAG;QAChB,OAAO,EAAE,CAAC;QACV,SAAS,EAAE,YAAY;QACvB,OAAO,EAAE,CAAC,WAAW,CAAC;KACvB,CAAA;IAED,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,MAAM,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAA;QAC5C,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QAC9B,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;QAC3C,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;QACtC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAA;IAChD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACjC,MAAM,CAAC,GAAG,EAAE,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAA;QACpE,MAAM,CAAC,GAAG,EAAE,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAA;QACxE,uEAAuE;QACvE,MAAM,CAAC,GAAG,EAAE,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,qCAAqC,CAAC,CAAA;IACrF,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,CAAC,GAAG,EAAE,CAAC,kBAAkB,CAAC,EAAE,GAAG,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CACpE,qCAAqC,CACtC,CAAA;QACD,MAAM,CAAC,GAAG,EAAE,CAAC,kBAAkB,CAAC,EAAE,GAAG,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CACpE,qCAAqC,CACtC,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACnC,MAAM,CAAC,GAAG,EAAE,CAAC,kBAAkB,CAAC,EAAE,GAAG,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,OAAO,CACjF,+BAA+B,CAChC,CAAA;QACD,MAAM,CAAC,GAAG,EAAE,CAAC,kBAAkB,CAAC,EAAE,GAAG,SAAS,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CACvE,+BAA+B,CAChC,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,CAAC,GAAG,EAAE,CAAC,kBAAkB,CAAC,EAAE,GAAG,SAAS,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CACrE,2BAA2B,CAC5B,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,KAAK,MAAM,KAAK,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,CAAC,EAAE,CAAC;YAC7D,MAAM,QAAQ,GAAG,EAAE,GAAG,WAAW,EAA6B,CAAA;YAC9D,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAA;YACtB,MAAM,CAAC,GAAG,EAAE,CAAC,kBAAkB,CAAC,EAAE,GAAG,SAAS,EAAE,OAAO,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAC7E,IAAI,MAAM,CAAC,oCAAoC,KAAK,EAAE,EAAE,GAAG,CAAC,CAC7D,CAAA;QACH,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,CAAC,GAAG,EAAE,CACV,kBAAkB,CAAC,EAAE,GAAG,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE,GAAG,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,CAChF,CAAC,OAAO,CAAC,0CAA0C,CAAC,CAAA;IACvD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,GAAG,GAAG,CAAC,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,kBAAkB,EAAE,eAAe,CAAC,CAAA;QACtF,KAAK,MAAM,IAAI,IAAI,GAAG,EAAE,CAAC;YACvB,MAAM,CAAC,GAAG,EAAE,CACV,kBAAkB,CAAC,EAAE,GAAG,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE,GAAG,WAAW,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAC1E,CAAC,OAAO,CAAC,6BAA6B,CAAC,CAAA;QAC1C,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,MAAM,IAAI,GAAG,CAAC,SAAS,EAAE,iBAAiB,EAAE,eAAe,EAAE,oBAAoB,CAAC,CAAA;QAClF,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;YACxB,MAAM,CAAC,GAAG,EAAE,CACV,kBAAkB,CAAC,EAAE,GAAG,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE,GAAG,WAAW,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAC1E,CAAC,GAAG,CAAC,OAAO,EAAE,CAAA;QACjB,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;QACxC,MAAM,CAAC,GAAG,EAAE,CACV,kBAAkB,CAAC,EAAE,GAAG,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE,GAAG,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC,CAC1F,CAAC,OAAO,CAAC,6BAA6B,CAAC,CAAA;IAC1C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;QACxC,MAAM,CAAC,GAAG,EAAE,CACV,kBAAkB,CAAC;YACjB,GAAG,SAAS;YACZ,OAAO,EAAE,CAAC,WAAW,EAAE,EAAE,GAAG,WAAW,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC;SAClE,CAAC,CACH,CAAC,OAAO,CAAC,mDAAmD,CAAC,CAAA;IAChE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,GAAG,EAAE,CACV,kBAAkB,CAAC,EAAE,GAAG,SAAS,EAAE,OAAO,EAAE,CAAC,WAAW,EAAE,cAAc,CAAC,EAAE,CAAC,CAC7E,CAAC,OAAO,CAAC,4BAA4B,CAAC,CAAA;IACzC,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,kEAAkE;AAElE,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACxC,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,oBAAoB,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;QACzE,MAAM,OAAO,GAAG,aAAa,CAAC,GAAG,CAAC,CAAA;QAClC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA;QACrC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC1D,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;QAClC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,uBAAuB,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;QAC5E,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAA;QACzC,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAA;QAChE,CAAC;gBAAS,CAAC;YACT,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAA;QACpB,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;QAClC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,qBAAqB,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;QAC1E,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,YAAY,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,CAAA;QAC3F,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,qCAAqC,CAAC,CAAA;QACjF,CAAC;gBAAS,CAAC;YACT,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAA;QACpB,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAC5B,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,mBAAmB,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;QACxE,EAAE,CAAC,aAAa,CACd,GAAG,EACH,IAAI,CAAC,SAAS,CAAC;YACb,OAAO,EAAE,CAAC;YACV,SAAS,EAAE,YAAY;YACvB,OAAO,EAAE,CAAC,WAAW,CAAC;SACvB,CAAC,CACH,CAAA;QACD,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,aAAa,CAAC,GAAG,CAAC,CAAA;YAClC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,gCAAgC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACtE,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC5D,CAAC;gBAAS,CAAC;YACT,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAA;QACpB,CAAC;IACH,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,mEAAmE;AAEnE,QAAQ,CAAC,8CAA8C,EAAE,GAAG,EAAE;IAC5D,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,yCAAyC,CAAC,CAAA;QACnF,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAA;QAC1D,MAAM,MAAM,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAA;QACtC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACrC,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAA;QACtD,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,4BAA4B,EAAE,gCAAgC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;QAC9F,kDAAkD;QAClD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACnE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACtE,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * SMI-4415: Unit tests for the signal-of-intent gate.
3
+ *
4
+ * Fixture-driven verification of the Wave 0 admit/reject gate criteria:
5
+ * - ≥ 98% known-good admission (known-good.json, 10 entries → 100% expected)
6
+ * - ≥ 95% non-skill rejection (non-skills.json, 20 entries → 100% expected)
7
+ *
8
+ * Plus explicit regression guards:
9
+ * - Plan-review H4 floor: metadata-only skills must reject even at high score
10
+ * - Score-boundary: score === SIGNAL_THRESHOLD with structural signal admits,
11
+ * score === SIGNAL_THRESHOLD - 1 rejects
12
+ * - mcp-server-only: structural but below threshold → reject
13
+ */
14
+ export {};
15
+ //# sourceMappingURL=signal-of-intent.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signal-of-intent.test.d.ts","sourceRoot":"","sources":["../../../tests/github-import/signal-of-intent.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG"}
@@ -0,0 +1,171 @@
1
+ /**
2
+ * SMI-4415: Unit tests for the signal-of-intent gate.
3
+ *
4
+ * Fixture-driven verification of the Wave 0 admit/reject gate criteria:
5
+ * - ≥ 98% known-good admission (known-good.json, 10 entries → 100% expected)
6
+ * - ≥ 95% non-skill rejection (non-skills.json, 20 entries → 100% expected)
7
+ *
8
+ * Plus explicit regression guards:
9
+ * - Plan-review H4 floor: metadata-only skills must reject even at high score
10
+ * - Score-boundary: score === SIGNAL_THRESHOLD with structural signal admits,
11
+ * score === SIGNAL_THRESHOLD - 1 rejects
12
+ * - mcp-server-only: structural but below threshold → reject
13
+ */
14
+ import { describe, expect, it } from 'vitest';
15
+ import { readFileSync } from 'node:fs';
16
+ import { dirname, join } from 'node:path';
17
+ import { fileURLToPath } from 'node:url';
18
+ import { computeSignalScore, HIGH_TRUST_OWNERS, shouldIngest, SIGNAL_THRESHOLD, } from '../../src/scripts/github-import/signal-of-intent.js';
19
+ const __dirname = dirname(fileURLToPath(import.meta.url));
20
+ const FIXTURES_DIR = join(__dirname, 'fixtures');
21
+ function loadFixture(name) {
22
+ return JSON.parse(readFileSync(join(FIXTURES_DIR, name), 'utf-8'));
23
+ }
24
+ /**
25
+ * Minimal ImportedSkill shape for synthetic regression tests. Fields not
26
+ * relevant to scoring get benign defaults.
27
+ */
28
+ function makeSkill(partial) {
29
+ return {
30
+ id: partial.id ?? 'github/test/synthetic',
31
+ name: partial.name ?? 'synthetic',
32
+ description: partial.description ?? '',
33
+ author: partial.author ?? 'test',
34
+ repo_url: partial.repo_url ?? 'https://github.com/test/synthetic',
35
+ clone_url: partial.clone_url ?? 'https://github.com/test/synthetic.git',
36
+ stars: partial.stars ?? 0,
37
+ forks: partial.forks ?? 0,
38
+ topics: partial.topics ?? [],
39
+ language: partial.language ?? null,
40
+ license: partial.license ?? null,
41
+ created_at: partial.created_at ?? '2024-01-01T00:00:00Z',
42
+ updated_at: partial.updated_at ?? '2026-04-21T00:00:00Z',
43
+ source: partial.source ?? 'github',
44
+ query_type: partial.query_type ?? 'test',
45
+ imported_at: partial.imported_at ?? '2026-04-21T00:00:00Z',
46
+ };
47
+ }
48
+ describe('signal-of-intent gate', () => {
49
+ describe('known-good fixtures', () => {
50
+ const knownGood = loadFixture('known-good.json');
51
+ it('loads exactly 10 entries (Wave 0 sample size)', () => {
52
+ expect(knownGood).toHaveLength(10);
53
+ });
54
+ it.each(knownGood.map((s) => [s.id, s]))('admits %s', (_id, skill) => {
55
+ expect(shouldIngest(skill)).toBe(true);
56
+ });
57
+ it('hits 100% admit rate on Wave 0 fixture corpus', () => {
58
+ const admitted = knownGood.filter((s) => shouldIngest(s));
59
+ expect(admitted).toHaveLength(knownGood.length);
60
+ });
61
+ });
62
+ describe('non-skill fixtures', () => {
63
+ const nonSkills = loadFixture('non-skills.json');
64
+ it('loads exactly 20 entries (Wave 0 sample size)', () => {
65
+ expect(nonSkills).toHaveLength(20);
66
+ });
67
+ it.each(nonSkills.map((s) => [s.id, s]))('rejects %s', (_id, skill) => {
68
+ expect(shouldIngest(skill)).toBe(false);
69
+ });
70
+ it('hits 100% reject rate on Wave 0 fixture corpus', () => {
71
+ const admitted = nonSkills.filter((s) => shouldIngest(s));
72
+ expect(admitted).toHaveLength(0);
73
+ });
74
+ });
75
+ describe('structural-signal floor (plan-review H4)', () => {
76
+ it('rejects metadata-only skills even when total score exceeds threshold', () => {
77
+ // Every metadata signal fires: description(+2) + name(+2) + language(+1)
78
+ // + license(+1) + stars(+1) = 7, well above SIGNAL_THRESHOLD (4).
79
+ // But topics=[] and author not in HIGH_TRUST_OWNERS → no structural
80
+ // signal → shouldIngest MUST reject. This is the H4 regression guard.
81
+ const metadataOnly = makeSkill({
82
+ id: 'github/nobody/claude-skill',
83
+ name: 'claude-skill', // matches NAME_REGEX
84
+ description: 'A skill for anthropic claude-code users', // matches DESCRIPTION_REGEX
85
+ author: 'nobody', // NOT in HIGH_TRUST_OWNERS
86
+ topics: [], // no structural topic
87
+ language: 'TypeScript',
88
+ license: 'MIT',
89
+ stars: 500, // >= STARS_THRESHOLD
90
+ });
91
+ const { score, signals, hasStructuralSignal } = computeSignalScore(metadataOnly);
92
+ expect(score).toBeGreaterThan(SIGNAL_THRESHOLD);
93
+ expect(hasStructuralSignal).toBe(false);
94
+ expect(signals).toEqual(expect.arrayContaining([
95
+ 'description-match',
96
+ 'name-match',
97
+ 'language-match',
98
+ 'license-present',
99
+ 'stars-threshold',
100
+ ]));
101
+ expect(shouldIngest(metadataOnly)).toBe(false);
102
+ });
103
+ });
104
+ describe('boundary conditions', () => {
105
+ it('admits a structural skill whose score equals SIGNAL_THRESHOLD', () => {
106
+ // Structural topic alone = +4 (exactly SIGNAL_THRESHOLD).
107
+ const exactlyAtThreshold = makeSkill({
108
+ topics: ['claude-skill'], // +4, structural
109
+ // no other signals
110
+ });
111
+ const { score, hasStructuralSignal } = computeSignalScore(exactlyAtThreshold);
112
+ expect(score).toBe(SIGNAL_THRESHOLD);
113
+ expect(hasStructuralSignal).toBe(true);
114
+ expect(shouldIngest(exactlyAtThreshold)).toBe(true);
115
+ });
116
+ it('rejects a structural skill whose score is one below SIGNAL_THRESHOLD', () => {
117
+ // mcp-server (+1, structural) + license (+1) + stars (+1) = 3.
118
+ const justBelowThreshold = makeSkill({
119
+ topics: ['mcp-server'], // +1, structural
120
+ license: 'MIT', // +1
121
+ stars: 50, // +1
122
+ });
123
+ const { score, hasStructuralSignal } = computeSignalScore(justBelowThreshold);
124
+ expect(score).toBe(SIGNAL_THRESHOLD - 1);
125
+ expect(hasStructuralSignal).toBe(true);
126
+ expect(shouldIngest(justBelowThreshold)).toBe(false);
127
+ });
128
+ it('rejects mcp-server-only skills (structural but below threshold)', () => {
129
+ // Just the mcp-server topic, no other signals. score=1 < threshold.
130
+ const mcpOnly = makeSkill({ topics: ['mcp-server'] });
131
+ const { score, hasStructuralSignal } = computeSignalScore(mcpOnly);
132
+ expect(score).toBe(1);
133
+ expect(hasStructuralSignal).toBe(true);
134
+ expect(shouldIngest(mcpOnly)).toBe(false);
135
+ });
136
+ it('respects a caller-supplied threshold override', () => {
137
+ // Same mcp-server-only skill, but threshold lowered to 1 → admits.
138
+ const mcpOnly = makeSkill({ topics: ['mcp-server'] });
139
+ expect(shouldIngest(mcpOnly, 1)).toBe(true);
140
+ expect(shouldIngest(mcpOnly, 2)).toBe(false);
141
+ });
142
+ });
143
+ describe('HIGH_TRUST_OWNERS', () => {
144
+ it('admits trusted-owner skills with no topics (community marketplace case)', () => {
145
+ // `daymade/claude-code-skills` in Wave 0 R2: HIGH_TRUST_OWNERS entry,
146
+ // empty topics, would otherwise fail the structural floor. score = 5
147
+ // (owner alone) + metadata >= threshold.
148
+ const owner = Array.from(HIGH_TRUST_OWNERS)[0];
149
+ expect(owner).toBeDefined();
150
+ const trustedNoTopics = makeSkill({
151
+ author: owner,
152
+ topics: [],
153
+ description: 'claude skill',
154
+ name: 'claude-skill',
155
+ });
156
+ const { hasStructuralSignal, signals } = computeSignalScore(trustedNoTopics);
157
+ expect(hasStructuralSignal).toBe(true);
158
+ expect(signals).toContain('high-trust-owner');
159
+ expect(shouldIngest(trustedNoTopics)).toBe(true);
160
+ });
161
+ it('matches HIGH_TRUST_OWNERS case-insensitively', () => {
162
+ const skill = makeSkill({
163
+ author: 'ANTHROPICS', // uppercase
164
+ topics: [],
165
+ });
166
+ const { hasStructuralSignal } = computeSignalScore(skill);
167
+ expect(hasStructuralSignal).toBe(true);
168
+ });
169
+ });
170
+ });
171
+ //# sourceMappingURL=signal-of-intent.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signal-of-intent.test.js","sourceRoot":"","sources":["../../../tests/github-import/signal-of-intent.test.ts"],"names":[],"mappings":"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"}
@@ -6,7 +6,19 @@
6
6
  * pattern removal during refactoring.
7
7
  *
8
8
  * Baseline validated: 2026-04-03
9
+ * SMI-4396 Wave 2 (2026-04-21): adjusted baselines for FP-rate tuning.
10
+ * - SENSITIVE_PATH_PATTERNS: 12 → 14 (tightened bare-keyword patterns
11
+ * to require assignment/path/file-ext context, expanding some into
12
+ * multiple variants).
13
+ * - DATA_EXFILTRATION_PATTERNS: 20 → 21 (word-boundary `\bcloud\b` fix
14
+ * plus new key/secret upload detector to preserve attack-shape coverage).
15
+ * - PRIVILEGE_ESCALATION_PATTERNS: 23 → 25 (removed bare `/escalat(e|ion)/i`
16
+ * documentation-keyword trigger; added 3 contextual variants).
17
+ * - Additionally: 12 → 15 ends up at 15 after adding explicit /etc/passwd
18
+ * system-file coverage (offsets the bare-keyword tightening).
19
+ *
9
20
  * Reference: docs/internal/security/two-scanner-runbook.md
21
+ * docs/internal/implementation/smi-4396-imported-skills-security-triage.md
10
22
  */
11
23
  export {};
12
24
  //# sourceMappingURL=scanner-regression-guard.test.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"scanner-regression-guard.test.d.ts","sourceRoot":"","sources":["../../../tests/security/scanner-regression-guard.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}
1
+ {"version":3,"file":"scanner-regression-guard.test.d.ts","sourceRoot":"","sources":["../../../tests/security/scanner-regression-guard.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG"}
@@ -6,7 +6,19 @@
6
6
  * pattern removal during refactoring.
7
7
  *
8
8
  * Baseline validated: 2026-04-03
9
+ * SMI-4396 Wave 2 (2026-04-21): adjusted baselines for FP-rate tuning.
10
+ * - SENSITIVE_PATH_PATTERNS: 12 → 14 (tightened bare-keyword patterns
11
+ * to require assignment/path/file-ext context, expanding some into
12
+ * multiple variants).
13
+ * - DATA_EXFILTRATION_PATTERNS: 20 → 21 (word-boundary `\bcloud\b` fix
14
+ * plus new key/secret upload detector to preserve attack-shape coverage).
15
+ * - PRIVILEGE_ESCALATION_PATTERNS: 23 → 25 (removed bare `/escalat(e|ion)/i`
16
+ * documentation-keyword trigger; added 3 contextual variants).
17
+ * - Additionally: 12 → 15 ends up at 15 after adding explicit /etc/passwd
18
+ * system-file coverage (offsets the bare-keyword tightening).
19
+ *
9
20
  * Reference: docs/internal/security/two-scanner-runbook.md
21
+ * docs/internal/implementation/smi-4396-imported-skills-security-triage.md
10
22
  */
11
23
  import { describe, it, expect } from 'vitest';
12
24
  import { SecurityScanner, SENSITIVE_PATH_PATTERNS, JAILBREAK_PATTERNS, SUSPICIOUS_PATTERNS, SOCIAL_ENGINEERING_PATTERNS, PROMPT_LEAKING_PATTERNS, DATA_EXFILTRATION_PATTERNS, PRIVILEGE_ESCALATION_PATTERNS, SSRF_INSTRUCTION_PATTERNS, AI_DEFENCE_PATTERNS, PII_PATTERNS, } from '../../src/security/scanner/index.js';
@@ -16,13 +28,13 @@ import { SecurityScanner, SENSITIVE_PATH_PATTERNS, JAILBREAK_PATTERNS, SUSPICIOU
16
28
  * removing patterns requires updating this file with justification.
17
29
  */
18
30
  const BASELINE_PATTERN_COUNTS = {
19
- SENSITIVE_PATH_PATTERNS: 12,
31
+ SENSITIVE_PATH_PATTERNS: 15, // SMI-4396 Wave 2: 12 → 15 (bare-keyword tightened + /etc/passwd explicit)
20
32
  JAILBREAK_PATTERNS: 15,
21
33
  SUSPICIOUS_PATTERNS: 11,
22
34
  SOCIAL_ENGINEERING_PATTERNS: 12,
23
35
  PROMPT_LEAKING_PATTERNS: 14,
24
- DATA_EXFILTRATION_PATTERNS: 20,
25
- PRIVILEGE_ESCALATION_PATTERNS: 23,
36
+ DATA_EXFILTRATION_PATTERNS: 22, // SMI-4396 Wave 2: 20 → 22 (word-boundary + key-upload + verb-object prose)
37
+ PRIVILEGE_ESCALATION_PATTERNS: 25, // SMI-4396 Wave 2: 23 → 25 (-1 bare +3 contextual)
26
38
  SSRF_INSTRUCTION_PATTERNS: 13,
27
39
  AI_DEFENCE_PATTERNS: 16,
28
40
  PII_PATTERNS: 11,
@@ -1 +1 @@
1
- {"version":3,"file":"scanner-regression-guard.test.js","sourceRoot":"","sources":["../../../tests/security/scanner-regression-guard.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"scanner-regression-guard.test.js","sourceRoot":"","sources":["../../../tests/security/scanner-regression-guard.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EACL,eAAe,EACf,uBAAuB,EACvB,kBAAkB,EAClB,mBAAmB,EACnB,2BAA2B,EAC3B,uBAAuB,EACvB,0BAA0B,EAC1B,6BAA6B,EAC7B,yBAAyB,EACzB,mBAAmB,EACnB,YAAY,GACb,MAAM,qCAAqC,CAAA;AAE5C;;;;GAIG;AACH,MAAM,uBAAuB,GAAG;IAC9B,uBAAuB,EAAE,EAAE,EAAE,2EAA2E;IACxG,kBAAkB,EAAE,EAAE;IACtB,mBAAmB,EAAE,EAAE;IACvB,2BAA2B,EAAE,EAAE;IAC/B,uBAAuB,EAAE,EAAE;IAC3B,0BAA0B,EAAE,EAAE,EAAE,4EAA4E;IAC5G,6BAA6B,EAAE,EAAE,EAAE,mDAAmD;IACtF,yBAAyB,EAAE,EAAE;IAC7B,mBAAmB,EAAE,EAAE;IACvB,YAAY,EAAE,EAAE;CACR,CAAA;AAEV,QAAQ,CAAC,qCAAqC,EAAE,GAAG,EAAE;IACnD,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACvC,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;YACnE,MAAM,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAC3D,uBAAuB,CAAC,uBAAuB,CAChD,CAAA;QACH,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;YAC9D,MAAM,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,sBAAsB,CACtD,uBAAuB,CAAC,kBAAkB,CAC3C,CAAA;QACH,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;YAC/D,MAAM,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC,sBAAsB,CACvD,uBAAuB,CAAC,mBAAmB,CAC5C,CAAA;QACH,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;YACvE,MAAM,CAAC,2BAA2B,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAC/D,uBAAuB,CAAC,2BAA2B,CACpD,CAAA;QACH,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;YACnE,MAAM,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAC3D,uBAAuB,CAAC,uBAAuB,CAChD,CAAA;QACH,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,8DAA8D,EAAE,GAAG,EAAE;YACtE,MAAM,CAAC,0BAA0B,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAC9D,uBAAuB,CAAC,0BAA0B,CACnD,CAAA;QACH,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;YACzE,MAAM,CAAC,6BAA6B,CAAC,MAAM,CAAC,CAAC,sBAAsB,CACjE,uBAAuB,CAAC,6BAA6B,CACtD,CAAA;QACH,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;YACrE,MAAM,CAAC,yBAAyB,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAC7D,uBAAuB,CAAC,yBAAyB,CAClD,CAAA;QACH,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;YAC/D,MAAM,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC,sBAAsB,CACvD,uBAAuB,CAAC,mBAAmB,CAC5C,CAAA;QACH,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;YACxD,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAAC,uBAAuB,CAAC,YAAY,CAAC,CAAA;QAC1F,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,QAAQ,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAClD,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;YAC3C,MAAM,OAAO,GAAG,IAAI,eAAe,EAAE,CAAA;YACrC,MAAM,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAA;QAC/B,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;YAC5C,MAAM,OAAO,GAAG,IAAI,eAAe,EAAE,CAAA;YACrC,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,8BAA8B,CAAC,CAAA;YAEzE,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,SAAS,EAAE,YAAY,CAAC,CAAA;YACtD,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAA;YACvC,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,UAAU,CAAC,CAAA;YACzC,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,WAAW,CAAC,CAAA;YAC1C,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,eAAe,CAAC,CAAA;YAC9C,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACnD,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,sEAAsE,EAAE,GAAG,EAAE;YAC9E,MAAM,OAAO,GAAG,IAAI,eAAe,EAAE,CAAA;YACrC,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CACzB,WAAW,EACX,4DAA4D,CAC7D,CAAA;YAED,MAAM,YAAY,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAA;YACrE,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAA;QAChD,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;YAC1C,MAAM,OAAO,GAAG,IAAI,eAAe,EAAE,CAAA;YACrC,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CACzB,gBAAgB,EAChB,wDAAwD,CACzD,CAAA;YAED,MAAM,iBAAiB,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,CAAA;YAC/E,MAAM,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAA;QACrD,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,mFAAmF,EAAE,GAAG,EAAE;YAC3F,MAAM,OAAO,GAAG,IAAI,eAAe,EAAE,CAAA;YACrC,gEAAgE;YAChE,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,gBAAgB,EAAE,2CAA2C,CAAC,CAAA;YAE1F,MAAM,iBAAiB,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,YAAY,CAAC,CAAA;YAChF,MAAM,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAA;QACrD,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;YAC/C,MAAM,OAAO,GAAG,IAAI,eAAe,EAAE,CAAA;YACrC,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,4CAA4C,CAAC,CAAA;YAErF,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,CAAA;YACnE,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAA;QAC/C,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,sEAAsE,EAAE,GAAG,EAAE;YAC9E,MAAM,OAAO,GAAG,IAAI,eAAe,EAAE,CAAA;YACrC,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CACzB,gBAAgB,EAChB,8DAA8D,CAC/D,CAAA;YAED,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CACrC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,YAAY,IAAI,CAAC,CAAC,IAAI,KAAK,WAAW,CACzD,CAAA;YACD,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAA;QAC5C,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * SMI-4396 Wave 2 regression fixtures.
3
+ *
4
+ * Five FP-shape fixtures drawn from the 2026-04-21 baseline spot-check:
5
+ * each asserts the NEW scanner does NOT quarantine the skill on the shape
6
+ * that previously caused a CRITICAL/HIGH finding. One attack-shape
7
+ * fixture asserts the scanner DOES still trigger on the genuine
8
+ * "upload private keys to our cdn bucket" exfiltration pattern — keeps
9
+ * Wave 2's bcloud word-boundary from weakening real detection.
10
+ */
11
+ export {};
12
+ //# sourceMappingURL=scanner-wave2-fixtures.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner-wave2-fixtures.test.d.ts","sourceRoot":"","sources":["../../../tests/security/scanner-wave2-fixtures.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}